diff options
Diffstat (limited to 'drivers/input')
148 files changed, 8266 insertions, 2947 deletions
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index cd50c00ab20f..07c2cd43109c 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig | |||
| @@ -8,7 +8,7 @@ menu "Input device support" | |||
| 8 | config INPUT | 8 | config INPUT |
| 9 | tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED | 9 | tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED |
| 10 | default y | 10 | default y |
| 11 | ---help--- | 11 | help |
| 12 | Say Y here if you have any input device (mouse, keyboard, tablet, | 12 | Say Y here if you have any input device (mouse, keyboard, tablet, |
| 13 | joystick, steering wheel ...) connected to your system and want | 13 | joystick, steering wheel ...) connected to your system and want |
| 14 | it to be available to applications. This includes standard PS/2 | 14 | it to be available to applications. This includes standard PS/2 |
| @@ -27,8 +27,7 @@ if INPUT | |||
| 27 | 27 | ||
| 28 | config INPUT_FF_MEMLESS | 28 | config INPUT_FF_MEMLESS |
| 29 | tristate "Support for memoryless force-feedback devices" | 29 | tristate "Support for memoryless force-feedback devices" |
| 30 | default n | 30 | help |
| 31 | ---help--- | ||
| 32 | Say Y here if you have memoryless force-feedback input device | 31 | Say Y here if you have memoryless force-feedback input device |
| 33 | such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual | 32 | such as Logitech WingMan Force 3D, ThrustMaster FireStorm Dual |
| 34 | Power 2, or similar. You will also need to enable hardware-specific | 33 | Power 2, or similar. You will also need to enable hardware-specific |
| @@ -52,12 +51,25 @@ config INPUT_POLLDEV | |||
| 52 | To compile this driver as a module, choose M here: the | 51 | To compile this driver as a module, choose M here: the |
| 53 | module will be called input-polldev. | 52 | module will be called input-polldev. |
| 54 | 53 | ||
| 54 | config INPUT_SPARSEKMAP | ||
| 55 | tristate "Sparse keymap support library" | ||
| 56 | help | ||
| 57 | Say Y here if you are using a driver for an input | ||
| 58 | device that uses sparse keymap. This option is only | ||
| 59 | useful for out-of-tree drivers since in-tree drivers | ||
| 60 | select it automatically. | ||
| 61 | |||
| 62 | If unsure, say N. | ||
| 63 | |||
| 64 | To compile this driver as a module, choose M here: the | ||
| 65 | module will be called sparse-keymap. | ||
| 66 | |||
| 55 | comment "Userland interfaces" | 67 | comment "Userland interfaces" |
| 56 | 68 | ||
| 57 | config INPUT_MOUSEDEV | 69 | config INPUT_MOUSEDEV |
| 58 | tristate "Mouse interface" if EMBEDDED | 70 | tristate "Mouse interface" if EMBEDDED |
| 59 | default y | 71 | default y |
| 60 | ---help--- | 72 | help |
| 61 | Say Y here if you want your mouse to be accessible as char devices | 73 | Say Y here if you want your mouse to be accessible as char devices |
| 62 | 13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an | 74 | 13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an |
| 63 | emulated IntelliMouse Explorer PS/2 mouse. That way, all user space | 75 | emulated IntelliMouse Explorer PS/2 mouse. That way, all user space |
| @@ -73,7 +85,7 @@ config INPUT_MOUSEDEV_PSAUX | |||
| 73 | bool "Provide legacy /dev/psaux device" | 85 | bool "Provide legacy /dev/psaux device" |
| 74 | default y | 86 | default y |
| 75 | depends on INPUT_MOUSEDEV | 87 | depends on INPUT_MOUSEDEV |
| 76 | ---help--- | 88 | help |
| 77 | Say Y here if you want your mouse also be accessible as char device | 89 | Say Y here if you want your mouse also be accessible as char device |
| 78 | 10:1 - /dev/psaux. The data available through /dev/psaux is exactly | 90 | 10:1 - /dev/psaux. The data available through /dev/psaux is exactly |
| 79 | the same as the data from /dev/input/mice. | 91 | the same as the data from /dev/input/mice. |
| @@ -103,7 +115,7 @@ config INPUT_MOUSEDEV_SCREEN_Y | |||
| 103 | 115 | ||
| 104 | config INPUT_JOYDEV | 116 | config INPUT_JOYDEV |
| 105 | tristate "Joystick interface" | 117 | tristate "Joystick interface" |
| 106 | ---help--- | 118 | help |
| 107 | Say Y here if you want your joystick or gamepad to be | 119 | Say Y here if you want your joystick or gamepad to be |
| 108 | accessible as char device 13:0+ - /dev/input/jsX device. | 120 | accessible as char device 13:0+ - /dev/input/jsX device. |
| 109 | 121 | ||
| @@ -125,7 +137,7 @@ config INPUT_EVDEV | |||
| 125 | 137 | ||
| 126 | config INPUT_EVBUG | 138 | config INPUT_EVBUG |
| 127 | tristate "Event debugging" | 139 | tristate "Event debugging" |
| 128 | ---help--- | 140 | help |
| 129 | Say Y here if you have a problem with the input subsystem and | 141 | Say Y here if you have a problem with the input subsystem and |
| 130 | want all events (keypresses, mouse movements), to be output to | 142 | want all events (keypresses, mouse movements), to be output to |
| 131 | the system log. While this is useful for debugging, it's also | 143 | the system log. While this is useful for debugging, it's also |
| @@ -140,7 +152,7 @@ config INPUT_EVBUG | |||
| 140 | config INPUT_APMPOWER | 152 | config INPUT_APMPOWER |
| 141 | tristate "Input Power Event -> APM Bridge" if EMBEDDED | 153 | tristate "Input Power Event -> APM Bridge" if EMBEDDED |
| 142 | depends on INPUT && APM_EMULATION | 154 | depends on INPUT && APM_EMULATION |
| 143 | ---help--- | 155 | help |
| 144 | Say Y here if you want suspend key events to trigger a user | 156 | Say Y here if you want suspend key events to trigger a user |
| 145 | requested suspend through APM. This is useful on embedded | 157 | requested suspend through APM. This is useful on embedded |
| 146 | systems where such behaviour is desired without userspace | 158 | systems where such behaviour is desired without userspace |
| @@ -153,6 +165,7 @@ config XEN_KBDDEV_FRONTEND | |||
| 153 | tristate "Xen virtual keyboard and mouse support" | 165 | tristate "Xen virtual keyboard and mouse support" |
| 154 | depends on XEN_FBDEV_FRONTEND | 166 | depends on XEN_FBDEV_FRONTEND |
| 155 | default y | 167 | default y |
| 168 | select XEN_XENBUS_FRONTEND | ||
| 156 | help | 169 | help |
| 157 | This driver implements the front-end of the Xen virtual | 170 | This driver implements the front-end of the Xen virtual |
| 158 | keyboard and mouse device driver. It communicates with a back-end | 171 | keyboard and mouse device driver. It communicates with a back-end |
diff --git a/drivers/input/Makefile b/drivers/input/Makefile index 4c9c745a7020..7ad212d31f99 100644 --- a/drivers/input/Makefile +++ b/drivers/input/Makefile | |||
| @@ -9,6 +9,7 @@ input-core-objs := input.o input-compat.o ff-core.o | |||
| 9 | 9 | ||
| 10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o | 10 | obj-$(CONFIG_INPUT_FF_MEMLESS) += ff-memless.o |
| 11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o | 11 | obj-$(CONFIG_INPUT_POLLDEV) += input-polldev.o |
| 12 | obj-$(CONFIG_INPUT_SPARSEKMAP) += sparse-keymap.o | ||
| 12 | 13 | ||
| 13 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o | 14 | obj-$(CONFIG_INPUT_MOUSEDEV) += mousedev.o |
| 14 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o | 15 | obj-$(CONFIG_INPUT_JOYDEV) += joydev.o |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index dee6706038aa..2ee6c7a68bdc 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -59,7 +59,8 @@ static void evdev_pass_event(struct evdev_client *client, | |||
| 59 | client->head &= EVDEV_BUFFER_SIZE - 1; | 59 | client->head &= EVDEV_BUFFER_SIZE - 1; |
| 60 | spin_unlock(&client->buffer_lock); | 60 | spin_unlock(&client->buffer_lock); |
| 61 | 61 | ||
| 62 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | 62 | if (event->type == EV_SYN) |
| 63 | kill_fasync(&client->fasync, SIGIO, POLL_IN); | ||
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | /* | 66 | /* |
| @@ -277,6 +278,8 @@ static int evdev_open(struct inode *inode, struct file *file) | |||
| 277 | goto err_free_client; | 278 | goto err_free_client; |
| 278 | 279 | ||
| 279 | file->private_data = client; | 280 | file->private_data = client; |
| 281 | nonseekable_open(inode, file); | ||
| 282 | |||
| 280 | return 0; | 283 | return 0; |
| 281 | 284 | ||
| 282 | err_free_client: | 285 | err_free_client: |
| @@ -512,7 +515,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
| 512 | struct input_absinfo abs; | 515 | struct input_absinfo abs; |
| 513 | struct ff_effect effect; | 516 | struct ff_effect effect; |
| 514 | int __user *ip = (int __user *)p; | 517 | int __user *ip = (int __user *)p; |
| 515 | int i, t, u, v; | 518 | unsigned int i, t, u, v; |
| 516 | int error; | 519 | int error; |
| 517 | 520 | ||
| 518 | switch (cmd) { | 521 | switch (cmd) { |
diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 38df81fcdc3a..03078c08309a 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
| 31 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
| 32 | #include <linux/slab.h> | ||
| 32 | 33 | ||
| 33 | /* | 34 | /* |
| 34 | * Check that the effect_id is a valid effect and whether the user | 35 | * Check that the effect_id is a valid effect and whether the user |
| @@ -353,7 +354,7 @@ int input_ff_create(struct input_dev *dev, int max_effects) | |||
| 353 | EXPORT_SYMBOL_GPL(input_ff_create); | 354 | EXPORT_SYMBOL_GPL(input_ff_create); |
| 354 | 355 | ||
| 355 | /** | 356 | /** |
| 356 | * input_ff_free() - frees force feedback portion of input device | 357 | * input_ff_destroy() - frees force feedback portion of input device |
| 357 | * @dev: input device supporting force feedback | 358 | * @dev: input device supporting force feedback |
| 358 | * | 359 | * |
| 359 | * This function is only needed in error path as input core will | 360 | * This function is only needed in error path as input core will |
| @@ -369,6 +370,7 @@ void input_ff_destroy(struct input_dev *dev) | |||
| 369 | if (ff->destroy) | 370 | if (ff->destroy) |
| 370 | ff->destroy(ff); | 371 | ff->destroy(ff); |
| 371 | kfree(ff->private); | 372 | kfree(ff->private); |
| 373 | kfree(ff->effects); | ||
| 372 | kfree(ff); | 374 | kfree(ff); |
| 373 | dev->ff = NULL; | 375 | dev->ff = NULL; |
| 374 | } | 376 | } |
diff --git a/drivers/input/ff-memless.c b/drivers/input/ff-memless.c index b483b2995fa9..1d881c96ba8f 100644 --- a/drivers/input/ff-memless.c +++ b/drivers/input/ff-memless.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | 25 | ||
| 26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) | 26 | #define debug(format, arg...) pr_debug("ff-memless: " format "\n", ## arg) |
| 27 | 27 | ||
| 28 | #include <linux/slab.h> | ||
| 28 | #include <linux/input.h> | 29 | #include <linux/input.h> |
| 29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 30 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
| @@ -221,11 +222,27 @@ static int get_compatible_type(struct ff_device *ff, int effect_type) | |||
| 221 | } | 222 | } |
| 222 | 223 | ||
| 223 | /* | 224 | /* |
| 225 | * Only left/right direction should be used (under/over 0x8000) for | ||
| 226 | * forward/reverse motor direction (to keep calculation fast & simple). | ||
| 227 | */ | ||
| 228 | static u16 ml_calculate_direction(u16 direction, u16 force, | ||
| 229 | u16 new_direction, u16 new_force) | ||
| 230 | { | ||
| 231 | if (!force) | ||
| 232 | return new_direction; | ||
| 233 | if (!new_force) | ||
| 234 | return direction; | ||
| 235 | return (((u32)(direction >> 1) * force + | ||
| 236 | (new_direction >> 1) * new_force) / | ||
| 237 | (force + new_force)) << 1; | ||
| 238 | } | ||
| 239 | |||
| 240 | /* | ||
| 224 | * Combine two effects and apply gain. | 241 | * Combine two effects and apply gain. |
| 225 | */ | 242 | */ |
| 226 | static void ml_combine_effects(struct ff_effect *effect, | 243 | static void ml_combine_effects(struct ff_effect *effect, |
| 227 | struct ml_effect_state *state, | 244 | struct ml_effect_state *state, |
| 228 | unsigned int gain) | 245 | int gain) |
| 229 | { | 246 | { |
| 230 | struct ff_effect *new = state->effect; | 247 | struct ff_effect *new = state->effect; |
| 231 | unsigned int strong, weak, i; | 248 | unsigned int strong, weak, i; |
| @@ -252,8 +269,21 @@ static void ml_combine_effects(struct ff_effect *effect, | |||
| 252 | break; | 269 | break; |
| 253 | 270 | ||
| 254 | case FF_RUMBLE: | 271 | case FF_RUMBLE: |
| 255 | strong = new->u.rumble.strong_magnitude * gain / 0xffff; | 272 | strong = (u32)new->u.rumble.strong_magnitude * gain / 0xffff; |
| 256 | weak = new->u.rumble.weak_magnitude * gain / 0xffff; | 273 | weak = (u32)new->u.rumble.weak_magnitude * gain / 0xffff; |
| 274 | |||
| 275 | if (effect->u.rumble.strong_magnitude + strong) | ||
| 276 | effect->direction = ml_calculate_direction( | ||
| 277 | effect->direction, | ||
| 278 | effect->u.rumble.strong_magnitude, | ||
| 279 | new->direction, strong); | ||
| 280 | else if (effect->u.rumble.weak_magnitude + weak) | ||
| 281 | effect->direction = ml_calculate_direction( | ||
| 282 | effect->direction, | ||
| 283 | effect->u.rumble.weak_magnitude, | ||
| 284 | new->direction, weak); | ||
| 285 | else | ||
| 286 | effect->direction = 0; | ||
| 257 | effect->u.rumble.strong_magnitude = | 287 | effect->u.rumble.strong_magnitude = |
| 258 | min(strong + effect->u.rumble.strong_magnitude, | 288 | min(strong + effect->u.rumble.strong_magnitude, |
| 259 | 0xffffU); | 289 | 0xffffU); |
| @@ -268,6 +298,13 @@ static void ml_combine_effects(struct ff_effect *effect, | |||
| 268 | /* here we also scale it 0x7fff => 0xffff */ | 298 | /* here we also scale it 0x7fff => 0xffff */ |
| 269 | i = i * gain / 0x7fff; | 299 | i = i * gain / 0x7fff; |
| 270 | 300 | ||
| 301 | if (effect->u.rumble.strong_magnitude + i) | ||
| 302 | effect->direction = ml_calculate_direction( | ||
| 303 | effect->direction, | ||
| 304 | effect->u.rumble.strong_magnitude, | ||
| 305 | new->direction, i); | ||
| 306 | else | ||
| 307 | effect->direction = 0; | ||
| 271 | effect->u.rumble.strong_magnitude = | 308 | effect->u.rumble.strong_magnitude = |
| 272 | min(i + effect->u.rumble.strong_magnitude, 0xffffU); | 309 | min(i + effect->u.rumble.strong_magnitude, 0xffffU); |
| 273 | effect->u.rumble.weak_magnitude = | 310 | effect->u.rumble.weak_magnitude = |
| @@ -411,8 +448,6 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
| 411 | msecs_to_jiffies(state->effect->replay.length); | 448 | msecs_to_jiffies(state->effect->replay.length); |
| 412 | state->adj_at = state->play_at; | 449 | state->adj_at = state->play_at; |
| 413 | 450 | ||
| 414 | ml_schedule_timer(ml); | ||
| 415 | |||
| 416 | } else { | 451 | } else { |
| 417 | debug("initiated stop"); | 452 | debug("initiated stop"); |
| 418 | 453 | ||
| @@ -420,10 +455,10 @@ static int ml_ff_playback(struct input_dev *dev, int effect_id, int value) | |||
| 420 | __set_bit(FF_EFFECT_ABORTING, &state->flags); | 455 | __set_bit(FF_EFFECT_ABORTING, &state->flags); |
| 421 | else | 456 | else |
| 422 | __clear_bit(FF_EFFECT_STARTED, &state->flags); | 457 | __clear_bit(FF_EFFECT_STARTED, &state->flags); |
| 423 | |||
| 424 | ml_play_effects(ml); | ||
| 425 | } | 458 | } |
| 426 | 459 | ||
| 460 | ml_play_effects(ml); | ||
| 461 | |||
| 427 | return 0; | 462 | return 0; |
| 428 | } | 463 | } |
| 429 | 464 | ||
diff --git a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c index b04930f7ea7d..7392992da424 100644 --- a/drivers/input/gameport/emu10k1-gp.c +++ b/drivers/input/gameport/emu10k1-gp.c | |||
| @@ -46,7 +46,7 @@ struct emu { | |||
| 46 | int size; | 46 | int size; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | static struct pci_device_id emu_tbl[] = { | 49 | static const struct pci_device_id emu_tbl[] = { |
| 50 | 50 | ||
| 51 | { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ | 51 | { 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */ |
| 52 | { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ | 52 | { 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */ |
diff --git a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c index 8a1810f88b9e..14d3f3e208a2 100644 --- a/drivers/input/gameport/fm801-gp.c +++ b/drivers/input/gameport/fm801-gp.c | |||
| @@ -140,7 +140,7 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci) | |||
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static struct pci_device_id fm801_gp_id_table[] = { | 143 | static const struct pci_device_id fm801_gp_id_table[] = { |
| 144 | { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, | 144 | { PCI_VENDOR_ID_FORTEMEDIA, PCI_DEVICE_ID_FM801_GP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
| 145 | { 0 } | 145 | { 0 } |
| 146 | }; | 146 | }; |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index ac11be08585e..7e18bcf05a66 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | * the Free Software Foundation. | 11 | * the Free Software Foundation. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 15 | |||
| 14 | #include <linux/stddef.h> | 16 | #include <linux/stddef.h> |
| 15 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 16 | #include <linux/ioport.h> | 18 | #include <linux/ioport.h> |
| @@ -190,9 +192,8 @@ static int gameport_bind_driver(struct gameport *gameport, struct gameport_drive | |||
| 190 | 192 | ||
| 191 | error = device_bind_driver(&gameport->dev); | 193 | error = device_bind_driver(&gameport->dev); |
| 192 | if (error) { | 194 | if (error) { |
| 193 | printk(KERN_WARNING | 195 | dev_warn(&gameport->dev, |
| 194 | "gameport: device_bind_driver() failed " | 196 | "device_bind_driver() failed for %s (%s) and %s, error: %d\n", |
| 195 | "for %s (%s) and %s, error: %d\n", | ||
| 196 | gameport->phys, gameport->name, | 197 | gameport->phys, gameport->name, |
| 197 | drv->description, error); | 198 | drv->description, error); |
| 198 | drv->disconnect(gameport); | 199 | drv->disconnect(gameport); |
| @@ -209,9 +210,9 @@ static void gameport_find_driver(struct gameport *gameport) | |||
| 209 | 210 | ||
| 210 | error = device_attach(&gameport->dev); | 211 | error = device_attach(&gameport->dev); |
| 211 | if (error < 0) | 212 | if (error < 0) |
| 212 | printk(KERN_WARNING | 213 | dev_warn(&gameport->dev, |
| 213 | "gameport: device_attach() failed for %s (%s), error: %d\n", | 214 | "device_attach() failed for %s (%s), error: %d\n", |
| 214 | gameport->phys, gameport->name, error); | 215 | gameport->phys, gameport->name, error); |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | 218 | ||
| @@ -262,17 +263,14 @@ static int gameport_queue_event(void *object, struct module *owner, | |||
| 262 | 263 | ||
| 263 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); | 264 | event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC); |
| 264 | if (!event) { | 265 | if (!event) { |
| 265 | printk(KERN_ERR | 266 | pr_err("Not enough memory to queue event %d\n", event_type); |
| 266 | "gameport: Not enough memory to queue event %d\n", | ||
| 267 | event_type); | ||
| 268 | retval = -ENOMEM; | 267 | retval = -ENOMEM; |
| 269 | goto out; | 268 | goto out; |
| 270 | } | 269 | } |
| 271 | 270 | ||
| 272 | if (!try_module_get(owner)) { | 271 | if (!try_module_get(owner)) { |
| 273 | printk(KERN_WARNING | 272 | pr_warning("Can't get module reference, dropping event %d\n", |
| 274 | "gameport: Can't get module reference, dropping event %d\n", | 273 | event_type); |
| 275 | event_type); | ||
| 276 | kfree(event); | 274 | kfree(event); |
| 277 | retval = -EINVAL; | 275 | retval = -EINVAL; |
| 278 | goto out; | 276 | goto out; |
| @@ -298,14 +296,12 @@ static void gameport_free_event(struct gameport_event *event) | |||
| 298 | 296 | ||
| 299 | static void gameport_remove_duplicate_events(struct gameport_event *event) | 297 | static void gameport_remove_duplicate_events(struct gameport_event *event) |
| 300 | { | 298 | { |
| 301 | struct list_head *node, *next; | 299 | struct gameport_event *e, *next; |
| 302 | struct gameport_event *e; | ||
| 303 | unsigned long flags; | 300 | unsigned long flags; |
| 304 | 301 | ||
| 305 | spin_lock_irqsave(&gameport_event_lock, flags); | 302 | spin_lock_irqsave(&gameport_event_lock, flags); |
| 306 | 303 | ||
| 307 | list_for_each_safe(node, next, &gameport_event_list) { | 304 | list_for_each_entry_safe(e, next, &gameport_event_list, node) { |
| 308 | e = list_entry(node, struct gameport_event, node); | ||
| 309 | if (event->object == e->object) { | 305 | if (event->object == e->object) { |
| 310 | /* | 306 | /* |
| 311 | * If this event is of different type we should not | 307 | * If this event is of different type we should not |
| @@ -315,7 +311,7 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) | |||
| 315 | if (event->type != e->type) | 311 | if (event->type != e->type) |
| 316 | break; | 312 | break; |
| 317 | 313 | ||
| 318 | list_del_init(node); | 314 | list_del_init(&e->node); |
| 319 | gameport_free_event(e); | 315 | gameport_free_event(e); |
| 320 | } | 316 | } |
| 321 | } | 317 | } |
| @@ -325,23 +321,18 @@ static void gameport_remove_duplicate_events(struct gameport_event *event) | |||
| 325 | 321 | ||
| 326 | static struct gameport_event *gameport_get_event(void) | 322 | static struct gameport_event *gameport_get_event(void) |
| 327 | { | 323 | { |
| 328 | struct gameport_event *event; | 324 | struct gameport_event *event = NULL; |
| 329 | struct list_head *node; | ||
| 330 | unsigned long flags; | 325 | unsigned long flags; |
| 331 | 326 | ||
| 332 | spin_lock_irqsave(&gameport_event_lock, flags); | 327 | spin_lock_irqsave(&gameport_event_lock, flags); |
| 333 | 328 | ||
| 334 | if (list_empty(&gameport_event_list)) { | 329 | if (!list_empty(&gameport_event_list)) { |
| 335 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 330 | event = list_first_entry(&gameport_event_list, |
| 336 | return NULL; | 331 | struct gameport_event, node); |
| 332 | list_del_init(&event->node); | ||
| 337 | } | 333 | } |
| 338 | 334 | ||
| 339 | node = gameport_event_list.next; | ||
| 340 | event = list_entry(node, struct gameport_event, node); | ||
| 341 | list_del_init(node); | ||
| 342 | |||
| 343 | spin_unlock_irqrestore(&gameport_event_lock, flags); | 335 | spin_unlock_irqrestore(&gameport_event_lock, flags); |
| 344 | |||
| 345 | return event; | 336 | return event; |
| 346 | } | 337 | } |
| 347 | 338 | ||
| @@ -360,16 +351,14 @@ static void gameport_handle_event(void) | |||
| 360 | if ((event = gameport_get_event())) { | 351 | if ((event = gameport_get_event())) { |
| 361 | 352 | ||
| 362 | switch (event->type) { | 353 | switch (event->type) { |
| 363 | case GAMEPORT_REGISTER_PORT: | ||
| 364 | gameport_add_port(event->object); | ||
| 365 | break; | ||
| 366 | 354 | ||
| 367 | case GAMEPORT_ATTACH_DRIVER: | 355 | case GAMEPORT_REGISTER_PORT: |
| 368 | gameport_attach_driver(event->object); | 356 | gameport_add_port(event->object); |
| 369 | break; | 357 | break; |
| 370 | 358 | ||
| 371 | default: | 359 | case GAMEPORT_ATTACH_DRIVER: |
| 372 | break; | 360 | gameport_attach_driver(event->object); |
| 361 | break; | ||
| 373 | } | 362 | } |
| 374 | 363 | ||
| 375 | gameport_remove_duplicate_events(event); | 364 | gameport_remove_duplicate_events(event); |
| @@ -385,16 +374,14 @@ static void gameport_handle_event(void) | |||
| 385 | */ | 374 | */ |
| 386 | static void gameport_remove_pending_events(void *object) | 375 | static void gameport_remove_pending_events(void *object) |
| 387 | { | 376 | { |
| 388 | struct list_head *node, *next; | 377 | struct gameport_event *event, *next; |
| 389 | struct gameport_event *event; | ||
| 390 | unsigned long flags; | 378 | unsigned long flags; |
| 391 | 379 | ||
| 392 | spin_lock_irqsave(&gameport_event_lock, flags); | 380 | spin_lock_irqsave(&gameport_event_lock, flags); |
| 393 | 381 | ||
| 394 | list_for_each_safe(node, next, &gameport_event_list) { | 382 | list_for_each_entry_safe(event, next, &gameport_event_list, node) { |
| 395 | event = list_entry(node, struct gameport_event, node); | ||
| 396 | if (event->object == object) { | 383 | if (event->object == object) { |
| 397 | list_del_init(node); | 384 | list_del_init(&event->node); |
| 398 | gameport_free_event(event); | 385 | gameport_free_event(event); |
| 399 | } | 386 | } |
| 400 | } | 387 | } |
| @@ -441,7 +428,6 @@ static int gameport_thread(void *nothing) | |||
| 441 | kthread_should_stop() || !list_empty(&gameport_event_list)); | 428 | kthread_should_stop() || !list_empty(&gameport_event_list)); |
| 442 | } while (!kthread_should_stop()); | 429 | } while (!kthread_should_stop()); |
| 443 | 430 | ||
| 444 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); | ||
| 445 | return 0; | 431 | return 0; |
| 446 | } | 432 | } |
| 447 | 433 | ||
| @@ -453,6 +439,7 @@ static int gameport_thread(void *nothing) | |||
| 453 | static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf) | 439 | static ssize_t gameport_show_description(struct device *dev, struct device_attribute *attr, char *buf) |
| 454 | { | 440 | { |
| 455 | struct gameport *gameport = to_gameport_port(dev); | 441 | struct gameport *gameport = to_gameport_port(dev); |
| 442 | |||
| 456 | return sprintf(buf, "%s\n", gameport->name); | 443 | return sprintf(buf, "%s\n", gameport->name); |
| 457 | } | 444 | } |
| 458 | 445 | ||
| @@ -521,7 +508,8 @@ static void gameport_init_port(struct gameport *gameport) | |||
| 521 | 508 | ||
| 522 | mutex_init(&gameport->drv_mutex); | 509 | mutex_init(&gameport->drv_mutex); |
| 523 | device_initialize(&gameport->dev); | 510 | device_initialize(&gameport->dev); |
| 524 | dev_set_name(&gameport->dev, "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1); | 511 | dev_set_name(&gameport->dev, "gameport%lu", |
| 512 | (unsigned long)atomic_inc_return(&gameport_no) - 1); | ||
| 525 | gameport->dev.bus = &gameport_bus; | 513 | gameport->dev.bus = &gameport_bus; |
| 526 | gameport->dev.release = gameport_release_port; | 514 | gameport->dev.release = gameport_release_port; |
| 527 | if (gameport->parent) | 515 | if (gameport->parent) |
| @@ -550,19 +538,17 @@ static void gameport_add_port(struct gameport *gameport) | |||
| 550 | list_add_tail(&gameport->node, &gameport_list); | 538 | list_add_tail(&gameport->node, &gameport_list); |
| 551 | 539 | ||
| 552 | if (gameport->io) | 540 | if (gameport->io) |
| 553 | printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n", | 541 | dev_info(&gameport->dev, "%s is %s, io %#x, speed %dkHz\n", |
| 554 | gameport->name, gameport->phys, gameport->io, gameport->speed); | 542 | gameport->name, gameport->phys, gameport->io, gameport->speed); |
| 555 | else | 543 | else |
| 556 | printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n", | 544 | dev_info(&gameport->dev, "%s is %s, speed %dkHz\n", |
| 557 | gameport->name, gameport->phys, gameport->speed); | 545 | gameport->name, gameport->phys, gameport->speed); |
| 558 | 546 | ||
| 559 | error = device_add(&gameport->dev); | 547 | error = device_add(&gameport->dev); |
| 560 | if (error) | 548 | if (error) |
| 561 | printk(KERN_ERR | 549 | dev_err(&gameport->dev, |
| 562 | "gameport: device_add() failed for %s (%s), error: %d\n", | 550 | "device_add() failed for %s (%s), error: %d\n", |
| 563 | gameport->phys, gameport->name, error); | 551 | gameport->phys, gameport->name, error); |
| 564 | else | ||
| 565 | gameport->registered = 1; | ||
| 566 | } | 552 | } |
| 567 | 553 | ||
| 568 | /* | 554 | /* |
| @@ -584,10 +570,8 @@ static void gameport_destroy_port(struct gameport *gameport) | |||
| 584 | gameport->parent = NULL; | 570 | gameport->parent = NULL; |
| 585 | } | 571 | } |
| 586 | 572 | ||
| 587 | if (gameport->registered) { | 573 | if (device_is_registered(&gameport->dev)) |
| 588 | device_del(&gameport->dev); | 574 | device_del(&gameport->dev); |
| 589 | gameport->registered = 0; | ||
| 590 | } | ||
| 591 | 575 | ||
| 592 | list_del_init(&gameport->node); | 576 | list_del_init(&gameport->node); |
| 593 | 577 | ||
| @@ -705,8 +689,7 @@ static void gameport_attach_driver(struct gameport_driver *drv) | |||
| 705 | 689 | ||
| 706 | error = driver_attach(&drv->driver); | 690 | error = driver_attach(&drv->driver); |
| 707 | if (error) | 691 | if (error) |
| 708 | printk(KERN_ERR | 692 | pr_err("driver_attach() failed for %s, error: %d\n", |
| 709 | "gameport: driver_attach() failed for %s, error: %d\n", | ||
| 710 | drv->driver.name, error); | 693 | drv->driver.name, error); |
| 711 | } | 694 | } |
| 712 | 695 | ||
| @@ -727,8 +710,7 @@ int __gameport_register_driver(struct gameport_driver *drv, struct module *owner | |||
| 727 | 710 | ||
| 728 | error = driver_register(&drv->driver); | 711 | error = driver_register(&drv->driver); |
| 729 | if (error) { | 712 | if (error) { |
| 730 | printk(KERN_ERR | 713 | pr_err("driver_register() failed for %s, error: %d\n", |
| 731 | "gameport: driver_register() failed for %s, error: %d\n", | ||
| 732 | drv->driver.name, error); | 714 | drv->driver.name, error); |
| 733 | return error; | 715 | return error; |
| 734 | } | 716 | } |
| @@ -828,7 +810,7 @@ static int __init gameport_init(void) | |||
| 828 | 810 | ||
| 829 | error = bus_register(&gameport_bus); | 811 | error = bus_register(&gameport_bus); |
| 830 | if (error) { | 812 | if (error) { |
| 831 | printk(KERN_ERR "gameport: failed to register gameport bus, error: %d\n", error); | 813 | pr_err("failed to register gameport bus, error: %d\n", error); |
| 832 | return error; | 814 | return error; |
| 833 | } | 815 | } |
| 834 | 816 | ||
| @@ -836,7 +818,7 @@ static int __init gameport_init(void) | |||
| 836 | if (IS_ERR(gameport_task)) { | 818 | if (IS_ERR(gameport_task)) { |
| 837 | bus_unregister(&gameport_bus); | 819 | bus_unregister(&gameport_bus); |
| 838 | error = PTR_ERR(gameport_task); | 820 | error = PTR_ERR(gameport_task); |
| 839 | printk(KERN_ERR "gameport: Failed to start kgameportd, error: %d\n", error); | 821 | pr_err("Failed to start kgameportd, error: %d\n", error); |
| 840 | return error; | 822 | return error; |
| 841 | } | 823 | } |
| 842 | 824 | ||
diff --git a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c index 06ad36ed3483..85d6ee09f11f 100644 --- a/drivers/input/gameport/lightning.c +++ b/drivers/input/gameport/lightning.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 36 | #include <linux/gameport.h> | 36 | #include <linux/gameport.h> |
| 37 | #include <linux/slab.h> | ||
| 38 | 37 | ||
| 39 | #define L4_PORT 0x201 | 38 | #define L4_PORT 0x201 |
| 40 | #define L4_SELECT_ANALOG 0xa4 | 39 | #define L4_SELECT_ANALOG 0xa4 |
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index db556b71ddda..7c217848613e 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
| @@ -166,7 +166,7 @@ static int ns558_isa_probe(int io) | |||
| 166 | 166 | ||
| 167 | #ifdef CONFIG_PNP | 167 | #ifdef CONFIG_PNP |
| 168 | 168 | ||
| 169 | static struct pnp_device_id pnp_devids[] = { | 169 | static const struct pnp_device_id pnp_devids[] = { |
| 170 | { .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */ | 170 | { .id = "@P@0001", .driver_data = 0 }, /* ALS 100 */ |
| 171 | { .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */ | 171 | { .id = "@P@0020", .driver_data = 0 }, /* ALS 200 */ |
| 172 | { .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */ | 172 | { .id = "@P@1001", .driver_data = 0 }, /* ALS 100+ */ |
diff --git a/drivers/input/input-compat.h b/drivers/input/input-compat.h index 47cd9eaee66a..4d8ea32e8a00 100644 --- a/drivers/input/input-compat.h +++ b/drivers/input/input-compat.h | |||
| @@ -21,8 +21,6 @@ | |||
| 21 | you why the ifdefs are needed? Think about it again. -AK */ | 21 | you why the ifdefs are needed? Think about it again. -AK */ |
| 22 | #ifdef CONFIG_X86_64 | 22 | #ifdef CONFIG_X86_64 |
| 23 | # define INPUT_COMPAT_TEST is_compat_task() | 23 | # define INPUT_COMPAT_TEST is_compat_task() |
| 24 | #elif defined(CONFIG_IA64) | ||
| 25 | # define INPUT_COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current)) | ||
| 26 | #elif defined(CONFIG_S390) | 24 | #elif defined(CONFIG_S390) |
| 27 | # define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT) | 25 | # define INPUT_COMPAT_TEST test_thread_flag(TIF_31BIT) |
| 28 | #elif defined(CONFIG_MIPS) | 26 | #elif defined(CONFIG_MIPS) |
diff --git a/drivers/input/input-polldev.c b/drivers/input/input-polldev.c index 0d3ce7a50fb1..10c9b0a845f0 100644 --- a/drivers/input/input-polldev.c +++ b/drivers/input/input-polldev.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/jiffies.h> | 11 | #include <linux/jiffies.h> |
| 12 | #include <linux/slab.h> | ||
| 12 | #include <linux/mutex.h> | 13 | #include <linux/mutex.h> |
| 13 | #include <linux/input-polldev.h> | 14 | #include <linux/input-polldev.h> |
| 14 | 15 | ||
| @@ -56,14 +57,10 @@ static void input_polldev_stop_workqueue(void) | |||
| 56 | mutex_unlock(&polldev_mutex); | 57 | mutex_unlock(&polldev_mutex); |
| 57 | } | 58 | } |
| 58 | 59 | ||
| 59 | static void input_polled_device_work(struct work_struct *work) | 60 | static void input_polldev_queue_work(struct input_polled_dev *dev) |
| 60 | { | 61 | { |
| 61 | struct input_polled_dev *dev = | ||
| 62 | container_of(work, struct input_polled_dev, work.work); | ||
| 63 | unsigned long delay; | 62 | unsigned long delay; |
| 64 | 63 | ||
| 65 | dev->poll(dev); | ||
| 66 | |||
| 67 | delay = msecs_to_jiffies(dev->poll_interval); | 64 | delay = msecs_to_jiffies(dev->poll_interval); |
| 68 | if (delay >= HZ) | 65 | if (delay >= HZ) |
| 69 | delay = round_jiffies_relative(delay); | 66 | delay = round_jiffies_relative(delay); |
| @@ -71,6 +68,15 @@ static void input_polled_device_work(struct work_struct *work) | |||
| 71 | queue_delayed_work(polldev_wq, &dev->work, delay); | 68 | queue_delayed_work(polldev_wq, &dev->work, delay); |
| 72 | } | 69 | } |
| 73 | 70 | ||
| 71 | static void input_polled_device_work(struct work_struct *work) | ||
| 72 | { | ||
| 73 | struct input_polled_dev *dev = | ||
| 74 | container_of(work, struct input_polled_dev, work.work); | ||
| 75 | |||
| 76 | dev->poll(dev); | ||
| 77 | input_polldev_queue_work(dev); | ||
| 78 | } | ||
| 79 | |||
| 74 | static int input_open_polled_device(struct input_dev *input) | 80 | static int input_open_polled_device(struct input_dev *input) |
| 75 | { | 81 | { |
| 76 | struct input_polled_dev *dev = input_get_drvdata(input); | 82 | struct input_polled_dev *dev = input_get_drvdata(input); |
| @@ -80,11 +86,12 @@ static int input_open_polled_device(struct input_dev *input) | |||
| 80 | if (error) | 86 | if (error) |
| 81 | return error; | 87 | return error; |
| 82 | 88 | ||
| 83 | if (dev->flush) | 89 | if (dev->open) |
| 84 | dev->flush(dev); | 90 | dev->open(dev); |
| 85 | 91 | ||
| 86 | queue_delayed_work(polldev_wq, &dev->work, | 92 | /* Only start polling if polling is enabled */ |
| 87 | msecs_to_jiffies(dev->poll_interval)); | 93 | if (dev->poll_interval > 0) |
| 94 | queue_delayed_work(polldev_wq, &dev->work, 0); | ||
| 88 | 95 | ||
| 89 | return 0; | 96 | return 0; |
| 90 | } | 97 | } |
| @@ -94,9 +101,95 @@ static void input_close_polled_device(struct input_dev *input) | |||
| 94 | struct input_polled_dev *dev = input_get_drvdata(input); | 101 | struct input_polled_dev *dev = input_get_drvdata(input); |
| 95 | 102 | ||
| 96 | cancel_delayed_work_sync(&dev->work); | 103 | cancel_delayed_work_sync(&dev->work); |
| 104 | /* | ||
| 105 | * Clean up work struct to remove references to the workqueue. | ||
| 106 | * It may be destroyed by the next call. This causes problems | ||
| 107 | * at next device open-close in case of poll_interval == 0. | ||
| 108 | */ | ||
| 109 | INIT_DELAYED_WORK(&dev->work, dev->work.work.func); | ||
| 97 | input_polldev_stop_workqueue(); | 110 | input_polldev_stop_workqueue(); |
| 111 | |||
| 112 | if (dev->close) | ||
| 113 | dev->close(dev); | ||
| 98 | } | 114 | } |
| 99 | 115 | ||
| 116 | /* SYSFS interface */ | ||
| 117 | |||
| 118 | static ssize_t input_polldev_get_poll(struct device *dev, | ||
| 119 | struct device_attribute *attr, char *buf) | ||
| 120 | { | ||
| 121 | struct input_polled_dev *polldev = dev_get_drvdata(dev); | ||
| 122 | |||
| 123 | return sprintf(buf, "%d\n", polldev->poll_interval); | ||
| 124 | } | ||
| 125 | |||
| 126 | static ssize_t input_polldev_set_poll(struct device *dev, | ||
| 127 | struct device_attribute *attr, const char *buf, | ||
| 128 | size_t count) | ||
| 129 | { | ||
| 130 | struct input_polled_dev *polldev = dev_get_drvdata(dev); | ||
| 131 | struct input_dev *input = polldev->input; | ||
| 132 | unsigned long interval; | ||
| 133 | |||
| 134 | if (strict_strtoul(buf, 0, &interval)) | ||
| 135 | return -EINVAL; | ||
| 136 | |||
| 137 | if (interval < polldev->poll_interval_min) | ||
| 138 | return -EINVAL; | ||
| 139 | |||
| 140 | if (interval > polldev->poll_interval_max) | ||
| 141 | return -EINVAL; | ||
| 142 | |||
| 143 | mutex_lock(&input->mutex); | ||
| 144 | |||
| 145 | polldev->poll_interval = interval; | ||
| 146 | |||
| 147 | if (input->users) { | ||
| 148 | cancel_delayed_work_sync(&polldev->work); | ||
| 149 | if (polldev->poll_interval > 0) | ||
| 150 | input_polldev_queue_work(polldev); | ||
| 151 | } | ||
| 152 | |||
| 153 | mutex_unlock(&input->mutex); | ||
| 154 | |||
| 155 | return count; | ||
| 156 | } | ||
| 157 | |||
| 158 | static DEVICE_ATTR(poll, S_IRUGO | S_IWUSR, input_polldev_get_poll, | ||
| 159 | input_polldev_set_poll); | ||
| 160 | |||
| 161 | |||
| 162 | static ssize_t input_polldev_get_max(struct device *dev, | ||
| 163 | struct device_attribute *attr, char *buf) | ||
| 164 | { | ||
| 165 | struct input_polled_dev *polldev = dev_get_drvdata(dev); | ||
| 166 | |||
| 167 | return sprintf(buf, "%d\n", polldev->poll_interval_max); | ||
| 168 | } | ||
| 169 | |||
| 170 | static DEVICE_ATTR(max, S_IRUGO, input_polldev_get_max, NULL); | ||
| 171 | |||
| 172 | static ssize_t input_polldev_get_min(struct device *dev, | ||
| 173 | struct device_attribute *attr, char *buf) | ||
| 174 | { | ||
| 175 | struct input_polled_dev *polldev = dev_get_drvdata(dev); | ||
| 176 | |||
| 177 | return sprintf(buf, "%d\n", polldev->poll_interval_min); | ||
| 178 | } | ||
| 179 | |||
| 180 | static DEVICE_ATTR(min, S_IRUGO, input_polldev_get_min, NULL); | ||
| 181 | |||
| 182 | static struct attribute *sysfs_attrs[] = { | ||
| 183 | &dev_attr_poll.attr, | ||
| 184 | &dev_attr_max.attr, | ||
| 185 | &dev_attr_min.attr, | ||
| 186 | NULL | ||
| 187 | }; | ||
| 188 | |||
| 189 | static struct attribute_group input_polldev_attribute_group = { | ||
| 190 | .attrs = sysfs_attrs | ||
| 191 | }; | ||
| 192 | |||
| 100 | /** | 193 | /** |
| 101 | * input_allocate_polled_device - allocated memory polled device | 194 | * input_allocate_polled_device - allocated memory polled device |
| 102 | * | 195 | * |
| @@ -126,7 +219,7 @@ EXPORT_SYMBOL(input_allocate_polled_device); | |||
| 126 | * @dev: device to free | 219 | * @dev: device to free |
| 127 | * | 220 | * |
| 128 | * The function frees memory allocated for polling device and drops | 221 | * The function frees memory allocated for polling device and drops |
| 129 | * reference to the associated input device (if present). | 222 | * reference to the associated input device. |
| 130 | */ | 223 | */ |
| 131 | void input_free_polled_device(struct input_polled_dev *dev) | 224 | void input_free_polled_device(struct input_polled_dev *dev) |
| 132 | { | 225 | { |
| @@ -150,15 +243,38 @@ EXPORT_SYMBOL(input_free_polled_device); | |||
| 150 | int input_register_polled_device(struct input_polled_dev *dev) | 243 | int input_register_polled_device(struct input_polled_dev *dev) |
| 151 | { | 244 | { |
| 152 | struct input_dev *input = dev->input; | 245 | struct input_dev *input = dev->input; |
| 246 | int error; | ||
| 153 | 247 | ||
| 154 | input_set_drvdata(input, dev); | 248 | input_set_drvdata(input, dev); |
| 155 | INIT_DELAYED_WORK(&dev->work, input_polled_device_work); | 249 | INIT_DELAYED_WORK(&dev->work, input_polled_device_work); |
| 156 | if (!dev->poll_interval) | 250 | if (!dev->poll_interval) |
| 157 | dev->poll_interval = 500; | 251 | dev->poll_interval = 500; |
| 252 | if (!dev->poll_interval_max) | ||
| 253 | dev->poll_interval_max = dev->poll_interval; | ||
| 158 | input->open = input_open_polled_device; | 254 | input->open = input_open_polled_device; |
| 159 | input->close = input_close_polled_device; | 255 | input->close = input_close_polled_device; |
| 160 | 256 | ||
| 161 | return input_register_device(input); | 257 | error = input_register_device(input); |
| 258 | if (error) | ||
| 259 | return error; | ||
| 260 | |||
| 261 | error = sysfs_create_group(&input->dev.kobj, | ||
| 262 | &input_polldev_attribute_group); | ||
| 263 | if (error) { | ||
| 264 | input_unregister_device(input); | ||
| 265 | return error; | ||
| 266 | } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Take extra reference to the underlying input device so | ||
| 270 | * that it survives call to input_unregister_polled_device() | ||
| 271 | * and is deleted only after input_free_polled_device() | ||
| 272 | * has been invoked. This is needed to ease task of freeing | ||
| 273 | * sparse keymaps. | ||
| 274 | */ | ||
| 275 | input_get_device(input); | ||
| 276 | |||
| 277 | return 0; | ||
| 162 | } | 278 | } |
| 163 | EXPORT_SYMBOL(input_register_polled_device); | 279 | EXPORT_SYMBOL(input_register_polled_device); |
| 164 | 280 | ||
| @@ -169,13 +285,13 @@ EXPORT_SYMBOL(input_register_polled_device); | |||
| 169 | * The function unregisters previously registered polled input | 285 | * The function unregisters previously registered polled input |
| 170 | * device from input layer. Polling is stopped and device is | 286 | * device from input layer. Polling is stopped and device is |
| 171 | * ready to be freed with call to input_free_polled_device(). | 287 | * ready to be freed with call to input_free_polled_device(). |
| 172 | * Callers should not attempt to access dev->input pointer | ||
| 173 | * after calling this function. | ||
| 174 | */ | 288 | */ |
| 175 | void input_unregister_polled_device(struct input_polled_dev *dev) | 289 | void input_unregister_polled_device(struct input_polled_dev *dev) |
| 176 | { | 290 | { |
| 291 | sysfs_remove_group(&dev->input->dev.kobj, | ||
| 292 | &input_polldev_attribute_group); | ||
| 293 | |||
| 177 | input_unregister_device(dev->input); | 294 | input_unregister_device(dev->input); |
| 178 | dev->input = NULL; | ||
| 179 | } | 295 | } |
| 180 | EXPORT_SYMBOL(input_unregister_polled_device); | 296 | EXPORT_SYMBOL(input_unregister_polled_device); |
| 181 | 297 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 2266ecbfbc01..afd4e2b7658c 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
| 15 | #include <linux/input.h> | 15 | #include <linux/input.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | #include <linux/random.h> | 18 | #include <linux/random.h> |
| 18 | #include <linux/major.h> | 19 | #include <linux/major.h> |
| 19 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
| @@ -24,6 +25,7 @@ | |||
| 24 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 25 | #include <linux/rcupdate.h> | 26 | #include <linux/rcupdate.h> |
| 26 | #include <linux/smp_lock.h> | 27 | #include <linux/smp_lock.h> |
| 28 | #include "input-compat.h" | ||
| 27 | 29 | ||
| 28 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | 30 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); |
| 29 | MODULE_DESCRIPTION("Input core"); | 31 | MODULE_DESCRIPTION("Input core"); |
| @@ -45,6 +47,7 @@ static unsigned int input_abs_bypass_init_data[] __initdata = { | |||
| 45 | ABS_MT_TOOL_TYPE, | 47 | ABS_MT_TOOL_TYPE, |
| 46 | ABS_MT_BLOB_ID, | 48 | ABS_MT_BLOB_ID, |
| 47 | ABS_MT_TRACKING_ID, | 49 | ABS_MT_TRACKING_ID, |
| 50 | ABS_MT_PRESSURE, | ||
| 48 | 0 | 51 | 0 |
| 49 | }; | 52 | }; |
| 50 | static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; | 53 | static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; |
| @@ -85,12 +88,14 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) | |||
| 85 | } | 88 | } |
| 86 | 89 | ||
| 87 | /* | 90 | /* |
| 88 | * Pass event through all open handles. This function is called with | 91 | * Pass event first through all filters and then, if event has not been |
| 92 | * filtered out, through all open handles. This function is called with | ||
| 89 | * dev->event_lock held and interrupts disabled. | 93 | * dev->event_lock held and interrupts disabled. |
| 90 | */ | 94 | */ |
| 91 | static void input_pass_event(struct input_dev *dev, | 95 | static void input_pass_event(struct input_dev *dev, |
| 92 | unsigned int type, unsigned int code, int value) | 96 | unsigned int type, unsigned int code, int value) |
| 93 | { | 97 | { |
| 98 | struct input_handler *handler; | ||
| 94 | struct input_handle *handle; | 99 | struct input_handle *handle; |
| 95 | 100 | ||
| 96 | rcu_read_lock(); | 101 | rcu_read_lock(); |
| @@ -98,11 +103,25 @@ static void input_pass_event(struct input_dev *dev, | |||
| 98 | handle = rcu_dereference(dev->grab); | 103 | handle = rcu_dereference(dev->grab); |
| 99 | if (handle) | 104 | if (handle) |
| 100 | handle->handler->event(handle, type, code, value); | 105 | handle->handler->event(handle, type, code, value); |
| 101 | else | 106 | else { |
| 102 | list_for_each_entry_rcu(handle, &dev->h_list, d_node) | 107 | bool filtered = false; |
| 103 | if (handle->open) | 108 | |
| 104 | handle->handler->event(handle, | 109 | list_for_each_entry_rcu(handle, &dev->h_list, d_node) { |
| 105 | type, code, value); | 110 | if (!handle->open) |
| 111 | continue; | ||
| 112 | |||
| 113 | handler = handle->handler; | ||
| 114 | if (!handler->filter) { | ||
| 115 | if (filtered) | ||
| 116 | break; | ||
| 117 | |||
| 118 | handler->event(handle, type, code, value); | ||
| 119 | |||
| 120 | } else if (handler->filter(handle, type, code, value)) | ||
| 121 | filtered = true; | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 106 | rcu_read_unlock(); | 125 | rcu_read_unlock(); |
| 107 | } | 126 | } |
| 108 | 127 | ||
| @@ -296,9 +315,15 @@ static void input_handle_event(struct input_dev *dev, | |||
| 296 | * @value: value of the event | 315 | * @value: value of the event |
| 297 | * | 316 | * |
| 298 | * This function should be used by drivers implementing various input | 317 | * This function should be used by drivers implementing various input |
| 299 | * devices. See also input_inject_event(). | 318 | * devices to report input events. See also input_inject_event(). |
| 319 | * | ||
| 320 | * NOTE: input_event() may be safely used right after input device was | ||
| 321 | * allocated with input_allocate_device(), even before it is registered | ||
| 322 | * with input_register_device(), but the event will not reach any of the | ||
| 323 | * input handlers. Such early invocation of input_event() may be used | ||
| 324 | * to 'seed' initial state of a switch or initial position of absolute | ||
| 325 | * axis, etc. | ||
| 300 | */ | 326 | */ |
| 301 | |||
| 302 | void input_event(struct input_dev *dev, | 327 | void input_event(struct input_dev *dev, |
| 303 | unsigned int type, unsigned int code, int value) | 328 | unsigned int type, unsigned int code, int value) |
| 304 | { | 329 | { |
| @@ -558,7 +583,8 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) | |||
| 558 | } | 583 | } |
| 559 | 584 | ||
| 560 | static int input_default_getkeycode(struct input_dev *dev, | 585 | static int input_default_getkeycode(struct input_dev *dev, |
| 561 | int scancode, int *keycode) | 586 | unsigned int scancode, |
| 587 | unsigned int *keycode) | ||
| 562 | { | 588 | { |
| 563 | if (!dev->keycodesize) | 589 | if (!dev->keycodesize) |
| 564 | return -EINVAL; | 590 | return -EINVAL; |
| @@ -572,7 +598,8 @@ static int input_default_getkeycode(struct input_dev *dev, | |||
| 572 | } | 598 | } |
| 573 | 599 | ||
| 574 | static int input_default_setkeycode(struct input_dev *dev, | 600 | static int input_default_setkeycode(struct input_dev *dev, |
| 575 | int scancode, int keycode) | 601 | unsigned int scancode, |
| 602 | unsigned int keycode) | ||
| 576 | { | 603 | { |
| 577 | int old_keycode; | 604 | int old_keycode; |
| 578 | int i; | 605 | int i; |
| @@ -607,12 +634,12 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
| 607 | } | 634 | } |
| 608 | } | 635 | } |
| 609 | 636 | ||
| 610 | clear_bit(old_keycode, dev->keybit); | 637 | __clear_bit(old_keycode, dev->keybit); |
| 611 | set_bit(keycode, dev->keybit); | 638 | __set_bit(keycode, dev->keybit); |
| 612 | 639 | ||
| 613 | for (i = 0; i < dev->keycodemax; i++) { | 640 | for (i = 0; i < dev->keycodemax; i++) { |
| 614 | if (input_fetch_keycode(dev, i) == old_keycode) { | 641 | if (input_fetch_keycode(dev, i) == old_keycode) { |
| 615 | set_bit(old_keycode, dev->keybit); | 642 | __set_bit(old_keycode, dev->keybit); |
| 616 | break; /* Setting the bit twice is useless, so break */ | 643 | break; /* Setting the bit twice is useless, so break */ |
| 617 | } | 644 | } |
| 618 | } | 645 | } |
| @@ -630,11 +657,9 @@ static int input_default_setkeycode(struct input_dev *dev, | |||
| 630 | * This function should be called by anyone interested in retrieving current | 657 | * This function should be called by anyone interested in retrieving current |
| 631 | * keymap. Presently keyboard and evdev handlers use it. | 658 | * keymap. Presently keyboard and evdev handlers use it. |
| 632 | */ | 659 | */ |
| 633 | int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) | 660 | int input_get_keycode(struct input_dev *dev, |
| 661 | unsigned int scancode, unsigned int *keycode) | ||
| 634 | { | 662 | { |
| 635 | if (scancode < 0) | ||
| 636 | return -EINVAL; | ||
| 637 | |||
| 638 | return dev->getkeycode(dev, scancode, keycode); | 663 | return dev->getkeycode(dev, scancode, keycode); |
| 639 | } | 664 | } |
| 640 | EXPORT_SYMBOL(input_get_keycode); | 665 | EXPORT_SYMBOL(input_get_keycode); |
| @@ -648,16 +673,14 @@ EXPORT_SYMBOL(input_get_keycode); | |||
| 648 | * This function should be called by anyone needing to update current | 673 | * This function should be called by anyone needing to update current |
| 649 | * keymap. Presently keyboard and evdev handlers use it. | 674 | * keymap. Presently keyboard and evdev handlers use it. |
| 650 | */ | 675 | */ |
| 651 | int input_set_keycode(struct input_dev *dev, int scancode, int keycode) | 676 | int input_set_keycode(struct input_dev *dev, |
| 677 | unsigned int scancode, unsigned int keycode) | ||
| 652 | { | 678 | { |
| 653 | unsigned long flags; | 679 | unsigned long flags; |
| 654 | int old_keycode; | 680 | int old_keycode; |
| 655 | int retval; | 681 | int retval; |
| 656 | 682 | ||
| 657 | if (scancode < 0) | 683 | if (keycode > KEY_MAX) |
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 661 | return -EINVAL; | 684 | return -EINVAL; |
| 662 | 685 | ||
| 663 | spin_lock_irqsave(&dev->event_lock, flags); | 686 | spin_lock_irqsave(&dev->event_lock, flags); |
| @@ -670,6 +693,9 @@ int input_set_keycode(struct input_dev *dev, int scancode, int keycode) | |||
| 670 | if (retval) | 693 | if (retval) |
| 671 | goto out; | 694 | goto out; |
| 672 | 695 | ||
| 696 | /* Make sure KEY_RESERVED did not get enabled. */ | ||
| 697 | __clear_bit(KEY_RESERVED, dev->keybit); | ||
| 698 | |||
| 673 | /* | 699 | /* |
| 674 | * Simulate keyup event if keycode is not present | 700 | * Simulate keyup event if keycode is not present |
| 675 | * in the keymap anymore | 701 | * in the keymap anymore |
| @@ -697,12 +723,13 @@ EXPORT_SYMBOL(input_set_keycode); | |||
| 697 | if (i != BITS_TO_LONGS(max)) \ | 723 | if (i != BITS_TO_LONGS(max)) \ |
| 698 | continue; | 724 | continue; |
| 699 | 725 | ||
| 700 | static const struct input_device_id *input_match_device(const struct input_device_id *id, | 726 | static const struct input_device_id *input_match_device(struct input_handler *handler, |
| 701 | struct input_dev *dev) | 727 | struct input_dev *dev) |
| 702 | { | 728 | { |
| 729 | const struct input_device_id *id; | ||
| 703 | int i; | 730 | int i; |
| 704 | 731 | ||
| 705 | for (; id->flags || id->driver_info; id++) { | 732 | for (id = handler->id_table; id->flags || id->driver_info; id++) { |
| 706 | 733 | ||
| 707 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) | 734 | if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) |
| 708 | if (id->bustype != dev->id.bustype) | 735 | if (id->bustype != dev->id.bustype) |
| @@ -730,7 +757,8 @@ static const struct input_device_id *input_match_device(const struct input_devic | |||
| 730 | MATCH_BIT(ffbit, FF_MAX); | 757 | MATCH_BIT(ffbit, FF_MAX); |
| 731 | MATCH_BIT(swbit, SW_MAX); | 758 | MATCH_BIT(swbit, SW_MAX); |
| 732 | 759 | ||
| 733 | return id; | 760 | if (!handler->match || handler->match(handler, dev)) |
| 761 | return id; | ||
| 734 | } | 762 | } |
| 735 | 763 | ||
| 736 | return NULL; | 764 | return NULL; |
| @@ -741,10 +769,7 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han | |||
| 741 | const struct input_device_id *id; | 769 | const struct input_device_id *id; |
| 742 | int error; | 770 | int error; |
| 743 | 771 | ||
| 744 | if (handler->blacklist && input_match_device(handler->blacklist, dev)) | 772 | id = input_match_device(handler, dev); |
| 745 | return -ENODEV; | ||
| 746 | |||
| 747 | id = input_match_device(handler->id_table, dev); | ||
| 748 | if (!id) | 773 | if (!id) |
| 749 | return -ENODEV; | 774 | return -ENODEV; |
| 750 | 775 | ||
| @@ -758,6 +783,40 @@ static int input_attach_handler(struct input_dev *dev, struct input_handler *han | |||
| 758 | return error; | 783 | return error; |
| 759 | } | 784 | } |
| 760 | 785 | ||
| 786 | #ifdef CONFIG_COMPAT | ||
| 787 | |||
| 788 | static int input_bits_to_string(char *buf, int buf_size, | ||
| 789 | unsigned long bits, bool skip_empty) | ||
| 790 | { | ||
| 791 | int len = 0; | ||
| 792 | |||
| 793 | if (INPUT_COMPAT_TEST) { | ||
| 794 | u32 dword = bits >> 32; | ||
| 795 | if (dword || !skip_empty) | ||
| 796 | len += snprintf(buf, buf_size, "%x ", dword); | ||
| 797 | |||
| 798 | dword = bits & 0xffffffffUL; | ||
| 799 | if (dword || !skip_empty || len) | ||
| 800 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
| 801 | "%x", dword); | ||
| 802 | } else { | ||
| 803 | if (bits || !skip_empty) | ||
| 804 | len += snprintf(buf, buf_size, "%lx", bits); | ||
| 805 | } | ||
| 806 | |||
| 807 | return len; | ||
| 808 | } | ||
| 809 | |||
| 810 | #else /* !CONFIG_COMPAT */ | ||
| 811 | |||
| 812 | static int input_bits_to_string(char *buf, int buf_size, | ||
| 813 | unsigned long bits, bool skip_empty) | ||
| 814 | { | ||
| 815 | return bits || !skip_empty ? | ||
| 816 | snprintf(buf, buf_size, "%lx", bits) : 0; | ||
| 817 | } | ||
| 818 | |||
| 819 | #endif | ||
| 761 | 820 | ||
| 762 | #ifdef CONFIG_PROC_FS | 821 | #ifdef CONFIG_PROC_FS |
| 763 | 822 | ||
| @@ -826,14 +885,25 @@ static void input_seq_print_bitmap(struct seq_file *seq, const char *name, | |||
| 826 | unsigned long *bitmap, int max) | 885 | unsigned long *bitmap, int max) |
| 827 | { | 886 | { |
| 828 | int i; | 887 | int i; |
| 829 | 888 | bool skip_empty = true; | |
| 830 | for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) | 889 | char buf[18]; |
| 831 | if (bitmap[i]) | ||
| 832 | break; | ||
| 833 | 890 | ||
| 834 | seq_printf(seq, "B: %s=", name); | 891 | seq_printf(seq, "B: %s=", name); |
| 835 | for (; i >= 0; i--) | 892 | |
| 836 | seq_printf(seq, "%lx%s", bitmap[i], i > 0 ? " " : ""); | 893 | for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { |
| 894 | if (input_bits_to_string(buf, sizeof(buf), | ||
| 895 | bitmap[i], skip_empty)) { | ||
| 896 | skip_empty = false; | ||
| 897 | seq_printf(seq, "%s%s", buf, i > 0 ? " " : ""); | ||
| 898 | } | ||
| 899 | } | ||
| 900 | |||
| 901 | /* | ||
| 902 | * If no output was produced print a single 0. | ||
| 903 | */ | ||
| 904 | if (skip_empty) | ||
| 905 | seq_puts(seq, "0"); | ||
| 906 | |||
| 837 | seq_putc(seq, '\n'); | 907 | seq_putc(seq, '\n'); |
| 838 | } | 908 | } |
| 839 | 909 | ||
| @@ -935,6 +1005,8 @@ static int input_handlers_seq_show(struct seq_file *seq, void *v) | |||
| 935 | union input_seq_state *state = (union input_seq_state *)&seq->private; | 1005 | union input_seq_state *state = (union input_seq_state *)&seq->private; |
| 936 | 1006 | ||
| 937 | seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); | 1007 | seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name); |
| 1008 | if (handler->filter) | ||
| 1009 | seq_puts(seq, " (filter)"); | ||
| 938 | if (handler->fops) | 1010 | if (handler->fops) |
| 939 | seq_printf(seq, " Minor=%d", handler->minor); | 1011 | seq_printf(seq, " Minor=%d", handler->minor); |
| 940 | seq_putc(seq, '\n'); | 1012 | seq_putc(seq, '\n'); |
| @@ -1122,14 +1194,23 @@ static int input_print_bitmap(char *buf, int buf_size, unsigned long *bitmap, | |||
| 1122 | { | 1194 | { |
| 1123 | int i; | 1195 | int i; |
| 1124 | int len = 0; | 1196 | int len = 0; |
| 1197 | bool skip_empty = true; | ||
| 1198 | |||
| 1199 | for (i = BITS_TO_LONGS(max) - 1; i >= 0; i--) { | ||
| 1200 | len += input_bits_to_string(buf + len, max(buf_size - len, 0), | ||
| 1201 | bitmap[i], skip_empty); | ||
| 1202 | if (len) { | ||
| 1203 | skip_empty = false; | ||
| 1204 | if (i > 0) | ||
| 1205 | len += snprintf(buf + len, max(buf_size - len, 0), " "); | ||
| 1206 | } | ||
| 1207 | } | ||
| 1125 | 1208 | ||
| 1126 | for (i = BITS_TO_LONGS(max) - 1; i > 0; i--) | 1209 | /* |
| 1127 | if (bitmap[i]) | 1210 | * If no output was produced print a single 0. |
| 1128 | break; | 1211 | */ |
| 1129 | 1212 | if (len == 0) | |
| 1130 | for (; i >= 0; i--) | 1213 | len = snprintf(buf, buf_size, "%d", 0); |
| 1131 | len += snprintf(buf + len, max(buf_size - len, 0), | ||
| 1132 | "%lx%s", bitmap[i], i > 0 ? " " : ""); | ||
| 1133 | 1214 | ||
| 1134 | if (add_cr) | 1215 | if (add_cr) |
| 1135 | len += snprintf(buf + len, max(buf_size - len, 0), "\n"); | 1216 | len += snprintf(buf + len, max(buf_size - len, 0), "\n"); |
| @@ -1144,7 +1225,8 @@ static ssize_t input_dev_show_cap_##bm(struct device *dev, \ | |||
| 1144 | { \ | 1225 | { \ |
| 1145 | struct input_dev *input_dev = to_input_dev(dev); \ | 1226 | struct input_dev *input_dev = to_input_dev(dev); \ |
| 1146 | int len = input_print_bitmap(buf, PAGE_SIZE, \ | 1227 | int len = input_print_bitmap(buf, PAGE_SIZE, \ |
| 1147 | input_dev->bm##bit, ev##_MAX, 1); \ | 1228 | input_dev->bm##bit, ev##_MAX, \ |
| 1229 | true); \ | ||
| 1148 | return min_t(int, len, PAGE_SIZE); \ | 1230 | return min_t(int, len, PAGE_SIZE); \ |
| 1149 | } \ | 1231 | } \ |
| 1150 | static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) | 1232 | static DEVICE_ATTR(bm, S_IRUGO, input_dev_show_cap_##bm, NULL) |
| @@ -1208,7 +1290,7 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env, | |||
| 1208 | 1290 | ||
| 1209 | len = input_print_bitmap(&env->buf[env->buflen - 1], | 1291 | len = input_print_bitmap(&env->buf[env->buflen - 1], |
| 1210 | sizeof(env->buf) - env->buflen, | 1292 | sizeof(env->buf) - env->buflen, |
| 1211 | bitmap, max, 0); | 1293 | bitmap, max, false); |
| 1212 | if (len >= (sizeof(env->buf) - env->buflen)) | 1294 | if (len >= (sizeof(env->buf) - env->buflen)) |
| 1213 | return -ENOMEM; | 1295 | return -ENOMEM; |
| 1214 | 1296 | ||
| @@ -1488,6 +1570,25 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int | |||
| 1488 | } | 1570 | } |
| 1489 | EXPORT_SYMBOL(input_set_capability); | 1571 | EXPORT_SYMBOL(input_set_capability); |
| 1490 | 1572 | ||
| 1573 | #define INPUT_CLEANSE_BITMASK(dev, type, bits) \ | ||
| 1574 | do { \ | ||
| 1575 | if (!test_bit(EV_##type, dev->evbit)) \ | ||
| 1576 | memset(dev->bits##bit, 0, \ | ||
| 1577 | sizeof(dev->bits##bit)); \ | ||
| 1578 | } while (0) | ||
| 1579 | |||
| 1580 | static void input_cleanse_bitmasks(struct input_dev *dev) | ||
| 1581 | { | ||
| 1582 | INPUT_CLEANSE_BITMASK(dev, KEY, key); | ||
| 1583 | INPUT_CLEANSE_BITMASK(dev, REL, rel); | ||
| 1584 | INPUT_CLEANSE_BITMASK(dev, ABS, abs); | ||
| 1585 | INPUT_CLEANSE_BITMASK(dev, MSC, msc); | ||
| 1586 | INPUT_CLEANSE_BITMASK(dev, LED, led); | ||
| 1587 | INPUT_CLEANSE_BITMASK(dev, SND, snd); | ||
| 1588 | INPUT_CLEANSE_BITMASK(dev, FF, ff); | ||
| 1589 | INPUT_CLEANSE_BITMASK(dev, SW, sw); | ||
| 1590 | } | ||
| 1591 | |||
| 1491 | /** | 1592 | /** |
| 1492 | * input_register_device - register device with input core | 1593 | * input_register_device - register device with input core |
| 1493 | * @dev: device to be registered | 1594 | * @dev: device to be registered |
| @@ -1507,13 +1608,19 @@ int input_register_device(struct input_dev *dev) | |||
| 1507 | const char *path; | 1608 | const char *path; |
| 1508 | int error; | 1609 | int error; |
| 1509 | 1610 | ||
| 1611 | /* Every input device generates EV_SYN/SYN_REPORT events. */ | ||
| 1510 | __set_bit(EV_SYN, dev->evbit); | 1612 | __set_bit(EV_SYN, dev->evbit); |
| 1511 | 1613 | ||
| 1614 | /* KEY_RESERVED is not supposed to be transmitted to userspace. */ | ||
| 1615 | __clear_bit(KEY_RESERVED, dev->keybit); | ||
| 1616 | |||
| 1617 | /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ | ||
| 1618 | input_cleanse_bitmasks(dev); | ||
| 1619 | |||
| 1512 | /* | 1620 | /* |
| 1513 | * If delay and period are pre-set by the driver, then autorepeating | 1621 | * If delay and period are pre-set by the driver, then autorepeating |
| 1514 | * is handled by the driver itself and we don't do it in input.c. | 1622 | * is handled by the driver itself and we don't do it in input.c. |
| 1515 | */ | 1623 | */ |
| 1516 | |||
| 1517 | init_timer(&dev->timer); | 1624 | init_timer(&dev->timer); |
| 1518 | if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { | 1625 | if (!dev->rep[REP_DELAY] && !dev->rep[REP_PERIOD]) { |
| 1519 | dev->timer.data = (long) dev; | 1626 | dev->timer.data = (long) dev; |
| @@ -1658,6 +1765,38 @@ void input_unregister_handler(struct input_handler *handler) | |||
| 1658 | EXPORT_SYMBOL(input_unregister_handler); | 1765 | EXPORT_SYMBOL(input_unregister_handler); |
| 1659 | 1766 | ||
| 1660 | /** | 1767 | /** |
| 1768 | * input_handler_for_each_handle - handle iterator | ||
| 1769 | * @handler: input handler to iterate | ||
| 1770 | * @data: data for the callback | ||
| 1771 | * @fn: function to be called for each handle | ||
| 1772 | * | ||
| 1773 | * Iterate over @bus's list of devices, and call @fn for each, passing | ||
| 1774 | * it @data and stop when @fn returns a non-zero value. The function is | ||
| 1775 | * using RCU to traverse the list and therefore may be usind in atonic | ||
| 1776 | * contexts. The @fn callback is invoked from RCU critical section and | ||
| 1777 | * thus must not sleep. | ||
| 1778 | */ | ||
| 1779 | int input_handler_for_each_handle(struct input_handler *handler, void *data, | ||
| 1780 | int (*fn)(struct input_handle *, void *)) | ||
| 1781 | { | ||
| 1782 | struct input_handle *handle; | ||
| 1783 | int retval = 0; | ||
| 1784 | |||
| 1785 | rcu_read_lock(); | ||
| 1786 | |||
| 1787 | list_for_each_entry_rcu(handle, &handler->h_list, h_node) { | ||
| 1788 | retval = fn(handle, data); | ||
| 1789 | if (retval) | ||
| 1790 | break; | ||
| 1791 | } | ||
| 1792 | |||
| 1793 | rcu_read_unlock(); | ||
| 1794 | |||
| 1795 | return retval; | ||
| 1796 | } | ||
| 1797 | EXPORT_SYMBOL(input_handler_for_each_handle); | ||
| 1798 | |||
| 1799 | /** | ||
| 1661 | * input_register_handle - register a new input handle | 1800 | * input_register_handle - register a new input handle |
| 1662 | * @handle: handle to register | 1801 | * @handle: handle to register |
| 1663 | * | 1802 | * |
| @@ -1681,7 +1820,16 @@ int input_register_handle(struct input_handle *handle) | |||
| 1681 | error = mutex_lock_interruptible(&dev->mutex); | 1820 | error = mutex_lock_interruptible(&dev->mutex); |
| 1682 | if (error) | 1821 | if (error) |
| 1683 | return error; | 1822 | return error; |
| 1684 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | 1823 | |
| 1824 | /* | ||
| 1825 | * Filters go to the head of the list, normal handlers | ||
| 1826 | * to the tail. | ||
| 1827 | */ | ||
| 1828 | if (handler->filter) | ||
| 1829 | list_add_rcu(&handle->d_node, &dev->h_list); | ||
| 1830 | else | ||
| 1831 | list_add_tail_rcu(&handle->d_node, &dev->h_list); | ||
| 1832 | |||
| 1685 | mutex_unlock(&dev->mutex); | 1833 | mutex_unlock(&dev->mutex); |
| 1686 | 1834 | ||
| 1687 | /* | 1835 | /* |
| @@ -1690,7 +1838,7 @@ int input_register_handle(struct input_handle *handle) | |||
| 1690 | * we can't be racing with input_unregister_handle() | 1838 | * we can't be racing with input_unregister_handle() |
| 1691 | * and so separate lock is not needed here. | 1839 | * and so separate lock is not needed here. |
| 1692 | */ | 1840 | */ |
| 1693 | list_add_tail(&handle->h_node, &handler->h_list); | 1841 | list_add_tail_rcu(&handle->h_node, &handler->h_list); |
| 1694 | 1842 | ||
| 1695 | if (handler->start) | 1843 | if (handler->start) |
| 1696 | handler->start(handle); | 1844 | handler->start(handle); |
| @@ -1713,7 +1861,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
| 1713 | { | 1861 | { |
| 1714 | struct input_dev *dev = handle->dev; | 1862 | struct input_dev *dev = handle->dev; |
| 1715 | 1863 | ||
| 1716 | list_del_init(&handle->h_node); | 1864 | list_del_rcu(&handle->h_node); |
| 1717 | 1865 | ||
| 1718 | /* | 1866 | /* |
| 1719 | * Take dev->mutex to prevent race with input_release_device(). | 1867 | * Take dev->mutex to prevent race with input_release_device(). |
| @@ -1721,6 +1869,7 @@ void input_unregister_handle(struct input_handle *handle) | |||
| 1721 | mutex_lock(&dev->mutex); | 1869 | mutex_lock(&dev->mutex); |
| 1722 | list_del_rcu(&handle->d_node); | 1870 | list_del_rcu(&handle->d_node); |
| 1723 | mutex_unlock(&dev->mutex); | 1871 | mutex_unlock(&dev->mutex); |
| 1872 | |||
| 1724 | synchronize_rcu(); | 1873 | synchronize_rcu(); |
| 1725 | } | 1874 | } |
| 1726 | EXPORT_SYMBOL(input_unregister_handle); | 1875 | EXPORT_SYMBOL(input_unregister_handle); |
| @@ -1731,35 +1880,37 @@ static int input_open_file(struct inode *inode, struct file *file) | |||
| 1731 | const struct file_operations *old_fops, *new_fops = NULL; | 1880 | const struct file_operations *old_fops, *new_fops = NULL; |
| 1732 | int err; | 1881 | int err; |
| 1733 | 1882 | ||
| 1734 | lock_kernel(); | 1883 | err = mutex_lock_interruptible(&input_mutex); |
| 1884 | if (err) | ||
| 1885 | return err; | ||
| 1886 | |||
| 1735 | /* No load-on-demand here? */ | 1887 | /* No load-on-demand here? */ |
| 1736 | handler = input_table[iminor(inode) >> 5]; | 1888 | handler = input_table[iminor(inode) >> 5]; |
| 1737 | if (!handler || !(new_fops = fops_get(handler->fops))) { | 1889 | if (handler) |
| 1738 | err = -ENODEV; | 1890 | new_fops = fops_get(handler->fops); |
| 1739 | goto out; | 1891 | |
| 1740 | } | 1892 | mutex_unlock(&input_mutex); |
| 1741 | 1893 | ||
| 1742 | /* | 1894 | /* |
| 1743 | * That's _really_ odd. Usually NULL ->open means "nothing special", | 1895 | * That's _really_ odd. Usually NULL ->open means "nothing special", |
| 1744 | * not "no device". Oh, well... | 1896 | * not "no device". Oh, well... |
| 1745 | */ | 1897 | */ |
| 1746 | if (!new_fops->open) { | 1898 | if (!new_fops || !new_fops->open) { |
| 1747 | fops_put(new_fops); | 1899 | fops_put(new_fops); |
| 1748 | err = -ENODEV; | 1900 | err = -ENODEV; |
| 1749 | goto out; | 1901 | goto out; |
| 1750 | } | 1902 | } |
| 1903 | |||
| 1751 | old_fops = file->f_op; | 1904 | old_fops = file->f_op; |
| 1752 | file->f_op = new_fops; | 1905 | file->f_op = new_fops; |
| 1753 | 1906 | ||
| 1754 | err = new_fops->open(inode, file); | 1907 | err = new_fops->open(inode, file); |
| 1755 | |||
| 1756 | if (err) { | 1908 | if (err) { |
| 1757 | fops_put(file->f_op); | 1909 | fops_put(file->f_op); |
| 1758 | file->f_op = fops_get(old_fops); | 1910 | file->f_op = fops_get(old_fops); |
| 1759 | } | 1911 | } |
| 1760 | fops_put(old_fops); | 1912 | fops_put(old_fops); |
| 1761 | out: | 1913 | out: |
| 1762 | unlock_kernel(); | ||
| 1763 | return err; | 1914 | return err; |
| 1764 | } | 1915 | } |
| 1765 | 1916 | ||
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index b1bd6dd32286..c52bec4d0530 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -286,6 +286,8 @@ static int joydev_open(struct inode *inode, struct file *file) | |||
| 286 | goto err_free_client; | 286 | goto err_free_client; |
| 287 | 287 | ||
| 288 | file->private_data = client; | 288 | file->private_data = client; |
| 289 | nonseekable_open(inode, file); | ||
| 290 | |||
| 289 | return 0; | 291 | return 0; |
| 290 | 292 | ||
| 291 | err_free_client: | 293 | err_free_client: |
| @@ -775,6 +777,20 @@ static void joydev_cleanup(struct joydev *joydev) | |||
| 775 | input_close_device(handle); | 777 | input_close_device(handle); |
| 776 | } | 778 | } |
| 777 | 779 | ||
| 780 | |||
| 781 | static bool joydev_match(struct input_handler *handler, struct input_dev *dev) | ||
| 782 | { | ||
| 783 | /* Avoid touchpads and touchscreens */ | ||
| 784 | if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit)) | ||
| 785 | return false; | ||
| 786 | |||
| 787 | /* Avoid tablets, digitisers and similar devices */ | ||
| 788 | if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit)) | ||
| 789 | return false; | ||
| 790 | |||
| 791 | return true; | ||
| 792 | } | ||
| 793 | |||
| 778 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | 794 | static int joydev_connect(struct input_handler *handler, struct input_dev *dev, |
| 779 | const struct input_device_id *id) | 795 | const struct input_device_id *id) |
| 780 | { | 796 | { |
| @@ -894,22 +910,6 @@ static void joydev_disconnect(struct input_handle *handle) | |||
| 894 | put_device(&joydev->dev); | 910 | put_device(&joydev->dev); |
| 895 | } | 911 | } |
| 896 | 912 | ||
| 897 | static const struct input_device_id joydev_blacklist[] = { | ||
| 898 | { | ||
| 899 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
| 900 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 901 | .evbit = { BIT_MASK(EV_KEY) }, | ||
| 902 | .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, | ||
| 903 | }, /* Avoid itouchpads and touchscreens */ | ||
| 904 | { | ||
| 905 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
| 906 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 907 | .evbit = { BIT_MASK(EV_KEY) }, | ||
| 908 | .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) }, | ||
| 909 | }, /* Avoid tablets, digitisers and similar devices */ | ||
| 910 | { } /* Terminating entry */ | ||
| 911 | }; | ||
| 912 | |||
| 913 | static const struct input_device_id joydev_ids[] = { | 913 | static const struct input_device_id joydev_ids[] = { |
| 914 | { | 914 | { |
| 915 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | 915 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | |
| @@ -936,13 +936,13 @@ MODULE_DEVICE_TABLE(input, joydev_ids); | |||
| 936 | 936 | ||
| 937 | static struct input_handler joydev_handler = { | 937 | static struct input_handler joydev_handler = { |
| 938 | .event = joydev_event, | 938 | .event = joydev_event, |
| 939 | .match = joydev_match, | ||
| 939 | .connect = joydev_connect, | 940 | .connect = joydev_connect, |
| 940 | .disconnect = joydev_disconnect, | 941 | .disconnect = joydev_disconnect, |
| 941 | .fops = &joydev_fops, | 942 | .fops = &joydev_fops, |
| 942 | .minor = JOYDEV_MINOR_BASE, | 943 | .minor = JOYDEV_MINOR_BASE, |
| 943 | .name = "joydev", | 944 | .name = "joydev", |
| 944 | .id_table = joydev_ids, | 945 | .id_table = joydev_ids, |
| 945 | .blacklist = joydev_blacklist, | ||
| 946 | }; | 946 | }; |
| 947 | 947 | ||
| 948 | static int __init joydev_init(void) | 948 | static int __init joydev_init(void) |
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig index b11419590cfe..5b596165b571 100644 --- a/drivers/input/joystick/Kconfig +++ b/drivers/input/joystick/Kconfig | |||
| @@ -221,6 +221,7 @@ config JOYSTICK_DB9 | |||
| 221 | config JOYSTICK_GAMECON | 221 | config JOYSTICK_GAMECON |
| 222 | tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" | 222 | tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads" |
| 223 | depends on PARPORT | 223 | depends on PARPORT |
| 224 | select INPUT_FF_MEMLESS | ||
| 224 | ---help--- | 225 | ---help--- |
| 225 | Say Y here if you have a Nintendo Entertainment System gamepad, | 226 | Say Y here if you have a Nintendo Entertainment System gamepad, |
| 226 | Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, | 227 | Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad, |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index 523959484753..8e7de5c7754f 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/parport.h> | 36 | #include <linux/parport.h> |
| 37 | #include <linux/input.h> | 37 | #include <linux/input.h> |
| 38 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
| 39 | #include <linux/slab.h> | ||
| 39 | 40 | ||
| 40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 41 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 41 | MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); | 42 | MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver"); |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 07a32aff5a31..fbd62abb66f9 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
| @@ -30,6 +30,8 @@ | |||
| 30 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 30 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 34 | |||
| 33 | #include <linux/kernel.h> | 35 | #include <linux/kernel.h> |
| 34 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
| 35 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| @@ -37,6 +39,7 @@ | |||
| 37 | #include <linux/parport.h> | 39 | #include <linux/parport.h> |
| 38 | #include <linux/input.h> | 40 | #include <linux/input.h> |
| 39 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
| 42 | #include <linux/slab.h> | ||
| 40 | 43 | ||
| 41 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 44 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 42 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); | 45 | MODULE_DESCRIPTION("NES, SNES, N64, MultiSystem, PSX gamepad driver"); |
| @@ -61,48 +64,73 @@ MODULE_PARM_DESC(map3, "Describes third set of devices"); | |||
| 61 | 64 | ||
| 62 | /* see also gs_psx_delay parameter in PSX support section */ | 65 | /* see also gs_psx_delay parameter in PSX support section */ |
| 63 | 66 | ||
| 64 | #define GC_SNES 1 | 67 | enum gc_type { |
| 65 | #define GC_NES 2 | 68 | GC_NONE = 0, |
| 66 | #define GC_NES4 3 | 69 | GC_SNES, |
| 67 | #define GC_MULTI 4 | 70 | GC_NES, |
| 68 | #define GC_MULTI2 5 | 71 | GC_NES4, |
| 69 | #define GC_N64 6 | 72 | GC_MULTI, |
| 70 | #define GC_PSX 7 | 73 | GC_MULTI2, |
| 71 | #define GC_DDR 8 | 74 | GC_N64, |
| 72 | #define GC_SNESMOUSE 9 | 75 | GC_PSX, |
| 73 | 76 | GC_DDR, | |
| 74 | #define GC_MAX 9 | 77 | GC_SNESMOUSE, |
| 78 | GC_MAX | ||
| 79 | }; | ||
| 75 | 80 | ||
| 76 | #define GC_REFRESH_TIME HZ/100 | 81 | #define GC_REFRESH_TIME HZ/100 |
| 77 | 82 | ||
| 83 | struct gc_pad { | ||
| 84 | struct input_dev *dev; | ||
| 85 | enum gc_type type; | ||
| 86 | char phys[32]; | ||
| 87 | }; | ||
| 88 | |||
| 78 | struct gc { | 89 | struct gc { |
| 79 | struct pardevice *pd; | 90 | struct pardevice *pd; |
| 91 | struct gc_pad pads[GC_MAX_DEVICES]; | ||
| 80 | struct input_dev *dev[GC_MAX_DEVICES]; | 92 | struct input_dev *dev[GC_MAX_DEVICES]; |
| 81 | struct timer_list timer; | 93 | struct timer_list timer; |
| 82 | unsigned char pads[GC_MAX + 1]; | 94 | int pad_count[GC_MAX]; |
| 83 | int used; | 95 | int used; |
| 84 | struct mutex mutex; | 96 | struct mutex mutex; |
| 85 | char phys[GC_MAX_DEVICES][32]; | 97 | }; |
| 98 | |||
| 99 | struct gc_subdev { | ||
| 100 | unsigned int idx; | ||
| 86 | }; | 101 | }; |
| 87 | 102 | ||
| 88 | static struct gc *gc_base[3]; | 103 | static struct gc *gc_base[3]; |
| 89 | 104 | ||
| 90 | static int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; | 105 | static const int gc_status_bit[] = { 0x40, 0x80, 0x20, 0x10, 0x08 }; |
| 106 | |||
| 107 | static const char *gc_names[] = { | ||
| 108 | NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", | ||
| 109 | "Multisystem 2-button joystick", "N64 controller", "PSX controller", | ||
| 110 | "PSX DDR controller", "SNES mouse" | ||
| 111 | }; | ||
| 91 | 112 | ||
| 92 | static char *gc_names[] = { NULL, "SNES pad", "NES pad", "NES FourPort", "Multisystem joystick", | ||
| 93 | "Multisystem 2-button joystick", "N64 controller", "PSX controller", | ||
| 94 | "PSX DDR controller", "SNES mouse" }; | ||
| 95 | /* | 113 | /* |
| 96 | * N64 support. | 114 | * N64 support. |
| 97 | */ | 115 | */ |
| 98 | 116 | ||
| 99 | static unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; | 117 | static const unsigned char gc_n64_bytes[] = { 0, 1, 13, 15, 14, 12, 10, 11, 2, 3 }; |
| 100 | static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START }; | 118 | static const short gc_n64_btn[] = { |
| 119 | BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, | ||
| 120 | BTN_TL, BTN_TR, BTN_TRIGGER, BTN_START | ||
| 121 | }; | ||
| 101 | 122 | ||
| 102 | #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ | 123 | #define GC_N64_LENGTH 32 /* N64 bit length, not including stop bit */ |
| 103 | #define GC_N64_REQUEST_LENGTH 37 /* transmit request sequence is 9 bits long */ | 124 | #define GC_N64_STOP_LENGTH 5 /* Length of encoded stop bit */ |
| 125 | #define GC_N64_CMD_00 0x11111111UL | ||
| 126 | #define GC_N64_CMD_01 0xd1111111UL | ||
| 127 | #define GC_N64_CMD_03 0xdd111111UL | ||
| 128 | #define GC_N64_CMD_1b 0xdd1dd111UL | ||
| 129 | #define GC_N64_CMD_c0 0x111111ddUL | ||
| 130 | #define GC_N64_CMD_80 0x1111111dUL | ||
| 131 | #define GC_N64_STOP_BIT 0x1d /* Encoded stop bit */ | ||
| 132 | #define GC_N64_REQUEST_DATA GC_N64_CMD_01 /* the request data command */ | ||
| 104 | #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ | 133 | #define GC_N64_DELAY 133 /* delay between transmit request, and response ready (us) */ |
| 105 | #define GC_N64_REQUEST 0x1dd1111111ULL /* the request data command (encoded for 000000011) */ | ||
| 106 | #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ | 134 | #define GC_N64_DWS 3 /* delay between write segments (required for sound playback because of ISA DMA) */ |
| 107 | /* GC_N64_DWS > 24 is known to fail */ | 135 | /* GC_N64_DWS > 24 is known to fail */ |
| 108 | #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ | 136 | #define GC_N64_POWER_W 0xe2 /* power during write (transmit request) */ |
| @@ -114,8 +142,40 @@ static short gc_n64_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, | |||
| 114 | #define GC_N64_CLOCK 0x02 /* clock bits for read */ | 142 | #define GC_N64_CLOCK 0x02 /* clock bits for read */ |
| 115 | 143 | ||
| 116 | /* | 144 | /* |
| 145 | * Used for rumble code. | ||
| 146 | */ | ||
| 147 | |||
| 148 | /* Send encoded command */ | ||
| 149 | static void gc_n64_send_command(struct gc *gc, unsigned long cmd, | ||
| 150 | unsigned char target) | ||
| 151 | { | ||
| 152 | struct parport *port = gc->pd->port; | ||
| 153 | int i; | ||
| 154 | |||
| 155 | for (i = 0; i < GC_N64_LENGTH; i++) { | ||
| 156 | unsigned char data = (cmd >> i) & 1 ? target : 0; | ||
| 157 | parport_write_data(port, GC_N64_POWER_W | data); | ||
| 158 | udelay(GC_N64_DWS); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | /* Send stop bit */ | ||
| 163 | static void gc_n64_send_stop_bit(struct gc *gc, unsigned char target) | ||
| 164 | { | ||
| 165 | struct parport *port = gc->pd->port; | ||
| 166 | int i; | ||
| 167 | |||
| 168 | for (i = 0; i < GC_N64_STOP_LENGTH; i++) { | ||
| 169 | unsigned char data = (GC_N64_STOP_BIT >> i) & 1 ? target : 0; | ||
| 170 | parport_write_data(port, GC_N64_POWER_W | data); | ||
| 171 | udelay(GC_N64_DWS); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | /* | ||
| 117 | * gc_n64_read_packet() reads an N64 packet. | 176 | * gc_n64_read_packet() reads an N64 packet. |
| 118 | * Each pad uses one bit per byte. So all pads connected to this port are read in parallel. | 177 | * Each pad uses one bit per byte. So all pads connected to this port |
| 178 | * are read in parallel. | ||
| 119 | */ | 179 | */ |
| 120 | 180 | ||
| 121 | static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | 181 | static void gc_n64_read_packet(struct gc *gc, unsigned char *data) |
| @@ -128,14 +188,13 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |||
| 128 | */ | 188 | */ |
| 129 | 189 | ||
| 130 | local_irq_save(flags); | 190 | local_irq_save(flags); |
| 131 | for (i = 0; i < GC_N64_REQUEST_LENGTH; i++) { | 191 | gc_n64_send_command(gc, GC_N64_REQUEST_DATA, GC_N64_OUT); |
| 132 | parport_write_data(gc->pd->port, GC_N64_POWER_W | ((GC_N64_REQUEST >> i) & 1 ? GC_N64_OUT : 0)); | 192 | gc_n64_send_stop_bit(gc, GC_N64_OUT); |
| 133 | udelay(GC_N64_DWS); | ||
| 134 | } | ||
| 135 | local_irq_restore(flags); | 193 | local_irq_restore(flags); |
| 136 | 194 | ||
| 137 | /* | 195 | /* |
| 138 | * Wait for the pad response to be loaded into the 33-bit register of the adapter | 196 | * Wait for the pad response to be loaded into the 33-bit register |
| 197 | * of the adapter. | ||
| 139 | */ | 198 | */ |
| 140 | 199 | ||
| 141 | udelay(GC_N64_DELAY); | 200 | udelay(GC_N64_DELAY); |
| @@ -146,13 +205,15 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |||
| 146 | 205 | ||
| 147 | for (i = 0; i < GC_N64_LENGTH; i++) { | 206 | for (i = 0; i < GC_N64_LENGTH; i++) { |
| 148 | parport_write_data(gc->pd->port, GC_N64_POWER_R); | 207 | parport_write_data(gc->pd->port, GC_N64_POWER_R); |
| 208 | udelay(2); | ||
| 149 | data[i] = parport_read_status(gc->pd->port); | 209 | data[i] = parport_read_status(gc->pd->port); |
| 150 | parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); | 210 | parport_write_data(gc->pd->port, GC_N64_POWER_R | GC_N64_CLOCK); |
| 151 | } | 211 | } |
| 152 | 212 | ||
| 153 | /* | 213 | /* |
| 154 | * We must wait 200 ms here for the controller to reinitialize before the next read request. | 214 | * We must wait 200 ms here for the controller to reinitialize before |
| 155 | * No worries as long as gc_read is polled less frequently than this. | 215 | * the next read request. No worries as long as gc_read is polled less |
| 216 | * frequently than this. | ||
| 156 | */ | 217 | */ |
| 157 | 218 | ||
| 158 | } | 219 | } |
| @@ -160,45 +221,112 @@ static void gc_n64_read_packet(struct gc *gc, unsigned char *data) | |||
| 160 | static void gc_n64_process_packet(struct gc *gc) | 221 | static void gc_n64_process_packet(struct gc *gc) |
| 161 | { | 222 | { |
| 162 | unsigned char data[GC_N64_LENGTH]; | 223 | unsigned char data[GC_N64_LENGTH]; |
| 163 | signed char axes[2]; | ||
| 164 | struct input_dev *dev; | 224 | struct input_dev *dev; |
| 165 | int i, j, s; | 225 | int i, j, s; |
| 226 | signed char x, y; | ||
| 166 | 227 | ||
| 167 | gc_n64_read_packet(gc, data); | 228 | gc_n64_read_packet(gc, data); |
| 168 | 229 | ||
| 169 | for (i = 0; i < GC_MAX_DEVICES; i++) { | 230 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
| 170 | 231 | ||
| 171 | dev = gc->dev[i]; | 232 | if (gc->pads[i].type != GC_N64) |
| 172 | if (!dev) | ||
| 173 | continue; | 233 | continue; |
| 174 | 234 | ||
| 235 | dev = gc->pads[i].dev; | ||
| 175 | s = gc_status_bit[i]; | 236 | s = gc_status_bit[i]; |
| 176 | 237 | ||
| 177 | if (s & gc->pads[GC_N64] & ~(data[8] | data[9])) { | 238 | if (s & ~(data[8] | data[9])) { |
| 178 | 239 | ||
| 179 | axes[0] = axes[1] = 0; | 240 | x = y = 0; |
| 180 | 241 | ||
| 181 | for (j = 0; j < 8; j++) { | 242 | for (j = 0; j < 8; j++) { |
| 182 | if (data[23 - j] & s) | 243 | if (data[23 - j] & s) |
| 183 | axes[0] |= 1 << j; | 244 | x |= 1 << j; |
| 184 | if (data[31 - j] & s) | 245 | if (data[31 - j] & s) |
| 185 | axes[1] |= 1 << j; | 246 | y |= 1 << j; |
| 186 | } | 247 | } |
| 187 | 248 | ||
| 188 | input_report_abs(dev, ABS_X, axes[0]); | 249 | input_report_abs(dev, ABS_X, x); |
| 189 | input_report_abs(dev, ABS_Y, -axes[1]); | 250 | input_report_abs(dev, ABS_Y, -y); |
| 190 | 251 | ||
| 191 | input_report_abs(dev, ABS_HAT0X, !(s & data[6]) - !(s & data[7])); | 252 | input_report_abs(dev, ABS_HAT0X, |
| 192 | input_report_abs(dev, ABS_HAT0Y, !(s & data[4]) - !(s & data[5])); | 253 | !(s & data[6]) - !(s & data[7])); |
| 254 | input_report_abs(dev, ABS_HAT0Y, | ||
| 255 | !(s & data[4]) - !(s & data[5])); | ||
| 193 | 256 | ||
| 194 | for (j = 0; j < 10; j++) | 257 | for (j = 0; j < 10; j++) |
| 195 | input_report_key(dev, gc_n64_btn[j], s & data[gc_n64_bytes[j]]); | 258 | input_report_key(dev, gc_n64_btn[j], |
| 259 | s & data[gc_n64_bytes[j]]); | ||
| 196 | 260 | ||
| 197 | input_sync(dev); | 261 | input_sync(dev); |
| 198 | } | 262 | } |
| 199 | } | 263 | } |
| 200 | } | 264 | } |
| 201 | 265 | ||
| 266 | static int gc_n64_play_effect(struct input_dev *dev, void *data, | ||
| 267 | struct ff_effect *effect) | ||
| 268 | { | ||
| 269 | int i; | ||
| 270 | unsigned long flags; | ||
| 271 | struct gc *gc = input_get_drvdata(dev); | ||
| 272 | struct gc_subdev *sdev = data; | ||
| 273 | unsigned char target = 1 << sdev->idx; /* select desired pin */ | ||
| 274 | |||
| 275 | if (effect->type == FF_RUMBLE) { | ||
| 276 | struct ff_rumble_effect *rumble = &effect->u.rumble; | ||
| 277 | unsigned int cmd = | ||
| 278 | rumble->strong_magnitude || rumble->weak_magnitude ? | ||
| 279 | GC_N64_CMD_01 : GC_N64_CMD_00; | ||
| 280 | |||
| 281 | local_irq_save(flags); | ||
| 282 | |||
| 283 | /* Init Rumble - 0x03, 0x80, 0x01, (34)0x80 */ | ||
| 284 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | ||
| 285 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | ||
| 286 | gc_n64_send_command(gc, GC_N64_CMD_01, target); | ||
| 287 | for (i = 0; i < 32; i++) | ||
| 288 | gc_n64_send_command(gc, GC_N64_CMD_80, target); | ||
| 289 | gc_n64_send_stop_bit(gc, target); | ||
| 290 | |||
| 291 | udelay(GC_N64_DELAY); | ||
| 292 | |||
| 293 | /* Now start or stop it - 0x03, 0xc0, 0zx1b, (32)0x01/0x00 */ | ||
| 294 | gc_n64_send_command(gc, GC_N64_CMD_03, target); | ||
| 295 | gc_n64_send_command(gc, GC_N64_CMD_c0, target); | ||
| 296 | gc_n64_send_command(gc, GC_N64_CMD_1b, target); | ||
| 297 | for (i = 0; i < 32; i++) | ||
| 298 | gc_n64_send_command(gc, cmd, target); | ||
| 299 | gc_n64_send_stop_bit(gc, target); | ||
| 300 | |||
| 301 | local_irq_restore(flags); | ||
| 302 | |||
| 303 | } | ||
| 304 | |||
| 305 | return 0; | ||
| 306 | } | ||
| 307 | |||
| 308 | static int __init gc_n64_init_ff(struct input_dev *dev, int i) | ||
| 309 | { | ||
| 310 | struct gc_subdev *sdev; | ||
| 311 | int err; | ||
| 312 | |||
| 313 | sdev = kmalloc(sizeof(*sdev), GFP_KERNEL); | ||
| 314 | if (!sdev) | ||
| 315 | return -ENOMEM; | ||
| 316 | |||
| 317 | sdev->idx = i; | ||
| 318 | |||
| 319 | input_set_capability(dev, EV_FF, FF_RUMBLE); | ||
| 320 | |||
| 321 | err = input_ff_create_memless(dev, sdev, gc_n64_play_effect); | ||
| 322 | if (err) { | ||
| 323 | kfree(sdev); | ||
| 324 | return err; | ||
| 325 | } | ||
| 326 | |||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | |||
| 202 | /* | 330 | /* |
| 203 | * NES/SNES support. | 331 | * NES/SNES support. |
| 204 | */ | 332 | */ |
| @@ -214,9 +342,11 @@ static void gc_n64_process_packet(struct gc *gc) | |||
| 214 | #define GC_NES_CLOCK 0x01 | 342 | #define GC_NES_CLOCK 0x01 |
| 215 | #define GC_NES_LATCH 0x02 | 343 | #define GC_NES_LATCH 0x02 |
| 216 | 344 | ||
| 217 | static unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; | 345 | static const unsigned char gc_nes_bytes[] = { 0, 1, 2, 3 }; |
| 218 | static unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; | 346 | static const unsigned char gc_snes_bytes[] = { 8, 0, 2, 3, 9, 1, 10, 11 }; |
| 219 | static short gc_snes_btn[] = { BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR }; | 347 | static const short gc_snes_btn[] = { |
| 348 | BTN_A, BTN_B, BTN_SELECT, BTN_START, BTN_X, BTN_Y, BTN_TL, BTN_TR | ||
| 349 | }; | ||
| 220 | 350 | ||
| 221 | /* | 351 | /* |
| 222 | * gc_nes_read_packet() reads a NES/SNES packet. | 352 | * gc_nes_read_packet() reads a NES/SNES packet. |
| @@ -244,40 +374,51 @@ static void gc_nes_read_packet(struct gc *gc, int length, unsigned char *data) | |||
| 244 | static void gc_nes_process_packet(struct gc *gc) | 374 | static void gc_nes_process_packet(struct gc *gc) |
| 245 | { | 375 | { |
| 246 | unsigned char data[GC_SNESMOUSE_LENGTH]; | 376 | unsigned char data[GC_SNESMOUSE_LENGTH]; |
| 377 | struct gc_pad *pad; | ||
| 247 | struct input_dev *dev; | 378 | struct input_dev *dev; |
| 248 | int i, j, s, len; | 379 | int i, j, s, len; |
| 249 | char x_rel, y_rel; | 380 | char x_rel, y_rel; |
| 250 | 381 | ||
| 251 | len = gc->pads[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : | 382 | len = gc->pad_count[GC_SNESMOUSE] ? GC_SNESMOUSE_LENGTH : |
| 252 | (gc->pads[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); | 383 | (gc->pad_count[GC_SNES] ? GC_SNES_LENGTH : GC_NES_LENGTH); |
| 253 | 384 | ||
| 254 | gc_nes_read_packet(gc, len, data); | 385 | gc_nes_read_packet(gc, len, data); |
| 255 | 386 | ||
| 256 | for (i = 0; i < GC_MAX_DEVICES; i++) { | 387 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
| 257 | 388 | ||
| 389 | pad = &gc->pads[i]; | ||
| 258 | dev = gc->dev[i]; | 390 | dev = gc->dev[i]; |
| 259 | if (!dev) | ||
| 260 | continue; | ||
| 261 | |||
| 262 | s = gc_status_bit[i]; | 391 | s = gc_status_bit[i]; |
| 263 | 392 | ||
| 264 | if (s & (gc->pads[GC_NES] | gc->pads[GC_SNES])) { | 393 | switch (pad->type) { |
| 394 | |||
| 395 | case GC_NES: | ||
| 396 | |||
| 265 | input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); | 397 | input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); |
| 266 | input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); | 398 | input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); |
| 267 | } | ||
| 268 | 399 | ||
| 269 | if (s & gc->pads[GC_NES]) | ||
| 270 | for (j = 0; j < 4; j++) | 400 | for (j = 0; j < 4; j++) |
| 271 | input_report_key(dev, gc_snes_btn[j], s & data[gc_nes_bytes[j]]); | 401 | input_report_key(dev, gc_snes_btn[j], |
| 402 | s & data[gc_nes_bytes[j]]); | ||
| 403 | input_sync(dev); | ||
| 404 | break; | ||
| 405 | |||
| 406 | case GC_SNES: | ||
| 407 | |||
| 408 | input_report_abs(dev, ABS_X, !(s & data[6]) - !(s & data[7])); | ||
| 409 | input_report_abs(dev, ABS_Y, !(s & data[4]) - !(s & data[5])); | ||
| 272 | 410 | ||
| 273 | if (s & gc->pads[GC_SNES]) | ||
| 274 | for (j = 0; j < 8; j++) | 411 | for (j = 0; j < 8; j++) |
| 275 | input_report_key(dev, gc_snes_btn[j], s & data[gc_snes_bytes[j]]); | 412 | input_report_key(dev, gc_snes_btn[j], |
| 413 | s & data[gc_snes_bytes[j]]); | ||
| 414 | input_sync(dev); | ||
| 415 | break; | ||
| 276 | 416 | ||
| 277 | if (s & gc->pads[GC_SNESMOUSE]) { | 417 | case GC_SNESMOUSE: |
| 278 | /* | 418 | /* |
| 279 | * The 4 unused bits from SNES controllers appear to be ID bits | 419 | * The 4 unused bits from SNES controllers appear |
| 280 | * so use them to make sure iwe are dealing with a mouse. | 420 | * to be ID bits so use them to make sure we are |
| 421 | * dealing with a mouse. | ||
| 281 | * gamepad is connected. This is important since | 422 | * gamepad is connected. This is important since |
| 282 | * my SNES gamepad sends 1's for bits 16-31, which | 423 | * my SNES gamepad sends 1's for bits 16-31, which |
| 283 | * cause the mouse pointer to quickly move to the | 424 | * cause the mouse pointer to quickly move to the |
| @@ -310,9 +451,14 @@ static void gc_nes_process_packet(struct gc *gc) | |||
| 310 | y_rel = -y_rel; | 451 | y_rel = -y_rel; |
| 311 | input_report_rel(dev, REL_Y, y_rel); | 452 | input_report_rel(dev, REL_Y, y_rel); |
| 312 | } | 453 | } |
| 454 | |||
| 455 | input_sync(dev); | ||
| 313 | } | 456 | } |
| 457 | break; | ||
| 458 | |||
| 459 | default: | ||
| 460 | break; | ||
| 314 | } | 461 | } |
| 315 | input_sync(dev); | ||
| 316 | } | 462 | } |
| 317 | } | 463 | } |
| 318 | 464 | ||
| @@ -340,29 +486,35 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data) | |||
| 340 | static void gc_multi_process_packet(struct gc *gc) | 486 | static void gc_multi_process_packet(struct gc *gc) |
| 341 | { | 487 | { |
| 342 | unsigned char data[GC_MULTI2_LENGTH]; | 488 | unsigned char data[GC_MULTI2_LENGTH]; |
| 489 | int data_len = gc->pad_count[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH; | ||
| 490 | struct gc_pad *pad; | ||
| 343 | struct input_dev *dev; | 491 | struct input_dev *dev; |
| 344 | int i, s; | 492 | int i, s; |
| 345 | 493 | ||
| 346 | gc_multi_read_packet(gc, gc->pads[GC_MULTI2] ? GC_MULTI2_LENGTH : GC_MULTI_LENGTH, data); | 494 | gc_multi_read_packet(gc, data_len, data); |
| 347 | 495 | ||
| 348 | for (i = 0; i < GC_MAX_DEVICES; i++) { | 496 | for (i = 0; i < GC_MAX_DEVICES; i++) { |
| 349 | 497 | pad = &gc->pads[i]; | |
| 350 | dev = gc->dev[i]; | 498 | dev = pad->dev; |
| 351 | if (!dev) | ||
| 352 | continue; | ||
| 353 | |||
| 354 | s = gc_status_bit[i]; | 499 | s = gc_status_bit[i]; |
| 355 | 500 | ||
| 356 | if (s & (gc->pads[GC_MULTI] | gc->pads[GC_MULTI2])) { | 501 | switch (pad->type) { |
| 357 | input_report_abs(dev, ABS_X, !(s & data[2]) - !(s & data[3])); | 502 | case GC_MULTI2: |
| 358 | input_report_abs(dev, ABS_Y, !(s & data[0]) - !(s & data[1])); | ||
| 359 | input_report_key(dev, BTN_TRIGGER, s & data[4]); | ||
| 360 | } | ||
| 361 | |||
| 362 | if (s & gc->pads[GC_MULTI2]) | ||
| 363 | input_report_key(dev, BTN_THUMB, s & data[5]); | 503 | input_report_key(dev, BTN_THUMB, s & data[5]); |
| 504 | /* fall through */ | ||
| 364 | 505 | ||
| 365 | input_sync(dev); | 506 | case GC_MULTI: |
| 507 | input_report_abs(dev, ABS_X, | ||
| 508 | !(s & data[2]) - !(s & data[3])); | ||
| 509 | input_report_abs(dev, ABS_Y, | ||
| 510 | !(s & data[0]) - !(s & data[1])); | ||
| 511 | input_report_key(dev, BTN_TRIGGER, s & data[4]); | ||
| 512 | input_sync(dev); | ||
| 513 | break; | ||
| 514 | |||
| 515 | default: | ||
| 516 | break; | ||
| 517 | } | ||
| 366 | } | 518 | } |
| 367 | } | 519 | } |
| 368 | 520 | ||
| @@ -398,30 +550,41 @@ static int gc_psx_delay = GC_PSX_DELAY; | |||
| 398 | module_param_named(psx_delay, gc_psx_delay, uint, 0); | 550 | module_param_named(psx_delay, gc_psx_delay, uint, 0); |
| 399 | MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); | 551 | MODULE_PARM_DESC(psx_delay, "Delay when accessing Sony PSX controller (usecs)"); |
| 400 | 552 | ||
| 401 | static short gc_psx_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y }; | 553 | static const short gc_psx_abs[] = { |
| 402 | static short gc_psx_btn[] = { BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, | 554 | ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_HAT0X, ABS_HAT0Y |
| 403 | BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR }; | 555 | }; |
| 404 | static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; | 556 | static const short gc_psx_btn[] = { |
| 557 | BTN_TL, BTN_TR, BTN_TL2, BTN_TR2, BTN_A, BTN_B, BTN_X, BTN_Y, | ||
| 558 | BTN_START, BTN_SELECT, BTN_THUMBL, BTN_THUMBR | ||
| 559 | }; | ||
| 560 | static const short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 }; | ||
| 405 | 561 | ||
| 406 | /* | 562 | /* |
| 407 | * gc_psx_command() writes 8bit command and reads 8bit data from | 563 | * gc_psx_command() writes 8bit command and reads 8bit data from |
| 408 | * the psx pad. | 564 | * the psx pad. |
| 409 | */ | 565 | */ |
| 410 | 566 | ||
| 411 | static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVICES]) | 567 | static void gc_psx_command(struct gc *gc, int b, unsigned char *data) |
| 412 | { | 568 | { |
| 569 | struct parport *port = gc->pd->port; | ||
| 413 | int i, j, cmd, read; | 570 | int i, j, cmd, read; |
| 414 | 571 | ||
| 415 | for (i = 0; i < GC_MAX_DEVICES; i++) | 572 | memset(data, 0, GC_MAX_DEVICES); |
| 416 | data[i] = 0; | ||
| 417 | 573 | ||
| 418 | for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { | 574 | for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) { |
| 419 | cmd = (b & 1) ? GC_PSX_COMMAND : 0; | 575 | cmd = (b & 1) ? GC_PSX_COMMAND : 0; |
| 420 | parport_write_data(gc->pd->port, cmd | GC_PSX_POWER); | 576 | parport_write_data(port, cmd | GC_PSX_POWER); |
| 421 | udelay(gc_psx_delay); | 577 | udelay(gc_psx_delay); |
| 422 | read = parport_read_status(gc->pd->port) ^ 0x80; | 578 | |
| 423 | for (j = 0; j < GC_MAX_DEVICES; j++) | 579 | read = parport_read_status(port) ^ 0x80; |
| 424 | data[j] |= (read & gc_status_bit[j] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) ? (1 << i) : 0; | 580 | |
| 581 | for (j = 0; j < GC_MAX_DEVICES; j++) { | ||
| 582 | struct gc_pad *pad = &gc->pads[i]; | ||
| 583 | |||
| 584 | if (pad->type == GC_PSX || pad->type == GC_DDR) | ||
| 585 | data[j] |= (read & gc_status_bit[j]) ? (1 << i) : 0; | ||
| 586 | } | ||
| 587 | |||
| 425 | parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); | 588 | parport_write_data(gc->pd->port, cmd | GC_PSX_CLOCK | GC_PSX_POWER); |
| 426 | udelay(gc_psx_delay); | 589 | udelay(gc_psx_delay); |
| 427 | } | 590 | } |
| @@ -432,31 +595,40 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_MAX_DEVIC | |||
| 432 | * device identifier code. | 595 | * device identifier code. |
| 433 | */ | 596 | */ |
| 434 | 597 | ||
| 435 | static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], | 598 | static void gc_psx_read_packet(struct gc *gc, |
| 599 | unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES], | ||
| 436 | unsigned char id[GC_MAX_DEVICES]) | 600 | unsigned char id[GC_MAX_DEVICES]) |
| 437 | { | 601 | { |
| 438 | int i, j, max_len = 0; | 602 | int i, j, max_len = 0; |
| 439 | unsigned long flags; | 603 | unsigned long flags; |
| 440 | unsigned char data2[GC_MAX_DEVICES]; | 604 | unsigned char data2[GC_MAX_DEVICES]; |
| 441 | 605 | ||
| 442 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); /* Select pad */ | 606 | /* Select pad */ |
| 607 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); | ||
| 443 | udelay(gc_psx_delay); | 608 | udelay(gc_psx_delay); |
| 444 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); /* Deselect, begin command */ | 609 | /* Deselect, begin command */ |
| 610 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_POWER); | ||
| 445 | udelay(gc_psx_delay); | 611 | udelay(gc_psx_delay); |
| 446 | 612 | ||
| 447 | local_irq_save(flags); | 613 | local_irq_save(flags); |
| 448 | 614 | ||
| 449 | gc_psx_command(gc, 0x01, data2); /* Access pad */ | 615 | gc_psx_command(gc, 0x01, data2); /* Access pad */ |
| 450 | gc_psx_command(gc, 0x42, id); /* Get device ids */ | 616 | gc_psx_command(gc, 0x42, id); /* Get device ids */ |
| 451 | gc_psx_command(gc, 0, data2); /* Dump status */ | 617 | gc_psx_command(gc, 0, data2); /* Dump status */ |
| 618 | |||
| 619 | /* Find the longest pad */ | ||
| 620 | for (i = 0; i < GC_MAX_DEVICES; i++) { | ||
| 621 | struct gc_pad *pad = &gc->pads[i]; | ||
| 452 | 622 | ||
| 453 | for (i =0; i < GC_MAX_DEVICES; i++) /* Find the longest pad */ | 623 | if ((pad->type == GC_PSX || pad->type == GC_DDR) && |
| 454 | if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) | 624 | GC_PSX_LEN(id[i]) > max_len && |
| 455 | && (GC_PSX_LEN(id[i]) > max_len) | 625 | GC_PSX_LEN(id[i]) <= GC_PSX_BYTES) { |
| 456 | && (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES)) | ||
| 457 | max_len = GC_PSX_LEN(id[i]); | 626 | max_len = GC_PSX_LEN(id[i]); |
| 627 | } | ||
| 628 | } | ||
| 458 | 629 | ||
| 459 | for (i = 0; i < max_len; i++) { /* Read in all the data */ | 630 | /* Read in all the data */ |
| 631 | for (i = 0; i < max_len; i++) { | ||
| 460 | gc_psx_command(gc, 0, data2); | 632 | gc_psx_command(gc, 0, data2); |
| 461 | for (j = 0; j < GC_MAX_DEVICES; j++) | 633 | for (j = 0; j < GC_MAX_DEVICES; j++) |
| 462 | data[j][i] = data2[j]; | 634 | data[j][i] = data2[j]; |
| @@ -466,86 +638,104 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[GC_MAX_DEVICES] | |||
| 466 | 638 | ||
| 467 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); | 639 | parport_write_data(gc->pd->port, GC_PSX_CLOCK | GC_PSX_SELECT | GC_PSX_POWER); |
| 468 | 640 | ||
| 469 | for(i = 0; i < GC_MAX_DEVICES; i++) /* Set id's to the real value */ | 641 | /* Set id's to the real value */ |
| 642 | for (i = 0; i < GC_MAX_DEVICES; i++) | ||
| 470 | id[i] = GC_PSX_ID(id[i]); | 643 | id[i] = GC_PSX_ID(id[i]); |
| 471 | } | 644 | } |
| 472 | 645 | ||
| 473 | static void gc_psx_process_packet(struct gc *gc) | 646 | static void gc_psx_report_one(struct gc_pad *pad, unsigned char psx_type, |
| 647 | unsigned char *data) | ||
| 474 | { | 648 | { |
| 475 | unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; | 649 | struct input_dev *dev = pad->dev; |
| 476 | unsigned char id[GC_MAX_DEVICES]; | 650 | int i; |
| 477 | struct input_dev *dev; | ||
| 478 | int i, j; | ||
| 479 | 651 | ||
| 480 | gc_psx_read_packet(gc, data, id); | 652 | switch (psx_type) { |
| 481 | 653 | ||
| 482 | for (i = 0; i < GC_MAX_DEVICES; i++) { | 654 | case GC_PSX_RUMBLE: |
| 483 | 655 | ||
| 484 | dev = gc->dev[i]; | 656 | input_report_key(dev, BTN_THUMBL, ~data[0] & 0x04); |
| 485 | if (!dev) | 657 | input_report_key(dev, BTN_THUMBR, ~data[0] & 0x02); |
| 486 | continue; | ||
| 487 | 658 | ||
| 488 | switch (id[i]) { | 659 | case GC_PSX_NEGCON: |
| 660 | case GC_PSX_ANALOG: | ||
| 489 | 661 | ||
| 490 | case GC_PSX_RUMBLE: | 662 | if (pad->type == GC_DDR) { |
| 663 | for (i = 0; i < 4; i++) | ||
| 664 | input_report_key(dev, gc_psx_ddr_btn[i], | ||
| 665 | ~data[0] & (0x10 << i)); | ||
| 666 | } else { | ||
| 667 | for (i = 0; i < 4; i++) | ||
| 668 | input_report_abs(dev, gc_psx_abs[i + 2], | ||
| 669 | data[i + 2]); | ||
| 491 | 670 | ||
| 492 | input_report_key(dev, BTN_THUMBL, ~data[i][0] & 0x04); | 671 | input_report_abs(dev, ABS_X, |
| 493 | input_report_key(dev, BTN_THUMBR, ~data[i][0] & 0x02); | 672 | !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); |
| 673 | input_report_abs(dev, ABS_Y, | ||
| 674 | !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); | ||
| 675 | } | ||
| 494 | 676 | ||
| 495 | case GC_PSX_NEGCON: | 677 | for (i = 0; i < 8; i++) |
| 496 | case GC_PSX_ANALOG: | 678 | input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); |
| 497 | 679 | ||
| 498 | if (gc->pads[GC_DDR] & gc_status_bit[i]) { | 680 | input_report_key(dev, BTN_START, ~data[0] & 0x08); |
| 499 | for(j = 0; j < 4; j++) | 681 | input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); |
| 500 | input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); | ||
| 501 | } else { | ||
| 502 | for (j = 0; j < 4; j++) | ||
| 503 | input_report_abs(dev, gc_psx_abs[j + 2], data[i][j + 2]); | ||
| 504 | 682 | ||
| 505 | input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); | 683 | input_sync(dev); |
| 506 | input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); | ||
| 507 | } | ||
| 508 | 684 | ||
| 509 | for (j = 0; j < 8; j++) | 685 | break; |
| 510 | input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); | ||
| 511 | 686 | ||
| 512 | input_report_key(dev, BTN_START, ~data[i][0] & 0x08); | 687 | case GC_PSX_NORMAL: |
| 513 | input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); | ||
| 514 | 688 | ||
| 515 | input_sync(dev); | 689 | if (pad->type == GC_DDR) { |
| 690 | for (i = 0; i < 4; i++) | ||
| 691 | input_report_key(dev, gc_psx_ddr_btn[i], | ||
| 692 | ~data[0] & (0x10 << i)); | ||
| 693 | } else { | ||
| 694 | input_report_abs(dev, ABS_X, | ||
| 695 | !!(data[0] & 0x80) * 128 + !(data[0] & 0x20) * 127); | ||
| 696 | input_report_abs(dev, ABS_Y, | ||
| 697 | !!(data[0] & 0x10) * 128 + !(data[0] & 0x40) * 127); | ||
| 516 | 698 | ||
| 517 | break; | 699 | /* |
| 518 | 700 | * For some reason if the extra axes are left unset | |
| 519 | case GC_PSX_NORMAL: | 701 | * they drift. |
| 520 | if (gc->pads[GC_DDR] & gc_status_bit[i]) { | 702 | * for (i = 0; i < 4; i++) |
| 521 | for(j = 0; j < 4; j++) | 703 | input_report_abs(dev, gc_psx_abs[i + 2], 128); |
| 522 | input_report_key(dev, gc_psx_ddr_btn[j], ~data[i][0] & (0x10 << j)); | 704 | * This needs to be debugged properly, |
| 523 | } else { | 705 | * maybe fuzz processing needs to be done |
| 524 | input_report_abs(dev, ABS_X, 128 + !(data[i][0] & 0x20) * 127 - !(data[i][0] & 0x80) * 128); | 706 | * in input_sync() |
| 525 | input_report_abs(dev, ABS_Y, 128 + !(data[i][0] & 0x40) * 127 - !(data[i][0] & 0x10) * 128); | 707 | * --vojtech |
| 526 | 708 | */ | |
| 527 | /* for some reason if the extra axes are left unset they drift */ | 709 | } |
| 528 | /* for (j = 0; j < 4; j++) | ||
| 529 | input_report_abs(dev, gc_psx_abs[j + 2], 128); | ||
| 530 | * This needs to be debugged properly, | ||
| 531 | * maybe fuzz processing needs to be done in input_sync() | ||
| 532 | * --vojtech | ||
| 533 | */ | ||
| 534 | } | ||
| 535 | 710 | ||
| 536 | for (j = 0; j < 8; j++) | 711 | for (i = 0; i < 8; i++) |
| 537 | input_report_key(dev, gc_psx_btn[j], ~data[i][1] & (1 << j)); | 712 | input_report_key(dev, gc_psx_btn[i], ~data[1] & (1 << i)); |
| 538 | 713 | ||
| 539 | input_report_key(dev, BTN_START, ~data[i][0] & 0x08); | 714 | input_report_key(dev, BTN_START, ~data[0] & 0x08); |
| 540 | input_report_key(dev, BTN_SELECT, ~data[i][0] & 0x01); | 715 | input_report_key(dev, BTN_SELECT, ~data[0] & 0x01); |
| 541 | 716 | ||
| 542 | input_sync(dev); | 717 | input_sync(dev); |
| 543 | 718 | ||
| 544 | break; | 719 | break; |
| 545 | 720 | ||
| 546 | case 0: /* not a pad, ignore */ | 721 | default: /* not a pad, ignore */ |
| 547 | break; | 722 | break; |
| 548 | } | 723 | } |
| 724 | } | ||
| 725 | |||
| 726 | static void gc_psx_process_packet(struct gc *gc) | ||
| 727 | { | ||
| 728 | unsigned char data[GC_MAX_DEVICES][GC_PSX_BYTES]; | ||
| 729 | unsigned char id[GC_MAX_DEVICES]; | ||
| 730 | struct gc_pad *pad; | ||
| 731 | int i; | ||
| 732 | |||
| 733 | gc_psx_read_packet(gc, data, id); | ||
| 734 | |||
| 735 | for (i = 0; i < GC_MAX_DEVICES; i++) { | ||
| 736 | pad = &gc->pads[i]; | ||
| 737 | if (pad->type == GC_PSX || pad->type == GC_DDR) | ||
| 738 | gc_psx_report_one(pad, id[i], data[i]); | ||
| 549 | } | 739 | } |
| 550 | } | 740 | } |
| 551 | 741 | ||
| @@ -561,28 +751,31 @@ static void gc_timer(unsigned long private) | |||
| 561 | * N64 pads - must be read first, any read confuses them for 200 us | 751 | * N64 pads - must be read first, any read confuses them for 200 us |
| 562 | */ | 752 | */ |
| 563 | 753 | ||
| 564 | if (gc->pads[GC_N64]) | 754 | if (gc->pad_count[GC_N64]) |
| 565 | gc_n64_process_packet(gc); | 755 | gc_n64_process_packet(gc); |
| 566 | 756 | ||
| 567 | /* | 757 | /* |
| 568 | * NES and SNES pads or mouse | 758 | * NES and SNES pads or mouse |
| 569 | */ | 759 | */ |
| 570 | 760 | ||
| 571 | if (gc->pads[GC_NES] || gc->pads[GC_SNES] || gc->pads[GC_SNESMOUSE]) | 761 | if (gc->pad_count[GC_NES] || |
| 762 | gc->pad_count[GC_SNES] || | ||
| 763 | gc->pad_count[GC_SNESMOUSE]) { | ||
| 572 | gc_nes_process_packet(gc); | 764 | gc_nes_process_packet(gc); |
| 765 | } | ||
| 573 | 766 | ||
| 574 | /* | 767 | /* |
| 575 | * Multi and Multi2 joysticks | 768 | * Multi and Multi2 joysticks |
| 576 | */ | 769 | */ |
| 577 | 770 | ||
| 578 | if (gc->pads[GC_MULTI] || gc->pads[GC_MULTI2]) | 771 | if (gc->pad_count[GC_MULTI] || gc->pad_count[GC_MULTI2]) |
| 579 | gc_multi_process_packet(gc); | 772 | gc_multi_process_packet(gc); |
| 580 | 773 | ||
| 581 | /* | 774 | /* |
| 582 | * PSX controllers | 775 | * PSX controllers |
| 583 | */ | 776 | */ |
| 584 | 777 | ||
| 585 | if (gc->pads[GC_PSX] || gc->pads[GC_DDR]) | 778 | if (gc->pad_count[GC_PSX] || gc->pad_count[GC_DDR]) |
| 586 | gc_psx_process_packet(gc); | 779 | gc_psx_process_packet(gc); |
| 587 | 780 | ||
| 588 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 781 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
| @@ -622,25 +815,29 @@ static void gc_close(struct input_dev *dev) | |||
| 622 | 815 | ||
| 623 | static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | 816 | static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) |
| 624 | { | 817 | { |
| 818 | struct gc_pad *pad = &gc->pads[idx]; | ||
| 625 | struct input_dev *input_dev; | 819 | struct input_dev *input_dev; |
| 626 | int i; | 820 | int i; |
| 821 | int err; | ||
| 627 | 822 | ||
| 628 | if (!pad_type) | 823 | if (pad_type < 1 || pad_type >= GC_MAX) { |
| 629 | return 0; | 824 | pr_err("Pad type %d unknown\n", pad_type); |
| 630 | |||
| 631 | if (pad_type < 1 || pad_type > GC_MAX) { | ||
| 632 | printk(KERN_WARNING "gamecon.c: Pad type %d unknown\n", pad_type); | ||
| 633 | return -EINVAL; | 825 | return -EINVAL; |
| 634 | } | 826 | } |
| 635 | 827 | ||
| 636 | gc->dev[idx] = input_dev = input_allocate_device(); | 828 | pad->dev = input_dev = input_allocate_device(); |
| 637 | if (!input_dev) { | 829 | if (!input_dev) { |
| 638 | printk(KERN_ERR "gamecon.c: Not enough memory for input device\n"); | 830 | pr_err("Not enough memory for input device\n"); |
| 639 | return -ENOMEM; | 831 | return -ENOMEM; |
| 640 | } | 832 | } |
| 641 | 833 | ||
| 834 | pad->type = pad_type; | ||
| 835 | |||
| 836 | snprintf(pad->phys, sizeof(pad->phys), | ||
| 837 | "%s/input%d", gc->pd->port->name, idx); | ||
| 838 | |||
| 642 | input_dev->name = gc_names[pad_type]; | 839 | input_dev->name = gc_names[pad_type]; |
| 643 | input_dev->phys = gc->phys[idx]; | 840 | input_dev->phys = pad->phys; |
| 644 | input_dev->id.bustype = BUS_PARPORT; | 841 | input_dev->id.bustype = BUS_PARPORT; |
| 645 | input_dev->id.vendor = 0x0001; | 842 | input_dev->id.vendor = 0x0001; |
| 646 | input_dev->id.product = pad_type; | 843 | input_dev->id.product = pad_type; |
| @@ -659,61 +856,76 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) | |||
| 659 | } else | 856 | } else |
| 660 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 857 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
| 661 | 858 | ||
| 662 | gc->pads[0] |= gc_status_bit[idx]; | 859 | gc->pad_count[pad_type]++; |
| 663 | gc->pads[pad_type] |= gc_status_bit[idx]; | ||
| 664 | 860 | ||
| 665 | switch (pad_type) { | 861 | switch (pad_type) { |
| 666 | 862 | ||
| 667 | case GC_N64: | 863 | case GC_N64: |
| 668 | for (i = 0; i < 10; i++) | 864 | for (i = 0; i < 10; i++) |
| 669 | set_bit(gc_n64_btn[i], input_dev->keybit); | 865 | __set_bit(gc_n64_btn[i], input_dev->keybit); |
| 670 | |||
| 671 | for (i = 0; i < 2; i++) { | ||
| 672 | input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); | ||
| 673 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | ||
| 674 | } | ||
| 675 | |||
| 676 | break; | ||
| 677 | |||
| 678 | case GC_SNESMOUSE: | ||
| 679 | set_bit(BTN_LEFT, input_dev->keybit); | ||
| 680 | set_bit(BTN_RIGHT, input_dev->keybit); | ||
| 681 | set_bit(REL_X, input_dev->relbit); | ||
| 682 | set_bit(REL_Y, input_dev->relbit); | ||
| 683 | break; | ||
| 684 | |||
| 685 | case GC_SNES: | ||
| 686 | for (i = 4; i < 8; i++) | ||
| 687 | set_bit(gc_snes_btn[i], input_dev->keybit); | ||
| 688 | case GC_NES: | ||
| 689 | for (i = 0; i < 4; i++) | ||
| 690 | set_bit(gc_snes_btn[i], input_dev->keybit); | ||
| 691 | break; | ||
| 692 | |||
| 693 | case GC_MULTI2: | ||
| 694 | set_bit(BTN_THUMB, input_dev->keybit); | ||
| 695 | case GC_MULTI: | ||
| 696 | set_bit(BTN_TRIGGER, input_dev->keybit); | ||
| 697 | break; | ||
| 698 | |||
| 699 | case GC_PSX: | ||
| 700 | for (i = 0; i < 6; i++) | ||
| 701 | input_set_abs_params(input_dev, gc_psx_abs[i], 4, 252, 0, 2); | ||
| 702 | for (i = 0; i < 12; i++) | ||
| 703 | set_bit(gc_psx_btn[i], input_dev->keybit); | ||
| 704 | 866 | ||
| 705 | break; | 867 | for (i = 0; i < 2; i++) { |
| 868 | input_set_abs_params(input_dev, ABS_X + i, -127, 126, 0, 2); | ||
| 869 | input_set_abs_params(input_dev, ABS_HAT0X + i, -1, 1, 0, 0); | ||
| 870 | } | ||
| 706 | 871 | ||
| 707 | case GC_DDR: | 872 | err = gc_n64_init_ff(input_dev, idx); |
| 708 | for (i = 0; i < 4; i++) | 873 | if (err) { |
| 709 | set_bit(gc_psx_ddr_btn[i], input_dev->keybit); | 874 | pr_warning("Failed to initiate rumble for N64 device %d\n", idx); |
| 710 | for (i = 0; i < 12; i++) | 875 | goto err_free_dev; |
| 711 | set_bit(gc_psx_btn[i], input_dev->keybit); | 876 | } |
| 712 | 877 | ||
| 713 | break; | 878 | break; |
| 879 | |||
| 880 | case GC_SNESMOUSE: | ||
| 881 | __set_bit(BTN_LEFT, input_dev->keybit); | ||
| 882 | __set_bit(BTN_RIGHT, input_dev->keybit); | ||
| 883 | __set_bit(REL_X, input_dev->relbit); | ||
| 884 | __set_bit(REL_Y, input_dev->relbit); | ||
| 885 | break; | ||
| 886 | |||
| 887 | case GC_SNES: | ||
| 888 | for (i = 4; i < 8; i++) | ||
| 889 | __set_bit(gc_snes_btn[i], input_dev->keybit); | ||
| 890 | case GC_NES: | ||
| 891 | for (i = 0; i < 4; i++) | ||
| 892 | __set_bit(gc_snes_btn[i], input_dev->keybit); | ||
| 893 | break; | ||
| 894 | |||
| 895 | case GC_MULTI2: | ||
| 896 | __set_bit(BTN_THUMB, input_dev->keybit); | ||
| 897 | case GC_MULTI: | ||
| 898 | __set_bit(BTN_TRIGGER, input_dev->keybit); | ||
| 899 | break; | ||
| 900 | |||
| 901 | case GC_PSX: | ||
| 902 | for (i = 0; i < 6; i++) | ||
| 903 | input_set_abs_params(input_dev, | ||
| 904 | gc_psx_abs[i], 4, 252, 0, 2); | ||
| 905 | for (i = 0; i < 12; i++) | ||
| 906 | __set_bit(gc_psx_btn[i], input_dev->keybit); | ||
| 907 | |||
| 908 | break; | ||
| 909 | |||
| 910 | case GC_DDR: | ||
| 911 | for (i = 0; i < 4; i++) | ||
| 912 | __set_bit(gc_psx_ddr_btn[i], input_dev->keybit); | ||
| 913 | for (i = 0; i < 12; i++) | ||
| 914 | __set_bit(gc_psx_btn[i], input_dev->keybit); | ||
| 915 | |||
| 916 | break; | ||
| 714 | } | 917 | } |
| 715 | 918 | ||
| 919 | err = input_register_device(pad->dev); | ||
| 920 | if (err) | ||
| 921 | goto err_free_dev; | ||
| 922 | |||
| 716 | return 0; | 923 | return 0; |
| 924 | |||
| 925 | err_free_dev: | ||
| 926 | input_free_device(pad->dev); | ||
| 927 | pad->dev = NULL; | ||
| 928 | return err; | ||
| 717 | } | 929 | } |
| 718 | 930 | ||
| 719 | static struct gc __init *gc_probe(int parport, int *pads, int n_pads) | 931 | static struct gc __init *gc_probe(int parport, int *pads, int n_pads) |
| @@ -722,52 +934,47 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) | |||
| 722 | struct parport *pp; | 934 | struct parport *pp; |
| 723 | struct pardevice *pd; | 935 | struct pardevice *pd; |
| 724 | int i; | 936 | int i; |
| 937 | int count = 0; | ||
| 725 | int err; | 938 | int err; |
| 726 | 939 | ||
| 727 | pp = parport_find_number(parport); | 940 | pp = parport_find_number(parport); |
| 728 | if (!pp) { | 941 | if (!pp) { |
| 729 | printk(KERN_ERR "gamecon.c: no such parport\n"); | 942 | pr_err("no such parport %d\n", parport); |
| 730 | err = -EINVAL; | 943 | err = -EINVAL; |
| 731 | goto err_out; | 944 | goto err_out; |
| 732 | } | 945 | } |
| 733 | 946 | ||
| 734 | pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 947 | pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
| 735 | if (!pd) { | 948 | if (!pd) { |
| 736 | printk(KERN_ERR "gamecon.c: parport busy already - lp.o loaded?\n"); | 949 | pr_err("parport busy already - lp.o loaded?\n"); |
| 737 | err = -EBUSY; | 950 | err = -EBUSY; |
| 738 | goto err_put_pp; | 951 | goto err_put_pp; |
| 739 | } | 952 | } |
| 740 | 953 | ||
| 741 | gc = kzalloc(sizeof(struct gc), GFP_KERNEL); | 954 | gc = kzalloc(sizeof(struct gc), GFP_KERNEL); |
| 742 | if (!gc) { | 955 | if (!gc) { |
| 743 | printk(KERN_ERR "gamecon.c: Not enough memory\n"); | 956 | pr_err("Not enough memory\n"); |
| 744 | err = -ENOMEM; | 957 | err = -ENOMEM; |
| 745 | goto err_unreg_pardev; | 958 | goto err_unreg_pardev; |
| 746 | } | 959 | } |
| 747 | 960 | ||
| 748 | mutex_init(&gc->mutex); | 961 | mutex_init(&gc->mutex); |
| 749 | gc->pd = pd; | 962 | gc->pd = pd; |
| 750 | init_timer(&gc->timer); | 963 | setup_timer(&gc->timer, gc_timer, (long) gc); |
| 751 | gc->timer.data = (long) gc; | ||
| 752 | gc->timer.function = gc_timer; | ||
| 753 | 964 | ||
| 754 | for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { | 965 | for (i = 0; i < n_pads && i < GC_MAX_DEVICES; i++) { |
| 755 | if (!pads[i]) | 966 | if (!pads[i]) |
| 756 | continue; | 967 | continue; |
| 757 | 968 | ||
| 758 | snprintf(gc->phys[i], sizeof(gc->phys[i]), | ||
| 759 | "%s/input%d", gc->pd->port->name, i); | ||
| 760 | err = gc_setup_pad(gc, i, pads[i]); | 969 | err = gc_setup_pad(gc, i, pads[i]); |
| 761 | if (err) | 970 | if (err) |
| 762 | goto err_unreg_devs; | 971 | goto err_unreg_devs; |
| 763 | 972 | ||
| 764 | err = input_register_device(gc->dev[i]); | 973 | count++; |
| 765 | if (err) | ||
| 766 | goto err_free_dev; | ||
| 767 | } | 974 | } |
| 768 | 975 | ||
| 769 | if (!gc->pads[0]) { | 976 | if (count == 0) { |
| 770 | printk(KERN_ERR "gamecon.c: No valid devices specified\n"); | 977 | pr_err("No valid devices specified\n"); |
| 771 | err = -EINVAL; | 978 | err = -EINVAL; |
| 772 | goto err_free_gc; | 979 | goto err_free_gc; |
| 773 | } | 980 | } |
| @@ -775,12 +982,10 @@ static struct gc __init *gc_probe(int parport, int *pads, int n_pads) | |||
| 775 | parport_put_port(pp); | 982 | parport_put_port(pp); |
| 776 | return gc; | 983 | return gc; |
| 777 | 984 | ||
| 778 | err_free_dev: | ||
| 779 | input_free_device(gc->dev[i]); | ||
| 780 | err_unreg_devs: | 985 | err_unreg_devs: |
| 781 | while (--i >= 0) | 986 | while (--i >= 0) |
| 782 | if (gc->dev[i]) | 987 | if (gc->pads[i].dev) |
| 783 | input_unregister_device(gc->dev[i]); | 988 | input_unregister_device(gc->pads[i].dev); |
| 784 | err_free_gc: | 989 | err_free_gc: |
| 785 | kfree(gc); | 990 | kfree(gc); |
| 786 | err_unreg_pardev: | 991 | err_unreg_pardev: |
| @@ -796,8 +1001,8 @@ static void gc_remove(struct gc *gc) | |||
| 796 | int i; | 1001 | int i; |
| 797 | 1002 | ||
| 798 | for (i = 0; i < GC_MAX_DEVICES; i++) | 1003 | for (i = 0; i < GC_MAX_DEVICES; i++) |
| 799 | if (gc->dev[i]) | 1004 | if (gc->pads[i].dev) |
| 800 | input_unregister_device(gc->dev[i]); | 1005 | input_unregister_device(gc->pads[i].dev); |
| 801 | parport_unregister_device(gc->pd); | 1006 | parport_unregister_device(gc->pd); |
| 802 | kfree(gc); | 1007 | kfree(gc); |
| 803 | } | 1008 | } |
| @@ -813,7 +1018,7 @@ static int __init gc_init(void) | |||
| 813 | continue; | 1018 | continue; |
| 814 | 1019 | ||
| 815 | if (gc_cfg[i].nargs < 2) { | 1020 | if (gc_cfg[i].nargs < 2) { |
| 816 | printk(KERN_ERR "gamecon.c: at least one device must be specified\n"); | 1021 | pr_err("at least one device must be specified\n"); |
| 817 | err = -EINVAL; | 1022 | err = -EINVAL; |
| 818 | break; | 1023 | break; |
| 819 | } | 1024 | } |
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index 67c207f5b1a1..45ac70eae0aa 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
| @@ -277,7 +277,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
| 277 | } | 277 | } |
| 278 | 278 | ||
| 279 | #ifdef RESET_WORKS | 279 | #ifdef RESET_WORKS |
| 280 | if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) || | 280 | if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) && |
| 281 | (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { | 281 | (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) { |
| 282 | err = -ENODEV; | 282 | err = -ENODEV; |
| 283 | goto fail2; | 283 | goto fail2; |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index f6c688cae334..b1edd778639c 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
| @@ -210,7 +210,7 @@ static int iforce_open(struct input_dev *dev) | |||
| 210 | return 0; | 210 | return 0; |
| 211 | } | 211 | } |
| 212 | 212 | ||
| 213 | static void iforce_release(struct input_dev *dev) | 213 | static void iforce_close(struct input_dev *dev) |
| 214 | { | 214 | { |
| 215 | struct iforce *iforce = input_get_drvdata(dev); | 215 | struct iforce *iforce = input_get_drvdata(dev); |
| 216 | int i; | 216 | int i; |
| @@ -228,30 +228,17 @@ static void iforce_release(struct input_dev *dev) | |||
| 228 | 228 | ||
| 229 | /* Disable force feedback playback */ | 229 | /* Disable force feedback playback */ |
| 230 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); | 230 | iforce_send_packet(iforce, FF_CMD_ENABLE, "\001"); |
| 231 | /* Wait for the command to complete */ | ||
| 232 | wait_event_interruptible(iforce->wait, | ||
| 233 | !test_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags)); | ||
| 231 | } | 234 | } |
| 232 | 235 | ||
| 233 | switch (iforce->bus) { | 236 | switch (iforce->bus) { |
| 234 | #ifdef CONFIG_JOYSTICK_IFORCE_USB | 237 | #ifdef CONFIG_JOYSTICK_IFORCE_USB |
| 235 | case IFORCE_USB: | ||
| 236 | usb_kill_urb(iforce->irq); | ||
| 237 | |||
| 238 | /* The device was unplugged before the file | ||
| 239 | * was released */ | ||
| 240 | if (iforce->usbdev == NULL) { | ||
| 241 | iforce_delete_device(iforce); | ||
| 242 | kfree(iforce); | ||
| 243 | } | ||
| 244 | break; | ||
| 245 | #endif | ||
| 246 | } | ||
| 247 | } | ||
| 248 | |||
| 249 | void iforce_delete_device(struct iforce *iforce) | ||
| 250 | { | ||
| 251 | switch (iforce->bus) { | ||
| 252 | #ifdef CONFIG_JOYSTICK_IFORCE_USB | ||
| 253 | case IFORCE_USB: | 238 | case IFORCE_USB: |
| 254 | iforce_usb_delete(iforce); | 239 | usb_kill_urb(iforce->irq); |
| 240 | usb_kill_urb(iforce->out); | ||
| 241 | usb_kill_urb(iforce->ctrl); | ||
| 255 | break; | 242 | break; |
| 256 | #endif | 243 | #endif |
| 257 | #ifdef CONFIG_JOYSTICK_IFORCE_232 | 244 | #ifdef CONFIG_JOYSTICK_IFORCE_232 |
| @@ -303,7 +290,7 @@ int iforce_init_device(struct iforce *iforce) | |||
| 303 | 290 | ||
| 304 | input_dev->name = "Unknown I-Force device"; | 291 | input_dev->name = "Unknown I-Force device"; |
| 305 | input_dev->open = iforce_open; | 292 | input_dev->open = iforce_open; |
| 306 | input_dev->close = iforce_release; | 293 | input_dev->close = iforce_close; |
| 307 | 294 | ||
| 308 | /* | 295 | /* |
| 309 | * On-device memory allocation. | 296 | * On-device memory allocation. |
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 9f289d8f52c6..b41303d3ec54 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
| @@ -109,6 +109,7 @@ static void iforce_usb_out(struct urb *urb) | |||
| 109 | struct iforce *iforce = urb->context; | 109 | struct iforce *iforce = urb->context; |
| 110 | 110 | ||
| 111 | if (urb->status) { | 111 | if (urb->status) { |
| 112 | clear_bit(IFORCE_XMIT_RUNNING, iforce->xmit_flags); | ||
| 112 | dbg("urb->status %d, exiting", urb->status); | 113 | dbg("urb->status %d, exiting", urb->status); |
| 113 | return; | 114 | return; |
| 114 | } | 115 | } |
| @@ -186,33 +187,19 @@ fail: | |||
| 186 | return err; | 187 | return err; |
| 187 | } | 188 | } |
| 188 | 189 | ||
| 189 | /* Called by iforce_delete() */ | ||
| 190 | void iforce_usb_delete(struct iforce* iforce) | ||
| 191 | { | ||
| 192 | usb_kill_urb(iforce->irq); | ||
| 193 | usb_kill_urb(iforce->out); | ||
| 194 | usb_kill_urb(iforce->ctrl); | ||
| 195 | |||
| 196 | usb_free_urb(iforce->irq); | ||
| 197 | usb_free_urb(iforce->out); | ||
| 198 | usb_free_urb(iforce->ctrl); | ||
| 199 | } | ||
| 200 | |||
| 201 | static void iforce_usb_disconnect(struct usb_interface *intf) | 190 | static void iforce_usb_disconnect(struct usb_interface *intf) |
| 202 | { | 191 | { |
| 203 | struct iforce *iforce = usb_get_intfdata(intf); | 192 | struct iforce *iforce = usb_get_intfdata(intf); |
| 204 | int open = 0; /* FIXME! iforce->dev.handle->open; */ | ||
| 205 | 193 | ||
| 206 | usb_set_intfdata(intf, NULL); | 194 | usb_set_intfdata(intf, NULL); |
| 207 | if (iforce) { | ||
| 208 | iforce->usbdev = NULL; | ||
| 209 | input_unregister_device(iforce->dev); | ||
| 210 | 195 | ||
| 211 | if (!open) { | 196 | input_unregister_device(iforce->dev); |
| 212 | iforce_delete_device(iforce); | 197 | |
| 213 | kfree(iforce); | 198 | usb_free_urb(iforce->irq); |
| 214 | } | 199 | usb_free_urb(iforce->out); |
| 215 | } | 200 | usb_free_urb(iforce->ctrl); |
| 201 | |||
| 202 | kfree(iforce); | ||
| 216 | } | 203 | } |
| 217 | 204 | ||
| 218 | static struct usb_device_id iforce_usb_ids [] = { | 205 | static struct usb_device_id iforce_usb_ids [] = { |
diff --git a/drivers/input/joystick/iforce/iforce.h b/drivers/input/joystick/iforce/iforce.h index f2d91f4028ca..9f494b75848a 100644 --- a/drivers/input/joystick/iforce/iforce.h +++ b/drivers/input/joystick/iforce/iforce.h | |||
| @@ -150,11 +150,9 @@ void iforce_serial_xmit(struct iforce *iforce); | |||
| 150 | 150 | ||
| 151 | /* iforce-usb.c */ | 151 | /* iforce-usb.c */ |
| 152 | void iforce_usb_xmit(struct iforce *iforce); | 152 | void iforce_usb_xmit(struct iforce *iforce); |
| 153 | void iforce_usb_delete(struct iforce *iforce); | ||
| 154 | 153 | ||
| 155 | /* iforce-main.c */ | 154 | /* iforce-main.c */ |
| 156 | int iforce_init_device(struct iforce *iforce); | 155 | int iforce_init_device(struct iforce *iforce); |
| 157 | void iforce_delete_device(struct iforce *iforce); | ||
| 158 | 156 | ||
| 159 | /* iforce-packets.c */ | 157 | /* iforce-packets.c */ |
| 160 | int iforce_control_playback(struct iforce*, u16 id, unsigned int); | 158 | int iforce_control_playback(struct iforce*, u16 id, unsigned int); |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index b6f859869540..d53b9e900234 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/mutex.h> | 37 | #include <linux/mutex.h> |
| 38 | #include <linux/slab.h> | ||
| 38 | 39 | ||
| 39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 40 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 40 | MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); | 41 | MODULE_DESCRIPTION("TurboGraFX parallel port interface driver"); |
diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 79e3edcced1a..9b3353b404da 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c | |||
| @@ -86,9 +86,8 @@ | |||
| 86 | 86 | ||
| 87 | /* xbox d-pads should map to buttons, as is required for DDR pads | 87 | /* xbox d-pads should map to buttons, as is required for DDR pads |
| 88 | but we map them to axes when possible to simplify things */ | 88 | but we map them to axes when possible to simplify things */ |
| 89 | #define MAP_DPAD_TO_BUTTONS 0 | 89 | #define MAP_DPAD_TO_BUTTONS (1 << 0) |
| 90 | #define MAP_DPAD_TO_AXES 1 | 90 | #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) |
| 91 | #define MAP_DPAD_UNKNOWN 2 | ||
| 92 | 91 | ||
| 93 | #define XTYPE_XBOX 0 | 92 | #define XTYPE_XBOX 0 |
| 94 | #define XTYPE_XBOX360 1 | 93 | #define XTYPE_XBOX360 1 |
| @@ -99,55 +98,61 @@ static int dpad_to_buttons; | |||
| 99 | module_param(dpad_to_buttons, bool, S_IRUGO); | 98 | module_param(dpad_to_buttons, bool, S_IRUGO); |
| 100 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); | 99 | MODULE_PARM_DESC(dpad_to_buttons, "Map D-PAD to buttons rather than axes for unknown pads"); |
| 101 | 100 | ||
| 101 | static int triggers_to_buttons; | ||
| 102 | module_param(triggers_to_buttons, bool, S_IRUGO); | ||
| 103 | MODULE_PARM_DESC(triggers_to_buttons, "Map triggers to buttons rather than axes for unknown pads"); | ||
| 104 | |||
| 102 | static const struct xpad_device { | 105 | static const struct xpad_device { |
| 103 | u16 idVendor; | 106 | u16 idVendor; |
| 104 | u16 idProduct; | 107 | u16 idProduct; |
| 105 | char *name; | 108 | char *name; |
| 106 | u8 dpad_mapping; | 109 | u8 mapping; |
| 107 | u8 xtype; | 110 | u8 xtype; |
| 108 | } xpad_device[] = { | 111 | } xpad_device[] = { |
| 109 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 112 | { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, |
| 110 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 113 | { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, |
| 111 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 114 | { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, |
| 112 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 115 | { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, |
| 113 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, | 116 | { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, |
| 114 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 117 | { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 115 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 118 | { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, |
| 116 | { 0x046d, 0xc242, "Logitech Chillstream Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 119 | { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, |
| 117 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 120 | { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, |
| 118 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 121 | { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, |
| 119 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 122 | { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, |
| 120 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 123 | { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, |
| 121 | { 0x0738, 0x4516, "Mad Catz Control Pad", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 124 | { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, |
| 122 | { 0x0738, 0x4522, "Mad Catz LumiCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 125 | { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX }, |
| 123 | { 0x0738, 0x4526, "Mad Catz Control Pad Pro", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 126 | { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, |
| 124 | { 0x0738, 0x4536, "Mad Catz MicroCON", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 127 | { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX }, |
| 125 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 128 | { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 126 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 129 | { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, |
| 127 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 130 | { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
| 131 | { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, | ||
| 128 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 132 | { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 129 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 133 | { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, |
| 130 | { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 134 | { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, |
| 131 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 135 | { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, |
| 132 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 136 | { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, |
| 133 | { 0x0e4c, 0x1097, "Radica Gamester Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 137 | { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, |
| 134 | { 0x0e4c, 0x2390, "Radica Games Jtech Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 138 | { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, |
| 135 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 139 | { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, |
| 136 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 140 | { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, |
| 137 | { 0x0e6f, 0x0006, "Edge wireless Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 141 | { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, |
| 138 | { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 142 | { 0x0e6f, 0x0006, "Pelican 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, |
| 139 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 143 | { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, |
| 140 | { 0x0f30, 0x0202, "Joytech Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 144 | { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, |
| 141 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 145 | { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, |
| 142 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 146 | { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, |
| 143 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 147 | { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 144 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 148 | { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, |
| 145 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, | 149 | { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, |
| 146 | { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 150 | { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, |
| 147 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", MAP_DPAD_TO_AXES, XTYPE_XBOX360 }, | 151 | { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, |
| 148 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, | 152 | { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, |
| 149 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", MAP_DPAD_TO_AXES, XTYPE_XBOX }, | 153 | { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, |
| 150 | { 0x0000, 0x0000, "Generic X-Box pad", MAP_DPAD_UNKNOWN, XTYPE_UNKNOWN } | 154 | { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, |
| 155 | { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } | ||
| 151 | }; | 156 | }; |
| 152 | 157 | ||
| 153 | /* buttons shared with xbox and xbox360 */ | 158 | /* buttons shared with xbox and xbox360 */ |
| @@ -163,13 +168,20 @@ static const signed short xpad_btn[] = { | |||
| 163 | -1 /* terminating entry */ | 168 | -1 /* terminating entry */ |
| 164 | }; | 169 | }; |
| 165 | 170 | ||
| 166 | /* only used if MAP_DPAD_TO_BUTTONS */ | 171 | /* used when dpad is mapped to nuttons */ |
| 167 | static const signed short xpad_btn_pad[] = { | 172 | static const signed short xpad_btn_pad[] = { |
| 168 | BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ | 173 | BTN_LEFT, BTN_RIGHT, /* d-pad left, right */ |
| 169 | BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ | 174 | BTN_0, BTN_1, /* d-pad up, down (XXX names??) */ |
| 170 | -1 /* terminating entry */ | 175 | -1 /* terminating entry */ |
| 171 | }; | 176 | }; |
| 172 | 177 | ||
| 178 | /* used when triggers are mapped to buttons */ | ||
| 179 | static const signed short xpad_btn_triggers[] = { | ||
| 180 | BTN_TL2, BTN_TR2, /* triggers left/right */ | ||
| 181 | -1 | ||
| 182 | }; | ||
| 183 | |||
| 184 | |||
| 173 | static const signed short xpad360_btn[] = { /* buttons for x360 controller */ | 185 | static const signed short xpad360_btn[] = { /* buttons for x360 controller */ |
| 174 | BTN_TL, BTN_TR, /* Button LB/RB */ | 186 | BTN_TL, BTN_TR, /* Button LB/RB */ |
| 175 | BTN_MODE, /* The big X button */ | 187 | BTN_MODE, /* The big X button */ |
| @@ -179,16 +191,21 @@ static const signed short xpad360_btn[] = { /* buttons for x360 controller */ | |||
| 179 | static const signed short xpad_abs[] = { | 191 | static const signed short xpad_abs[] = { |
| 180 | ABS_X, ABS_Y, /* left stick */ | 192 | ABS_X, ABS_Y, /* left stick */ |
| 181 | ABS_RX, ABS_RY, /* right stick */ | 193 | ABS_RX, ABS_RY, /* right stick */ |
| 182 | ABS_Z, ABS_RZ, /* triggers left/right */ | ||
| 183 | -1 /* terminating entry */ | 194 | -1 /* terminating entry */ |
| 184 | }; | 195 | }; |
| 185 | 196 | ||
| 186 | /* only used if MAP_DPAD_TO_AXES */ | 197 | /* used when dpad is mapped to axes */ |
| 187 | static const signed short xpad_abs_pad[] = { | 198 | static const signed short xpad_abs_pad[] = { |
| 188 | ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ | 199 | ABS_HAT0X, ABS_HAT0Y, /* d-pad axes */ |
| 189 | -1 /* terminating entry */ | 200 | -1 /* terminating entry */ |
| 190 | }; | 201 | }; |
| 191 | 202 | ||
| 203 | /* used when triggers are mapped to axes */ | ||
| 204 | static const signed short xpad_abs_triggers[] = { | ||
| 205 | ABS_Z, ABS_RZ, /* triggers left/right */ | ||
| 206 | -1 | ||
| 207 | }; | ||
| 208 | |||
| 192 | /* Xbox 360 has a vendor-specific class, so we cannot match it with only | 209 | /* Xbox 360 has a vendor-specific class, so we cannot match it with only |
| 193 | * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we | 210 | * USB_INTERFACE_INFO (also specifically refused by USB subsystem), so we |
| 194 | * match against vendor id as well. Wired Xbox 360 devices have protocol 1, | 211 | * match against vendor id as well. Wired Xbox 360 devices have protocol 1, |
| @@ -212,6 +229,7 @@ static struct usb_device_id xpad_table [] = { | |||
| 212 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ | 229 | XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ |
| 213 | XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ | 230 | XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ |
| 214 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ | 231 | XPAD_XBOX360_VENDOR(0x1bad), /* Rock Band Drums */ |
| 232 | XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ | ||
| 215 | { } | 233 | { } |
| 216 | }; | 234 | }; |
| 217 | 235 | ||
| @@ -243,7 +261,7 @@ struct usb_xpad { | |||
| 243 | 261 | ||
| 244 | char phys[64]; /* physical device path */ | 262 | char phys[64]; /* physical device path */ |
| 245 | 263 | ||
| 246 | int dpad_mapping; /* map d-pad to buttons or to axes */ | 264 | int mapping; /* map d-pad to buttons or to axes */ |
| 247 | int xtype; /* type of xbox device */ | 265 | int xtype; /* type of xbox device */ |
| 248 | }; | 266 | }; |
| 249 | 267 | ||
| @@ -274,20 +292,25 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
| 274 | ~(__s16) le16_to_cpup((__le16 *)(data + 18))); | 292 | ~(__s16) le16_to_cpup((__le16 *)(data + 18))); |
| 275 | 293 | ||
| 276 | /* triggers left/right */ | 294 | /* triggers left/right */ |
| 277 | input_report_abs(dev, ABS_Z, data[10]); | 295 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { |
| 278 | input_report_abs(dev, ABS_RZ, data[11]); | 296 | input_report_key(dev, BTN_TL2, data[10]); |
| 297 | input_report_key(dev, BTN_TR2, data[11]); | ||
| 298 | } else { | ||
| 299 | input_report_abs(dev, ABS_Z, data[10]); | ||
| 300 | input_report_abs(dev, ABS_RZ, data[11]); | ||
| 301 | } | ||
| 279 | 302 | ||
| 280 | /* digital pad */ | 303 | /* digital pad */ |
| 281 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 304 | if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { |
| 282 | input_report_abs(dev, ABS_HAT0X, | ||
| 283 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
| 284 | input_report_abs(dev, ABS_HAT0Y, | ||
| 285 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 286 | } else /* xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS */ { | ||
| 287 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 305 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
| 288 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | 306 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); |
| 289 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ | 307 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ |
| 290 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ | 308 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ |
| 309 | } else { | ||
| 310 | input_report_abs(dev, ABS_HAT0X, | ||
| 311 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
| 312 | input_report_abs(dev, ABS_HAT0Y, | ||
| 313 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 291 | } | 314 | } |
| 292 | 315 | ||
| 293 | /* start/back buttons and stick press left/right */ | 316 | /* start/back buttons and stick press left/right */ |
| @@ -325,17 +348,17 @@ static void xpad360_process_packet(struct usb_xpad *xpad, | |||
| 325 | struct input_dev *dev = xpad->dev; | 348 | struct input_dev *dev = xpad->dev; |
| 326 | 349 | ||
| 327 | /* digital pad */ | 350 | /* digital pad */ |
| 328 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) { | 351 | if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { |
| 329 | input_report_abs(dev, ABS_HAT0X, | ||
| 330 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
| 331 | input_report_abs(dev, ABS_HAT0Y, | ||
| 332 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 333 | } else if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) { | ||
| 334 | /* dpad as buttons (right, left, down, up) */ | 352 | /* dpad as buttons (right, left, down, up) */ |
| 335 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); | 353 | input_report_key(dev, BTN_LEFT, data[2] & 0x04); |
| 336 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); | 354 | input_report_key(dev, BTN_RIGHT, data[2] & 0x08); |
| 337 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ | 355 | input_report_key(dev, BTN_0, data[2] & 0x01); /* up */ |
| 338 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ | 356 | input_report_key(dev, BTN_1, data[2] & 0x02); /* down */ |
| 357 | } else { | ||
| 358 | input_report_abs(dev, ABS_HAT0X, | ||
| 359 | !!(data[2] & 0x08) - !!(data[2] & 0x04)); | ||
| 360 | input_report_abs(dev, ABS_HAT0Y, | ||
| 361 | !!(data[2] & 0x02) - !!(data[2] & 0x01)); | ||
| 339 | } | 362 | } |
| 340 | 363 | ||
| 341 | /* start/back buttons */ | 364 | /* start/back buttons */ |
| @@ -368,8 +391,13 @@ static void xpad360_process_packet(struct usb_xpad *xpad, | |||
| 368 | ~(__s16) le16_to_cpup((__le16 *)(data + 12))); | 391 | ~(__s16) le16_to_cpup((__le16 *)(data + 12))); |
| 369 | 392 | ||
| 370 | /* triggers left/right */ | 393 | /* triggers left/right */ |
| 371 | input_report_abs(dev, ABS_Z, data[4]); | 394 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { |
| 372 | input_report_abs(dev, ABS_RZ, data[5]); | 395 | input_report_key(dev, BTN_TL2, data[4]); |
| 396 | input_report_key(dev, BTN_TR2, data[5]); | ||
| 397 | } else { | ||
| 398 | input_report_abs(dev, ABS_Z, data[4]); | ||
| 399 | input_report_abs(dev, ABS_RZ, data[5]); | ||
| 400 | } | ||
| 373 | 401 | ||
| 374 | input_sync(dev); | 402 | input_sync(dev); |
| 375 | } | 403 | } |
| @@ -443,7 +471,7 @@ static void xpad_irq_in(struct urb *urb) | |||
| 443 | } | 471 | } |
| 444 | 472 | ||
| 445 | exit: | 473 | exit: |
| 446 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 474 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| 447 | if (retval) | 475 | if (retval) |
| 448 | err ("%s - usb_submit_urb failed with result %d", | 476 | err ("%s - usb_submit_urb failed with result %d", |
| 449 | __func__, retval); | 477 | __func__, retval); |
| @@ -502,7 +530,7 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
| 502 | struct usb_endpoint_descriptor *ep_irq_out; | 530 | struct usb_endpoint_descriptor *ep_irq_out; |
| 503 | int error = -ENOMEM; | 531 | int error = -ENOMEM; |
| 504 | 532 | ||
| 505 | if (xpad->xtype != XTYPE_XBOX360) | 533 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) |
| 506 | return 0; | 534 | return 0; |
| 507 | 535 | ||
| 508 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, | 536 | xpad->odata = usb_buffer_alloc(xpad->udev, XPAD_PKT_LEN, |
| @@ -532,13 +560,13 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) | |||
| 532 | 560 | ||
| 533 | static void xpad_stop_output(struct usb_xpad *xpad) | 561 | static void xpad_stop_output(struct usb_xpad *xpad) |
| 534 | { | 562 | { |
| 535 | if (xpad->xtype == XTYPE_XBOX360) | 563 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) |
| 536 | usb_kill_urb(xpad->irq_out); | 564 | usb_kill_urb(xpad->irq_out); |
| 537 | } | 565 | } |
| 538 | 566 | ||
| 539 | static void xpad_deinit_output(struct usb_xpad *xpad) | 567 | static void xpad_deinit_output(struct usb_xpad *xpad) |
| 540 | { | 568 | { |
| 541 | if (xpad->xtype == XTYPE_XBOX360) { | 569 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX) { |
| 542 | usb_free_urb(xpad->irq_out); | 570 | usb_free_urb(xpad->irq_out); |
| 543 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, | 571 | usb_buffer_free(xpad->udev, XPAD_PKT_LEN, |
| 544 | xpad->odata, xpad->odata_dma); | 572 | xpad->odata, xpad->odata_dma); |
| @@ -551,24 +579,45 @@ static void xpad_stop_output(struct usb_xpad *xpad) {} | |||
| 551 | #endif | 579 | #endif |
| 552 | 580 | ||
| 553 | #ifdef CONFIG_JOYSTICK_XPAD_FF | 581 | #ifdef CONFIG_JOYSTICK_XPAD_FF |
| 554 | static int xpad_play_effect(struct input_dev *dev, void *data, | 582 | static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) |
| 555 | struct ff_effect *effect) | ||
| 556 | { | 583 | { |
| 557 | struct usb_xpad *xpad = input_get_drvdata(dev); | 584 | struct usb_xpad *xpad = input_get_drvdata(dev); |
| 558 | 585 | ||
| 559 | if (effect->type == FF_RUMBLE) { | 586 | if (effect->type == FF_RUMBLE) { |
| 560 | __u16 strong = effect->u.rumble.strong_magnitude; | 587 | __u16 strong = effect->u.rumble.strong_magnitude; |
| 561 | __u16 weak = effect->u.rumble.weak_magnitude; | 588 | __u16 weak = effect->u.rumble.weak_magnitude; |
| 562 | xpad->odata[0] = 0x00; | 589 | |
| 563 | xpad->odata[1] = 0x08; | 590 | switch (xpad->xtype) { |
| 564 | xpad->odata[2] = 0x00; | 591 | |
| 565 | xpad->odata[3] = strong / 256; | 592 | case XTYPE_XBOX: |
| 566 | xpad->odata[4] = weak / 256; | 593 | xpad->odata[0] = 0x00; |
| 567 | xpad->odata[5] = 0x00; | 594 | xpad->odata[1] = 0x06; |
| 568 | xpad->odata[6] = 0x00; | 595 | xpad->odata[2] = 0x00; |
| 569 | xpad->odata[7] = 0x00; | 596 | xpad->odata[3] = strong / 256; /* left actuator */ |
| 570 | xpad->irq_out->transfer_buffer_length = 8; | 597 | xpad->odata[4] = 0x00; |
| 571 | usb_submit_urb(xpad->irq_out, GFP_KERNEL); | 598 | xpad->odata[5] = weak / 256; /* right actuator */ |
| 599 | xpad->irq_out->transfer_buffer_length = 6; | ||
| 600 | |||
| 601 | return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); | ||
| 602 | |||
| 603 | case XTYPE_XBOX360: | ||
| 604 | xpad->odata[0] = 0x00; | ||
| 605 | xpad->odata[1] = 0x08; | ||
| 606 | xpad->odata[2] = 0x00; | ||
| 607 | xpad->odata[3] = strong / 256; /* left actuator? */ | ||
| 608 | xpad->odata[4] = weak / 256; /* right actuator? */ | ||
| 609 | xpad->odata[5] = 0x00; | ||
| 610 | xpad->odata[6] = 0x00; | ||
| 611 | xpad->odata[7] = 0x00; | ||
| 612 | xpad->irq_out->transfer_buffer_length = 8; | ||
| 613 | |||
| 614 | return usb_submit_urb(xpad->irq_out, GFP_ATOMIC); | ||
| 615 | |||
| 616 | default: | ||
| 617 | dbg("%s - rumble command sent to unsupported xpad type: %d", | ||
| 618 | __func__, xpad->xtype); | ||
| 619 | return -1; | ||
| 620 | } | ||
| 572 | } | 621 | } |
| 573 | 622 | ||
| 574 | return 0; | 623 | return 0; |
| @@ -576,7 +625,7 @@ static int xpad_play_effect(struct input_dev *dev, void *data, | |||
| 576 | 625 | ||
| 577 | static int xpad_init_ff(struct usb_xpad *xpad) | 626 | static int xpad_init_ff(struct usb_xpad *xpad) |
| 578 | { | 627 | { |
| 579 | if (xpad->xtype != XTYPE_XBOX360) | 628 | if (xpad->xtype != XTYPE_XBOX360 && xpad->xtype != XTYPE_XBOX) |
| 580 | return 0; | 629 | return 0; |
| 581 | 630 | ||
| 582 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); | 631 | input_set_capability(xpad->dev, EV_FF, FF_RUMBLE); |
| @@ -709,11 +758,11 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) | |||
| 709 | input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); | 758 | input_set_abs_params(input_dev, abs, -32768, 32767, 16, 128); |
| 710 | break; | 759 | break; |
| 711 | case ABS_Z: | 760 | case ABS_Z: |
| 712 | case ABS_RZ: /* the triggers */ | 761 | case ABS_RZ: /* the triggers (if mapped to axes) */ |
| 713 | input_set_abs_params(input_dev, abs, 0, 255, 0, 0); | 762 | input_set_abs_params(input_dev, abs, 0, 255, 0, 0); |
| 714 | break; | 763 | break; |
| 715 | case ABS_HAT0X: | 764 | case ABS_HAT0X: |
| 716 | case ABS_HAT0Y: /* the d-pad (only if MAP_DPAD_TO_AXES) */ | 765 | case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ |
| 717 | input_set_abs_params(input_dev, abs, -1, 1, 0, 0); | 766 | input_set_abs_params(input_dev, abs, -1, 1, 0, 0); |
| 718 | break; | 767 | break; |
| 719 | } | 768 | } |
| @@ -749,10 +798,9 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 749 | goto fail2; | 798 | goto fail2; |
| 750 | 799 | ||
| 751 | xpad->udev = udev; | 800 | xpad->udev = udev; |
| 752 | xpad->dpad_mapping = xpad_device[i].dpad_mapping; | 801 | xpad->mapping = xpad_device[i].mapping; |
| 753 | xpad->xtype = xpad_device[i].xtype; | 802 | xpad->xtype = xpad_device[i].xtype; |
| 754 | if (xpad->dpad_mapping == MAP_DPAD_UNKNOWN) | 803 | |
| 755 | xpad->dpad_mapping = !dpad_to_buttons; | ||
| 756 | if (xpad->xtype == XTYPE_UNKNOWN) { | 804 | if (xpad->xtype == XTYPE_UNKNOWN) { |
| 757 | if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { | 805 | if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { |
| 758 | if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) | 806 | if (intf->cur_altsetting->desc.bInterfaceProtocol == 129) |
| @@ -761,7 +809,13 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 761 | xpad->xtype = XTYPE_XBOX360; | 809 | xpad->xtype = XTYPE_XBOX360; |
| 762 | } else | 810 | } else |
| 763 | xpad->xtype = XTYPE_XBOX; | 811 | xpad->xtype = XTYPE_XBOX; |
| 812 | |||
| 813 | if (dpad_to_buttons) | ||
| 814 | xpad->mapping |= MAP_DPAD_TO_BUTTONS; | ||
| 815 | if (triggers_to_buttons) | ||
| 816 | xpad->mapping |= MAP_TRIGGERS_TO_BUTTONS; | ||
| 764 | } | 817 | } |
| 818 | |||
| 765 | xpad->dev = input_dev; | 819 | xpad->dev = input_dev; |
| 766 | usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); | 820 | usb_make_path(udev, xpad->phys, sizeof(xpad->phys)); |
| 767 | strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); | 821 | strlcat(xpad->phys, "/input0", sizeof(xpad->phys)); |
| @@ -778,25 +832,37 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 778 | 832 | ||
| 779 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 833 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 780 | 834 | ||
| 781 | /* set up buttons */ | 835 | /* set up standard buttons and axes */ |
| 782 | for (i = 0; xpad_common_btn[i] >= 0; i++) | 836 | for (i = 0; xpad_common_btn[i] >= 0; i++) |
| 783 | set_bit(xpad_common_btn[i], input_dev->keybit); | 837 | __set_bit(xpad_common_btn[i], input_dev->keybit); |
| 784 | if ((xpad->xtype == XTYPE_XBOX360) || (xpad->xtype == XTYPE_XBOX360W)) | ||
| 785 | for (i = 0; xpad360_btn[i] >= 0; i++) | ||
| 786 | set_bit(xpad360_btn[i], input_dev->keybit); | ||
| 787 | else | ||
| 788 | for (i = 0; xpad_btn[i] >= 0; i++) | ||
| 789 | set_bit(xpad_btn[i], input_dev->keybit); | ||
| 790 | if (xpad->dpad_mapping == MAP_DPAD_TO_BUTTONS) | ||
| 791 | for (i = 0; xpad_btn_pad[i] >= 0; i++) | ||
| 792 | set_bit(xpad_btn_pad[i], input_dev->keybit); | ||
| 793 | 838 | ||
| 794 | /* set up axes */ | ||
| 795 | for (i = 0; xpad_abs[i] >= 0; i++) | 839 | for (i = 0; xpad_abs[i] >= 0; i++) |
| 796 | xpad_set_up_abs(input_dev, xpad_abs[i]); | 840 | xpad_set_up_abs(input_dev, xpad_abs[i]); |
| 797 | if (xpad->dpad_mapping == MAP_DPAD_TO_AXES) | 841 | |
| 842 | /* Now set up model-specific ones */ | ||
| 843 | if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W) { | ||
| 844 | for (i = 0; xpad360_btn[i] >= 0; i++) | ||
| 845 | __set_bit(xpad360_btn[i], input_dev->keybit); | ||
| 846 | } else { | ||
| 847 | for (i = 0; xpad_btn[i] >= 0; i++) | ||
| 848 | __set_bit(xpad_btn[i], input_dev->keybit); | ||
| 849 | } | ||
| 850 | |||
| 851 | if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { | ||
| 852 | for (i = 0; xpad_btn_pad[i] >= 0; i++) | ||
| 853 | __set_bit(xpad_btn_pad[i], input_dev->keybit); | ||
| 854 | } else { | ||
| 798 | for (i = 0; xpad_abs_pad[i] >= 0; i++) | 855 | for (i = 0; xpad_abs_pad[i] >= 0; i++) |
| 799 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); | 856 | xpad_set_up_abs(input_dev, xpad_abs_pad[i]); |
| 857 | } | ||
| 858 | |||
| 859 | if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { | ||
| 860 | for (i = 0; xpad_btn_triggers[i] >= 0; i++) | ||
| 861 | __set_bit(xpad_btn_triggers[i], input_dev->keybit); | ||
| 862 | } else { | ||
| 863 | for (i = 0; xpad_abs_triggers[i] >= 0; i++) | ||
| 864 | xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); | ||
| 865 | } | ||
| 800 | 866 | ||
| 801 | error = xpad_init_output(intf, xpad); | 867 | error = xpad_init_output(intf, xpad); |
| 802 | if (error) | 868 | if (error) |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index ee98b1bc5d89..64c102355f53 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -24,11 +24,21 @@ config KEYBOARD_AAED2000 | |||
| 24 | To compile this driver as a module, choose M here: the | 24 | To compile this driver as a module, choose M here: the |
| 25 | module will be called aaed2000_kbd. | 25 | module will be called aaed2000_kbd. |
| 26 | 26 | ||
| 27 | config KEYBOARD_ADP5520 | ||
| 28 | tristate "Keypad Support for ADP5520 PMIC" | ||
| 29 | depends on PMIC_ADP5520 | ||
| 30 | help | ||
| 31 | This option enables support for the keypad scan matrix | ||
| 32 | on Analog Devices ADP5520 PMICs. | ||
| 33 | |||
| 34 | To compile this driver as a module, choose M here: the module will | ||
| 35 | be called adp5520-keys. | ||
| 36 | |||
| 27 | config KEYBOARD_ADP5588 | 37 | config KEYBOARD_ADP5588 |
| 28 | tristate "ADP5588 I2C QWERTY Keypad and IO Expander" | 38 | tristate "ADP5588/87 I2C QWERTY Keypad and IO Expander" |
| 29 | depends on I2C | 39 | depends on I2C |
| 30 | help | 40 | help |
| 31 | Say Y here if you want to use a ADP5588 attached to your | 41 | Say Y here if you want to use a ADP5588/87 attached to your |
| 32 | system I2C bus. | 42 | system I2C bus. |
| 33 | 43 | ||
| 34 | To compile this driver as a module, choose M here: the | 44 | To compile this driver as a module, choose M here: the |
| @@ -134,13 +144,15 @@ config KEYBOARD_BFIN | |||
| 134 | module will be called bf54x-keys. | 144 | module will be called bf54x-keys. |
| 135 | 145 | ||
| 136 | config KEYBOARD_CORGI | 146 | config KEYBOARD_CORGI |
| 137 | tristate "Corgi keyboard" | 147 | tristate "Corgi keyboard (deprecated)" |
| 138 | depends on PXA_SHARPSL | 148 | depends on PXA_SHARPSL |
| 139 | default y | ||
| 140 | help | 149 | help |
| 141 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | 150 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx |
| 142 | series of PDAs. | 151 | series of PDAs. |
| 143 | 152 | ||
| 153 | This driver is now deprecated, use generic GPIO based matrix | ||
| 154 | keyboard driver instead. | ||
| 155 | |||
| 144 | To compile this driver as a module, choose M here: the | 156 | To compile this driver as a module, choose M here: the |
| 145 | module will be called corgikbd. | 157 | module will be called corgikbd. |
| 146 | 158 | ||
| @@ -282,6 +294,15 @@ config KEYBOARD_MAX7359 | |||
| 282 | To compile this driver as a module, choose M here: the | 294 | To compile this driver as a module, choose M here: the |
| 283 | module will be called max7359_keypad. | 295 | module will be called max7359_keypad. |
| 284 | 296 | ||
| 297 | config KEYBOARD_IMX | ||
| 298 | tristate "IMX keypad support" | ||
| 299 | depends on ARCH_MXC | ||
| 300 | help | ||
| 301 | Enable support for IMX keypad port. | ||
| 302 | |||
| 303 | To compile this driver as a module, choose M here: the | ||
| 304 | module will be called imx_keypad. | ||
| 305 | |||
| 285 | config KEYBOARD_NEWTON | 306 | config KEYBOARD_NEWTON |
| 286 | tristate "Newton keyboard" | 307 | tristate "Newton keyboard" |
| 287 | select SERIO | 308 | select SERIO |
| @@ -319,13 +340,15 @@ config KEYBOARD_PXA930_ROTARY | |||
| 319 | module will be called pxa930_rotary. | 340 | module will be called pxa930_rotary. |
| 320 | 341 | ||
| 321 | config KEYBOARD_SPITZ | 342 | config KEYBOARD_SPITZ |
| 322 | tristate "Spitz keyboard" | 343 | tristate "Spitz keyboard (deprecated)" |
| 323 | depends on PXA_SHARPSL | 344 | depends on PXA_SHARPSL |
| 324 | default y | ||
| 325 | help | 345 | help |
| 326 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | 346 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, |
| 327 | SL-C3000 and Sl-C3100 series of PDAs. | 347 | SL-C3000 and Sl-C3100 series of PDAs. |
| 328 | 348 | ||
| 349 | This driver is now deprecated, use generic GPIO based matrix | ||
| 350 | keyboard driver instead. | ||
| 351 | |||
| 329 | To compile this driver as a module, choose M here: the | 352 | To compile this driver as a module, choose M here: the |
| 330 | module will be called spitzkbd. | 353 | module will be called spitzkbd. |
| 331 | 354 | ||
| @@ -353,7 +376,7 @@ config KEYBOARD_SUNKBD | |||
| 353 | 376 | ||
| 354 | config KEYBOARD_SH_KEYSC | 377 | config KEYBOARD_SH_KEYSC |
| 355 | tristate "SuperH KEYSC keypad support" | 378 | tristate "SuperH KEYSC keypad support" |
| 356 | depends on SUPERH | 379 | depends on SUPERH || ARCH_SHMOBILE |
| 357 | help | 380 | help |
| 358 | Say Y here if you want to use a keypad attached to the KEYSC block | 381 | Say Y here if you want to use a keypad attached to the KEYSC block |
| 359 | on SuperH processors such as sh7722 and sh7343. | 382 | on SuperH processors such as sh7722 and sh7343. |
| @@ -361,6 +384,16 @@ config KEYBOARD_SH_KEYSC | |||
| 361 | To compile this driver as a module, choose M here: the | 384 | To compile this driver as a module, choose M here: the |
| 362 | module will be called sh_keysc. | 385 | module will be called sh_keysc. |
| 363 | 386 | ||
| 387 | config KEYBOARD_DAVINCI | ||
| 388 | tristate "TI DaVinci Key Scan" | ||
| 389 | depends on ARCH_DAVINCI_DM365 | ||
| 390 | help | ||
| 391 | Say Y to enable keypad module support for the TI DaVinci | ||
| 392 | platforms (DM365). | ||
| 393 | |||
| 394 | To compile this driver as a module, choose M here: the | ||
| 395 | module will be called davinci_keyscan. | ||
| 396 | |||
| 364 | config KEYBOARD_OMAP | 397 | config KEYBOARD_OMAP |
| 365 | tristate "TI OMAP keypad support" | 398 | tristate "TI OMAP keypad support" |
| 366 | depends on (ARCH_OMAP1 || ARCH_OMAP2) | 399 | depends on (ARCH_OMAP1 || ARCH_OMAP2) |
| @@ -382,12 +415,14 @@ config KEYBOARD_TWL4030 | |||
| 382 | module will be called twl4030_keypad. | 415 | module will be called twl4030_keypad. |
| 383 | 416 | ||
| 384 | config KEYBOARD_TOSA | 417 | config KEYBOARD_TOSA |
| 385 | tristate "Tosa keyboard" | 418 | tristate "Tosa keyboard (deprecated)" |
| 386 | depends on MACH_TOSA | 419 | depends on MACH_TOSA |
| 387 | default y | ||
| 388 | help | 420 | help |
| 389 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | 421 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) |
| 390 | 422 | ||
| 423 | This driver is now deprecated, use generic GPIO based matrix | ||
| 424 | keyboard driver instead. | ||
| 425 | |||
| 391 | To compile this driver as a module, choose M here: the | 426 | To compile this driver as a module, choose M here: the |
| 392 | module will be called tosakbd. | 427 | module will be called tosakbd. |
| 393 | 428 | ||
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index babad5e58b77..706c6b5ed5f4 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -5,16 +5,19 @@ | |||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o | 7 | obj-$(CONFIG_KEYBOARD_AAED2000) += aaed2000_kbd.o |
| 8 | obj-$(CONFIG_KEYBOARD_ADP5520) += adp5520-keys.o | ||
| 8 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o | 9 | obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o |
| 9 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | 10 | obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o |
| 10 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
| 11 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
| 12 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
| 13 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | 14 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o |
| 15 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | ||
| 14 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 16 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
| 15 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 17 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
| 16 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o | 18 | obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o |
| 17 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o | 19 | obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o |
| 20 | obj-$(CONFIG_KEYBOARD_IMX) += imx_keypad.o | ||
| 18 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o | 21 | obj-$(CONFIG_KEYBOARD_HP6XX) += jornada680_kbd.o |
| 19 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o | 22 | obj-$(CONFIG_KEYBOARD_HP7XX) += jornada720_kbd.o |
| 20 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o | 23 | obj-$(CONFIG_KEYBOARD_LKKBD) += lkkbd.o |
diff --git a/drivers/input/keyboard/adp5520-keys.c b/drivers/input/keyboard/adp5520-keys.c new file mode 100644 index 000000000000..3db8006dac3a --- /dev/null +++ b/drivers/input/keyboard/adp5520-keys.c | |||
| @@ -0,0 +1,221 @@ | |||
| 1 | /* | ||
| 2 | * Keypad driver for Analog Devices ADP5520 MFD PMICs | ||
| 3 | * | ||
| 4 | * Copyright 2009 Analog Devices Inc. | ||
| 5 | * | ||
| 6 | * Licensed under the GPL-2 or later. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/platform_device.h> | ||
| 13 | #include <linux/input.h> | ||
| 14 | #include <linux/mfd/adp5520.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | |||
| 17 | struct adp5520_keys { | ||
| 18 | struct input_dev *input; | ||
| 19 | struct notifier_block notifier; | ||
| 20 | struct device *master; | ||
| 21 | unsigned short keycode[ADP5520_KEYMAPSIZE]; | ||
| 22 | }; | ||
| 23 | |||
| 24 | static void adp5520_keys_report_event(struct adp5520_keys *dev, | ||
| 25 | unsigned short keymask, int value) | ||
| 26 | { | ||
| 27 | int i; | ||
| 28 | |||
| 29 | for (i = 0; i < ADP5520_MAXKEYS; i++) | ||
| 30 | if (keymask & (1 << i)) | ||
| 31 | input_report_key(dev->input, dev->keycode[i], value); | ||
| 32 | |||
| 33 | input_sync(dev->input); | ||
| 34 | } | ||
| 35 | |||
| 36 | static int adp5520_keys_notifier(struct notifier_block *nb, | ||
| 37 | unsigned long event, void *data) | ||
| 38 | { | ||
| 39 | struct adp5520_keys *dev; | ||
| 40 | uint8_t reg_val_lo, reg_val_hi; | ||
| 41 | unsigned short keymask; | ||
| 42 | |||
| 43 | dev = container_of(nb, struct adp5520_keys, notifier); | ||
| 44 | |||
| 45 | if (event & ADP5520_KP_INT) { | ||
| 46 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); | ||
| 47 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); | ||
| 48 | |||
| 49 | keymask = (reg_val_hi << 8) | reg_val_lo; | ||
| 50 | /* Read twice to clear */ | ||
| 51 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_1, ®_val_lo); | ||
| 52 | adp5520_read(dev->master, ADP5520_KP_INT_STAT_2, ®_val_hi); | ||
| 53 | keymask |= (reg_val_hi << 8) | reg_val_lo; | ||
| 54 | adp5520_keys_report_event(dev, keymask, 1); | ||
| 55 | } | ||
| 56 | |||
| 57 | if (event & ADP5520_KR_INT) { | ||
| 58 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); | ||
| 59 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); | ||
| 60 | |||
| 61 | keymask = (reg_val_hi << 8) | reg_val_lo; | ||
| 62 | /* Read twice to clear */ | ||
| 63 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_1, ®_val_lo); | ||
| 64 | adp5520_read(dev->master, ADP5520_KR_INT_STAT_2, ®_val_hi); | ||
| 65 | keymask |= (reg_val_hi << 8) | reg_val_lo; | ||
| 66 | adp5520_keys_report_event(dev, keymask, 0); | ||
| 67 | } | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static int __devinit adp5520_keys_probe(struct platform_device *pdev) | ||
| 73 | { | ||
| 74 | struct adp5520_keys_platform_data *pdata = pdev->dev.platform_data; | ||
| 75 | struct input_dev *input; | ||
| 76 | struct adp5520_keys *dev; | ||
| 77 | int ret, i; | ||
| 78 | unsigned char en_mask, ctl_mask = 0; | ||
| 79 | |||
| 80 | if (pdev->id != ID_ADP5520) { | ||
| 81 | dev_err(&pdev->dev, "only ADP5520 supports Keypad\n"); | ||
| 82 | return -EINVAL; | ||
| 83 | } | ||
| 84 | |||
| 85 | if (pdata == NULL) { | ||
| 86 | dev_err(&pdev->dev, "missing platform data\n"); | ||
| 87 | return -EINVAL; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (!(pdata->rows_en_mask && pdata->cols_en_mask)) | ||
| 91 | return -EINVAL; | ||
| 92 | |||
| 93 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
| 94 | if (dev == NULL) { | ||
| 95 | dev_err(&pdev->dev, "failed to alloc memory\n"); | ||
| 96 | return -ENOMEM; | ||
| 97 | } | ||
| 98 | |||
| 99 | input = input_allocate_device(); | ||
| 100 | if (!input) { | ||
| 101 | ret = -ENOMEM; | ||
| 102 | goto err; | ||
| 103 | } | ||
| 104 | |||
| 105 | dev->master = pdev->dev.parent; | ||
| 106 | dev->input = input; | ||
| 107 | |||
| 108 | input->name = pdev->name; | ||
| 109 | input->phys = "adp5520-keys/input0"; | ||
| 110 | input->dev.parent = &pdev->dev; | ||
| 111 | |||
| 112 | input_set_drvdata(input, dev); | ||
| 113 | |||
| 114 | input->id.bustype = BUS_I2C; | ||
| 115 | input->id.vendor = 0x0001; | ||
| 116 | input->id.product = 0x5520; | ||
| 117 | input->id.version = 0x0001; | ||
| 118 | |||
| 119 | input->keycodesize = sizeof(dev->keycode[0]); | ||
| 120 | input->keycodemax = pdata->keymapsize; | ||
| 121 | input->keycode = dev->keycode; | ||
| 122 | |||
| 123 | memcpy(dev->keycode, pdata->keymap, | ||
| 124 | pdata->keymapsize * input->keycodesize); | ||
| 125 | |||
| 126 | /* setup input device */ | ||
| 127 | __set_bit(EV_KEY, input->evbit); | ||
| 128 | |||
| 129 | if (pdata->repeat) | ||
| 130 | __set_bit(EV_REP, input->evbit); | ||
| 131 | |||
| 132 | for (i = 0; i < input->keycodemax; i++) | ||
| 133 | __set_bit(dev->keycode[i], input->keybit); | ||
| 134 | __clear_bit(KEY_RESERVED, input->keybit); | ||
| 135 | |||
| 136 | ret = input_register_device(input); | ||
| 137 | if (ret) { | ||
| 138 | dev_err(&pdev->dev, "unable to register input device\n"); | ||
| 139 | goto err; | ||
| 140 | } | ||
| 141 | |||
| 142 | en_mask = pdata->rows_en_mask | pdata->cols_en_mask; | ||
| 143 | |||
| 144 | ret = adp5520_set_bits(dev->master, ADP5520_GPIO_CFG_1, en_mask); | ||
| 145 | |||
| 146 | if (en_mask & ADP5520_COL_C3) | ||
| 147 | ctl_mask |= ADP5520_C3_MODE; | ||
| 148 | |||
| 149 | if (en_mask & ADP5520_ROW_R3) | ||
| 150 | ctl_mask |= ADP5520_R3_MODE; | ||
| 151 | |||
| 152 | if (ctl_mask) | ||
| 153 | ret |= adp5520_set_bits(dev->master, ADP5520_LED_CONTROL, | ||
| 154 | ctl_mask); | ||
| 155 | |||
| 156 | ret |= adp5520_set_bits(dev->master, ADP5520_GPIO_PULLUP, | ||
| 157 | pdata->rows_en_mask); | ||
| 158 | |||
| 159 | if (ret) { | ||
| 160 | dev_err(&pdev->dev, "failed to write\n"); | ||
| 161 | ret = -EIO; | ||
| 162 | goto err1; | ||
| 163 | } | ||
| 164 | |||
| 165 | dev->notifier.notifier_call = adp5520_keys_notifier; | ||
| 166 | ret = adp5520_register_notifier(dev->master, &dev->notifier, | ||
| 167 | ADP5520_KP_IEN | ADP5520_KR_IEN); | ||
| 168 | if (ret) { | ||
| 169 | dev_err(&pdev->dev, "failed to register notifier\n"); | ||
| 170 | goto err1; | ||
| 171 | } | ||
| 172 | |||
| 173 | platform_set_drvdata(pdev, dev); | ||
| 174 | return 0; | ||
| 175 | |||
| 176 | err1: | ||
| 177 | input_unregister_device(input); | ||
| 178 | input = NULL; | ||
| 179 | err: | ||
| 180 | input_free_device(input); | ||
| 181 | kfree(dev); | ||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | |||
| 185 | static int __devexit adp5520_keys_remove(struct platform_device *pdev) | ||
| 186 | { | ||
| 187 | struct adp5520_keys *dev = platform_get_drvdata(pdev); | ||
| 188 | |||
| 189 | adp5520_unregister_notifier(dev->master, &dev->notifier, | ||
| 190 | ADP5520_KP_IEN | ADP5520_KR_IEN); | ||
| 191 | |||
| 192 | input_unregister_device(dev->input); | ||
| 193 | kfree(dev); | ||
| 194 | return 0; | ||
| 195 | } | ||
| 196 | |||
| 197 | static struct platform_driver adp5520_keys_driver = { | ||
| 198 | .driver = { | ||
| 199 | .name = "adp5520-keys", | ||
| 200 | .owner = THIS_MODULE, | ||
| 201 | }, | ||
| 202 | .probe = adp5520_keys_probe, | ||
| 203 | .remove = __devexit_p(adp5520_keys_remove), | ||
| 204 | }; | ||
| 205 | |||
| 206 | static int __init adp5520_keys_init(void) | ||
| 207 | { | ||
| 208 | return platform_driver_register(&adp5520_keys_driver); | ||
| 209 | } | ||
| 210 | module_init(adp5520_keys_init); | ||
| 211 | |||
| 212 | static void __exit adp5520_keys_exit(void) | ||
| 213 | { | ||
| 214 | platform_driver_unregister(&adp5520_keys_driver); | ||
| 215 | } | ||
| 216 | module_exit(adp5520_keys_exit); | ||
| 217 | |||
| 218 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
| 219 | MODULE_DESCRIPTION("Keys ADP5520 Driver"); | ||
| 220 | MODULE_LICENSE("GPL"); | ||
| 221 | MODULE_ALIAS("platform:adp5520-keys"); | ||
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index d48c808d5928..4771ab172b59 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * File: drivers/input/keyboard/adp5588_keys.c | 2 | * File: drivers/input/keyboard/adp5588_keys.c |
| 3 | * Description: keypad driver for ADP5588 I2C QWERTY Keypad and IO Expander | 3 | * Description: keypad driver for ADP5588 and ADP5587 |
| 4 | * I2C QWERTY Keypad and IO Expander | ||
| 4 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 5 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
| 5 | * | 6 | * |
| 6 | * Copyright (C) 2008-2009 Analog Devices Inc. | 7 | * Copyright (C) 2008-2009 Analog Devices Inc. |
| @@ -18,6 +19,7 @@ | |||
| 18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 19 | #include <linux/input.h> | 20 | #include <linux/input.h> |
| 20 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
| 22 | #include <linux/slab.h> | ||
| 21 | 23 | ||
| 22 | #include <linux/i2c/adp5588.h> | 24 | #include <linux/i2c/adp5588.h> |
| 23 | 25 | ||
| @@ -319,7 +321,7 @@ static int adp5588_resume(struct device *dev) | |||
| 319 | return 0; | 321 | return 0; |
| 320 | } | 322 | } |
| 321 | 323 | ||
| 322 | static struct dev_pm_ops adp5588_dev_pm_ops = { | 324 | static const struct dev_pm_ops adp5588_dev_pm_ops = { |
| 323 | .suspend = adp5588_suspend, | 325 | .suspend = adp5588_suspend, |
| 324 | .resume = adp5588_resume, | 326 | .resume = adp5588_resume, |
| 325 | }; | 327 | }; |
| @@ -327,6 +329,7 @@ static struct dev_pm_ops adp5588_dev_pm_ops = { | |||
| 327 | 329 | ||
| 328 | static const struct i2c_device_id adp5588_id[] = { | 330 | static const struct i2c_device_id adp5588_id[] = { |
| 329 | { KBUILD_MODNAME, 0 }, | 331 | { KBUILD_MODNAME, 0 }, |
| 332 | { "adp5587-keys", 0 }, | ||
| 330 | { } | 333 | { } |
| 331 | }; | 334 | }; |
| 332 | MODULE_DEVICE_TABLE(i2c, adp5588_id); | 335 | MODULE_DEVICE_TABLE(i2c, adp5588_id); |
| @@ -357,5 +360,5 @@ module_exit(adp5588_exit); | |||
| 357 | 360 | ||
| 358 | MODULE_LICENSE("GPL"); | 361 | MODULE_LICENSE("GPL"); |
| 359 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | 362 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
| 360 | MODULE_DESCRIPTION("ADP5588 Keypad driver"); | 363 | MODULE_DESCRIPTION("ADP5588/87 Keypad driver"); |
| 361 | MODULE_ALIAS("platform:adp5588-keys"); | 364 | MODULE_ALIAS("platform:adp5588-keys"); |
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 28e6110d1ff8..d358ef8623f4 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -40,26 +40,26 @@ module_param_named(set, atkbd_set, int, 0); | |||
| 40 | MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)"); | 40 | MODULE_PARM_DESC(set, "Select keyboard code set (2 = default, 3 = PS/2 native)"); |
| 41 | 41 | ||
| 42 | #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__) | 42 | #if defined(__i386__) || defined(__x86_64__) || defined(__hppa__) |
| 43 | static int atkbd_reset; | 43 | static bool atkbd_reset; |
| 44 | #else | 44 | #else |
| 45 | static int atkbd_reset = 1; | 45 | static bool atkbd_reset = true; |
| 46 | #endif | 46 | #endif |
| 47 | module_param_named(reset, atkbd_reset, bool, 0); | 47 | module_param_named(reset, atkbd_reset, bool, 0); |
| 48 | MODULE_PARM_DESC(reset, "Reset keyboard during initialization"); | 48 | MODULE_PARM_DESC(reset, "Reset keyboard during initialization"); |
| 49 | 49 | ||
| 50 | static int atkbd_softrepeat; | 50 | static bool atkbd_softrepeat; |
| 51 | module_param_named(softrepeat, atkbd_softrepeat, bool, 0); | 51 | module_param_named(softrepeat, atkbd_softrepeat, bool, 0); |
| 52 | MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat"); | 52 | MODULE_PARM_DESC(softrepeat, "Use software keyboard repeat"); |
| 53 | 53 | ||
| 54 | static int atkbd_softraw = 1; | 54 | static bool atkbd_softraw = true; |
| 55 | module_param_named(softraw, atkbd_softraw, bool, 0); | 55 | module_param_named(softraw, atkbd_softraw, bool, 0); |
| 56 | MODULE_PARM_DESC(softraw, "Use software generated rawmode"); | 56 | MODULE_PARM_DESC(softraw, "Use software generated rawmode"); |
| 57 | 57 | ||
| 58 | static int atkbd_scroll; | 58 | static bool atkbd_scroll; |
| 59 | module_param_named(scroll, atkbd_scroll, bool, 0); | 59 | module_param_named(scroll, atkbd_scroll, bool, 0); |
| 60 | MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); | 60 | MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards"); |
| 61 | 61 | ||
| 62 | static int atkbd_extra; | 62 | static bool atkbd_extra; |
| 63 | module_param_named(extra, atkbd_extra, bool, 0); | 63 | module_param_named(extra, atkbd_extra, bool, 0); |
| 64 | MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards"); | 64 | MODULE_PARM_DESC(extra, "Enable extra LEDs and keys on IBM RapidAcces, EzKey and similar keyboards"); |
| 65 | 65 | ||
| @@ -134,7 +134,8 @@ static const unsigned short atkbd_unxlate_table[128] = { | |||
| 134 | #define ATKBD_CMD_GETID 0x02f2 | 134 | #define ATKBD_CMD_GETID 0x02f2 |
| 135 | #define ATKBD_CMD_SETREP 0x10f3 | 135 | #define ATKBD_CMD_SETREP 0x10f3 |
| 136 | #define ATKBD_CMD_ENABLE 0x00f4 | 136 | #define ATKBD_CMD_ENABLE 0x00f4 |
| 137 | #define ATKBD_CMD_RESET_DIS 0x00f5 | 137 | #define ATKBD_CMD_RESET_DIS 0x00f5 /* Reset to defaults and disable */ |
| 138 | #define ATKBD_CMD_RESET_DEF 0x00f6 /* Reset to defaults */ | ||
| 138 | #define ATKBD_CMD_SETALL_MBR 0x00fa | 139 | #define ATKBD_CMD_SETALL_MBR 0x00fa |
| 139 | #define ATKBD_CMD_RESET_BAT 0x02ff | 140 | #define ATKBD_CMD_RESET_BAT 0x02ff |
| 140 | #define ATKBD_CMD_RESEND 0x00fe | 141 | #define ATKBD_CMD_RESEND 0x00fe |
| @@ -152,16 +153,16 @@ static const unsigned short atkbd_unxlate_table[128] = { | |||
| 152 | #define ATKBD_RET_HANGEUL 0xf2 | 153 | #define ATKBD_RET_HANGEUL 0xf2 |
| 153 | #define ATKBD_RET_ERR 0xff | 154 | #define ATKBD_RET_ERR 0xff |
| 154 | 155 | ||
| 155 | #define ATKBD_KEY_UNKNOWN 0 | 156 | #define ATKBD_KEY_UNKNOWN 0 |
| 156 | #define ATKBD_KEY_NULL 255 | 157 | #define ATKBD_KEY_NULL 255 |
| 157 | 158 | ||
| 158 | #define ATKBD_SCR_1 254 | 159 | #define ATKBD_SCR_1 0xfffe |
| 159 | #define ATKBD_SCR_2 253 | 160 | #define ATKBD_SCR_2 0xfffd |
| 160 | #define ATKBD_SCR_4 252 | 161 | #define ATKBD_SCR_4 0xfffc |
| 161 | #define ATKBD_SCR_8 251 | 162 | #define ATKBD_SCR_8 0xfffb |
| 162 | #define ATKBD_SCR_CLICK 250 | 163 | #define ATKBD_SCR_CLICK 0xfffa |
| 163 | #define ATKBD_SCR_LEFT 249 | 164 | #define ATKBD_SCR_LEFT 0xfff9 |
| 164 | #define ATKBD_SCR_RIGHT 248 | 165 | #define ATKBD_SCR_RIGHT 0xfff8 |
| 165 | 166 | ||
| 166 | #define ATKBD_SPECIAL ATKBD_SCR_RIGHT | 167 | #define ATKBD_SPECIAL ATKBD_SCR_RIGHT |
| 167 | 168 | ||
| @@ -176,7 +177,7 @@ static const unsigned short atkbd_unxlate_table[128] = { | |||
| 176 | #define ATKBD_XL_HANJA 0x20 | 177 | #define ATKBD_XL_HANJA 0x20 |
| 177 | 178 | ||
| 178 | static const struct { | 179 | static const struct { |
| 179 | unsigned char keycode; | 180 | unsigned short keycode; |
| 180 | unsigned char set2; | 181 | unsigned char set2; |
| 181 | } atkbd_scroll_keys[] = { | 182 | } atkbd_scroll_keys[] = { |
| 182 | { ATKBD_SCR_1, 0xc5 }, | 183 | { ATKBD_SCR_1, 0xc5 }, |
| @@ -205,18 +206,18 @@ struct atkbd { | |||
| 205 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; | 206 | unsigned short keycode[ATKBD_KEYMAP_SIZE]; |
| 206 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); | 207 | DECLARE_BITMAP(force_release_mask, ATKBD_KEYMAP_SIZE); |
| 207 | unsigned char set; | 208 | unsigned char set; |
| 208 | unsigned char translated; | 209 | bool translated; |
| 209 | unsigned char extra; | 210 | bool extra; |
| 210 | unsigned char write; | 211 | bool write; |
| 211 | unsigned char softrepeat; | 212 | bool softrepeat; |
| 212 | unsigned char softraw; | 213 | bool softraw; |
| 213 | unsigned char scroll; | 214 | bool scroll; |
| 214 | unsigned char enabled; | 215 | bool enabled; |
| 215 | 216 | ||
| 216 | /* Accessed only from interrupt */ | 217 | /* Accessed only from interrupt */ |
| 217 | unsigned char emul; | 218 | unsigned char emul; |
| 218 | unsigned char resend; | 219 | bool resend; |
| 219 | unsigned char release; | 220 | bool release; |
| 220 | unsigned long xl_bit; | 221 | unsigned long xl_bit; |
| 221 | unsigned int last; | 222 | unsigned int last; |
| 222 | unsigned long time; | 223 | unsigned long time; |
| @@ -224,8 +225,10 @@ struct atkbd { | |||
| 224 | 225 | ||
| 225 | struct delayed_work event_work; | 226 | struct delayed_work event_work; |
| 226 | unsigned long event_jiffies; | 227 | unsigned long event_jiffies; |
| 227 | struct mutex event_mutex; | ||
| 228 | unsigned long event_mask; | 228 | unsigned long event_mask; |
| 229 | |||
| 230 | /* Serializes reconnect(), attr->set() and event work */ | ||
| 231 | struct mutex mutex; | ||
| 229 | }; | 232 | }; |
| 230 | 233 | ||
| 231 | /* | 234 | /* |
| @@ -298,18 +301,18 @@ static const unsigned int xl_table[] = { | |||
| 298 | * Checks if we should mangle the scancode to extract 'release' bit | 301 | * Checks if we should mangle the scancode to extract 'release' bit |
| 299 | * in translated mode. | 302 | * in translated mode. |
| 300 | */ | 303 | */ |
| 301 | static int atkbd_need_xlate(unsigned long xl_bit, unsigned char code) | 304 | static bool atkbd_need_xlate(unsigned long xl_bit, unsigned char code) |
| 302 | { | 305 | { |
| 303 | int i; | 306 | int i; |
| 304 | 307 | ||
| 305 | if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1) | 308 | if (code == ATKBD_RET_EMUL0 || code == ATKBD_RET_EMUL1) |
| 306 | return 0; | 309 | return false; |
| 307 | 310 | ||
| 308 | for (i = 0; i < ARRAY_SIZE(xl_table); i++) | 311 | for (i = 0; i < ARRAY_SIZE(xl_table); i++) |
| 309 | if (code == xl_table[i]) | 312 | if (code == xl_table[i]) |
| 310 | return test_bit(i, &xl_bit); | 313 | return test_bit(i, &xl_bit); |
| 311 | 314 | ||
| 312 | return 1; | 315 | return true; |
| 313 | } | 316 | } |
| 314 | 317 | ||
| 315 | /* | 318 | /* |
| @@ -356,7 +359,7 @@ static unsigned int atkbd_compat_scancode(struct atkbd *atkbd, unsigned int code | |||
| 356 | */ | 359 | */ |
| 357 | 360 | ||
| 358 | static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | 361 | static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, |
| 359 | unsigned int flags) | 362 | unsigned int flags) |
| 360 | { | 363 | { |
| 361 | struct atkbd *atkbd = serio_get_drvdata(serio); | 364 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 362 | struct input_dev *dev = atkbd->dev; | 365 | struct input_dev *dev = atkbd->dev; |
| @@ -365,20 +368,18 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
| 365 | int value; | 368 | int value; |
| 366 | unsigned short keycode; | 369 | unsigned short keycode; |
| 367 | 370 | ||
| 368 | #ifdef ATKBD_DEBUG | 371 | dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, flags); |
| 369 | printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags); | ||
| 370 | #endif | ||
| 371 | 372 | ||
| 372 | #if !defined(__i386__) && !defined (__x86_64__) | 373 | #if !defined(__i386__) && !defined (__x86_64__) |
| 373 | if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { | 374 | if ((flags & (SERIO_FRAME | SERIO_PARITY)) && (~flags & SERIO_TIMEOUT) && !atkbd->resend && atkbd->write) { |
| 374 | printk(KERN_WARNING "atkbd.c: frame/parity error: %02x\n", flags); | 375 | dev_warn(&serio->dev, "Frame/parity error: %02x\n", flags); |
| 375 | serio_write(serio, ATKBD_CMD_RESEND); | 376 | serio_write(serio, ATKBD_CMD_RESEND); |
| 376 | atkbd->resend = 1; | 377 | atkbd->resend = true; |
| 377 | goto out; | 378 | goto out; |
| 378 | } | 379 | } |
| 379 | 380 | ||
| 380 | if (!flags && data == ATKBD_RET_ACK) | 381 | if (!flags && data == ATKBD_RET_ACK) |
| 381 | atkbd->resend = 0; | 382 | atkbd->resend = false; |
| 382 | #endif | 383 | #endif |
| 383 | 384 | ||
| 384 | if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) | 385 | if (unlikely(atkbd->ps2dev.flags & PS2_FLAG_ACK)) |
| @@ -409,32 +410,32 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
| 409 | } | 410 | } |
| 410 | 411 | ||
| 411 | switch (code) { | 412 | switch (code) { |
| 412 | case ATKBD_RET_BAT: | 413 | case ATKBD_RET_BAT: |
| 413 | atkbd->enabled = 0; | 414 | atkbd->enabled = false; |
| 414 | serio_reconnect(atkbd->ps2dev.serio); | 415 | serio_reconnect(atkbd->ps2dev.serio); |
| 415 | goto out; | 416 | goto out; |
| 416 | case ATKBD_RET_EMUL0: | 417 | case ATKBD_RET_EMUL0: |
| 417 | atkbd->emul = 1; | 418 | atkbd->emul = 1; |
| 418 | goto out; | 419 | goto out; |
| 419 | case ATKBD_RET_EMUL1: | 420 | case ATKBD_RET_EMUL1: |
| 420 | atkbd->emul = 2; | 421 | atkbd->emul = 2; |
| 421 | goto out; | 422 | goto out; |
| 422 | case ATKBD_RET_RELEASE: | 423 | case ATKBD_RET_RELEASE: |
| 423 | atkbd->release = 1; | 424 | atkbd->release = true; |
| 424 | goto out; | 425 | goto out; |
| 425 | case ATKBD_RET_ACK: | 426 | case ATKBD_RET_ACK: |
| 426 | case ATKBD_RET_NAK: | 427 | case ATKBD_RET_NAK: |
| 427 | if (printk_ratelimit()) | 428 | if (printk_ratelimit()) |
| 428 | printk(KERN_WARNING "atkbd.c: Spurious %s on %s. " | 429 | dev_warn(&serio->dev, |
| 429 | "Some program might be trying access hardware directly.\n", | 430 | "Spurious %s on %s. " |
| 430 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); | 431 | "Some program might be trying access hardware directly.\n", |
| 431 | goto out; | 432 | data == ATKBD_RET_ACK ? "ACK" : "NAK", serio->phys); |
| 432 | case ATKBD_RET_ERR: | 433 | goto out; |
| 433 | atkbd->err_count++; | 434 | case ATKBD_RET_ERR: |
| 434 | #ifdef ATKBD_DEBUG | 435 | atkbd->err_count++; |
| 435 | printk(KERN_DEBUG "atkbd.c: Keyboard on %s reports too many keys pressed.\n", serio->phys); | 436 | dev_dbg(&serio->dev, "Keyboard on %s reports too many keys pressed.\n", |
| 436 | #endif | 437 | serio->phys); |
| 437 | goto out; | 438 | goto out; |
| 438 | } | 439 | } |
| 439 | 440 | ||
| 440 | code = atkbd_compat_scancode(atkbd, code); | 441 | code = atkbd_compat_scancode(atkbd, code); |
| @@ -448,71 +449,72 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
| 448 | input_event(dev, EV_MSC, MSC_SCAN, code); | 449 | input_event(dev, EV_MSC, MSC_SCAN, code); |
| 449 | 450 | ||
| 450 | switch (keycode) { | 451 | switch (keycode) { |
| 451 | case ATKBD_KEY_NULL: | 452 | case ATKBD_KEY_NULL: |
| 452 | break; | 453 | break; |
| 453 | case ATKBD_KEY_UNKNOWN: | 454 | case ATKBD_KEY_UNKNOWN: |
| 454 | printk(KERN_WARNING | 455 | dev_warn(&serio->dev, |
| 455 | "atkbd.c: Unknown key %s (%s set %d, code %#x on %s).\n", | 456 | "Unknown key %s (%s set %d, code %#x on %s).\n", |
| 456 | atkbd->release ? "released" : "pressed", | 457 | atkbd->release ? "released" : "pressed", |
| 457 | atkbd->translated ? "translated" : "raw", | 458 | atkbd->translated ? "translated" : "raw", |
| 458 | atkbd->set, code, serio->phys); | 459 | atkbd->set, code, serio->phys); |
| 459 | printk(KERN_WARNING | 460 | dev_warn(&serio->dev, |
| 460 | "atkbd.c: Use 'setkeycodes %s%02x <keycode>' to make it known.\n", | 461 | "Use 'setkeycodes %s%02x <keycode>' to make it known.\n", |
| 461 | code & 0x80 ? "e0" : "", code & 0x7f); | 462 | code & 0x80 ? "e0" : "", code & 0x7f); |
| 462 | input_sync(dev); | 463 | input_sync(dev); |
| 463 | break; | 464 | break; |
| 464 | case ATKBD_SCR_1: | 465 | case ATKBD_SCR_1: |
| 465 | scroll = 1 - atkbd->release * 2; | 466 | scroll = 1; |
| 466 | break; | 467 | break; |
| 467 | case ATKBD_SCR_2: | 468 | case ATKBD_SCR_2: |
| 468 | scroll = 2 - atkbd->release * 4; | 469 | scroll = 2; |
| 469 | break; | 470 | break; |
| 470 | case ATKBD_SCR_4: | 471 | case ATKBD_SCR_4: |
| 471 | scroll = 4 - atkbd->release * 8; | 472 | scroll = 4; |
| 472 | break; | 473 | break; |
| 473 | case ATKBD_SCR_8: | 474 | case ATKBD_SCR_8: |
| 474 | scroll = 8 - atkbd->release * 16; | 475 | scroll = 8; |
| 475 | break; | 476 | break; |
| 476 | case ATKBD_SCR_CLICK: | 477 | case ATKBD_SCR_CLICK: |
| 477 | click = !atkbd->release; | 478 | click = !atkbd->release; |
| 478 | break; | 479 | break; |
| 479 | case ATKBD_SCR_LEFT: | 480 | case ATKBD_SCR_LEFT: |
| 480 | hscroll = -1; | 481 | hscroll = -1; |
| 481 | break; | 482 | break; |
| 482 | case ATKBD_SCR_RIGHT: | 483 | case ATKBD_SCR_RIGHT: |
| 483 | hscroll = 1; | 484 | hscroll = 1; |
| 484 | break; | 485 | break; |
| 485 | default: | 486 | default: |
| 486 | if (atkbd->release) { | 487 | if (atkbd->release) { |
| 487 | value = 0; | 488 | value = 0; |
| 488 | atkbd->last = 0; | 489 | atkbd->last = 0; |
| 489 | } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) { | 490 | } else if (!atkbd->softrepeat && test_bit(keycode, dev->key)) { |
| 490 | /* Workaround Toshiba laptop multiple keypress */ | 491 | /* Workaround Toshiba laptop multiple keypress */ |
| 491 | value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2; | 492 | value = time_before(jiffies, atkbd->time) && atkbd->last == code ? 1 : 2; |
| 492 | } else { | 493 | } else { |
| 493 | value = 1; | 494 | value = 1; |
| 494 | atkbd->last = code; | 495 | atkbd->last = code; |
| 495 | atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; | 496 | atkbd->time = jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]) / 2; |
| 496 | } | 497 | } |
| 497 | 498 | ||
| 498 | input_event(dev, EV_KEY, keycode, value); | 499 | input_event(dev, EV_KEY, keycode, value); |
| 499 | input_sync(dev); | 500 | input_sync(dev); |
| 500 | 501 | ||
| 501 | if (value && test_bit(code, atkbd->force_release_mask)) { | 502 | if (value && test_bit(code, atkbd->force_release_mask)) { |
| 502 | input_report_key(dev, keycode, 0); | 503 | input_report_key(dev, keycode, 0); |
| 503 | input_sync(dev); | 504 | input_sync(dev); |
| 504 | } | 505 | } |
| 505 | } | 506 | } |
| 506 | 507 | ||
| 507 | if (atkbd->scroll) { | 508 | if (atkbd->scroll) { |
| 508 | if (click != -1) | 509 | if (click != -1) |
| 509 | input_report_key(dev, BTN_MIDDLE, click); | 510 | input_report_key(dev, BTN_MIDDLE, click); |
| 510 | input_report_rel(dev, REL_WHEEL, scroll); | 511 | input_report_rel(dev, REL_WHEEL, |
| 512 | atkbd->release ? -scroll : scroll); | ||
| 511 | input_report_rel(dev, REL_HWHEEL, hscroll); | 513 | input_report_rel(dev, REL_HWHEEL, hscroll); |
| 512 | input_sync(dev); | 514 | input_sync(dev); |
| 513 | } | 515 | } |
| 514 | 516 | ||
| 515 | atkbd->release = 0; | 517 | atkbd->release = false; |
| 516 | out: | 518 | out: |
| 517 | return IRQ_HANDLED; | 519 | return IRQ_HANDLED; |
| 518 | } | 520 | } |
| @@ -576,7 +578,7 @@ static void atkbd_event_work(struct work_struct *work) | |||
| 576 | { | 578 | { |
| 577 | struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); | 579 | struct atkbd *atkbd = container_of(work, struct atkbd, event_work.work); |
| 578 | 580 | ||
| 579 | mutex_lock(&atkbd->event_mutex); | 581 | mutex_lock(&atkbd->mutex); |
| 580 | 582 | ||
| 581 | if (!atkbd->enabled) { | 583 | if (!atkbd->enabled) { |
| 582 | /* | 584 | /* |
| @@ -595,7 +597,7 @@ static void atkbd_event_work(struct work_struct *work) | |||
| 595 | atkbd_set_repeat_rate(atkbd); | 597 | atkbd_set_repeat_rate(atkbd); |
| 596 | } | 598 | } |
| 597 | 599 | ||
| 598 | mutex_unlock(&atkbd->event_mutex); | 600 | mutex_unlock(&atkbd->mutex); |
| 599 | } | 601 | } |
| 600 | 602 | ||
| 601 | /* | 603 | /* |
| @@ -611,7 +613,7 @@ static void atkbd_schedule_event_work(struct atkbd *atkbd, int event_bit) | |||
| 611 | 613 | ||
| 612 | atkbd->event_jiffies = jiffies; | 614 | atkbd->event_jiffies = jiffies; |
| 613 | set_bit(event_bit, &atkbd->event_mask); | 615 | set_bit(event_bit, &atkbd->event_mask); |
| 614 | wmb(); | 616 | mb(); |
| 615 | schedule_delayed_work(&atkbd->event_work, delay); | 617 | schedule_delayed_work(&atkbd->event_work, delay); |
| 616 | } | 618 | } |
| 617 | 619 | ||
| @@ -631,17 +633,18 @@ static int atkbd_event(struct input_dev *dev, | |||
| 631 | 633 | ||
| 632 | switch (type) { | 634 | switch (type) { |
| 633 | 635 | ||
| 634 | case EV_LED: | 636 | case EV_LED: |
| 635 | atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT); | 637 | atkbd_schedule_event_work(atkbd, ATKBD_LED_EVENT_BIT); |
| 636 | return 0; | 638 | return 0; |
| 637 | 639 | ||
| 638 | case EV_REP: | 640 | case EV_REP: |
| 639 | if (!atkbd->softrepeat) | 641 | if (!atkbd->softrepeat) |
| 640 | atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT); | 642 | atkbd_schedule_event_work(atkbd, ATKBD_REP_EVENT_BIT); |
| 641 | return 0; | 643 | return 0; |
| 642 | } | ||
| 643 | 644 | ||
| 644 | return -1; | 645 | default: |
| 646 | return -1; | ||
| 647 | } | ||
| 645 | } | 648 | } |
| 646 | 649 | ||
| 647 | /* | 650 | /* |
| @@ -652,7 +655,7 @@ static int atkbd_event(struct input_dev *dev, | |||
| 652 | static inline void atkbd_enable(struct atkbd *atkbd) | 655 | static inline void atkbd_enable(struct atkbd *atkbd) |
| 653 | { | 656 | { |
| 654 | serio_pause_rx(atkbd->ps2dev.serio); | 657 | serio_pause_rx(atkbd->ps2dev.serio); |
| 655 | atkbd->enabled = 1; | 658 | atkbd->enabled = true; |
| 656 | serio_continue_rx(atkbd->ps2dev.serio); | 659 | serio_continue_rx(atkbd->ps2dev.serio); |
| 657 | } | 660 | } |
| 658 | 661 | ||
| @@ -664,7 +667,7 @@ static inline void atkbd_enable(struct atkbd *atkbd) | |||
| 664 | static inline void atkbd_disable(struct atkbd *atkbd) | 667 | static inline void atkbd_disable(struct atkbd *atkbd) |
| 665 | { | 668 | { |
| 666 | serio_pause_rx(atkbd->ps2dev.serio); | 669 | serio_pause_rx(atkbd->ps2dev.serio); |
| 667 | atkbd->enabled = 0; | 670 | atkbd->enabled = false; |
| 668 | serio_continue_rx(atkbd->ps2dev.serio); | 671 | serio_continue_rx(atkbd->ps2dev.serio); |
| 669 | } | 672 | } |
| 670 | 673 | ||
| @@ -685,7 +688,9 @@ static int atkbd_probe(struct atkbd *atkbd) | |||
| 685 | 688 | ||
| 686 | if (atkbd_reset) | 689 | if (atkbd_reset) |
| 687 | if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT)) | 690 | if (ps2_command(ps2dev, NULL, ATKBD_CMD_RESET_BAT)) |
| 688 | printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", ps2dev->serio->phys); | 691 | dev_warn(&ps2dev->serio->dev, |
| 692 | "keyboard reset failed on %s\n", | ||
| 693 | ps2dev->serio->phys); | ||
| 689 | 694 | ||
| 690 | /* | 695 | /* |
| 691 | * Then we check the keyboard ID. We should get 0xab83 under normal conditions. | 696 | * Then we check the keyboard ID. We should get 0xab83 under normal conditions. |
| @@ -715,8 +720,9 @@ static int atkbd_probe(struct atkbd *atkbd) | |||
| 715 | atkbd->id = (param[0] << 8) | param[1]; | 720 | atkbd->id = (param[0] << 8) | param[1]; |
| 716 | 721 | ||
| 717 | if (atkbd->id == 0xaca1 && atkbd->translated) { | 722 | if (atkbd->id == 0xaca1 && atkbd->translated) { |
| 718 | printk(KERN_ERR "atkbd.c: NCD terminal keyboards are only supported on non-translating\n"); | 723 | dev_err(&ps2dev->serio->dev, |
| 719 | printk(KERN_ERR "atkbd.c: controllers. Use i8042.direct=1 to disable translation.\n"); | 724 | "NCD terminal keyboards are only supported on non-translating controlelrs. " |
| 725 | "Use i8042.direct=1 to disable translation.\n"); | ||
| 720 | return -1; | 726 | return -1; |
| 721 | } | 727 | } |
| 722 | 728 | ||
| @@ -734,7 +740,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra | |||
| 734 | struct ps2dev *ps2dev = &atkbd->ps2dev; | 740 | struct ps2dev *ps2dev = &atkbd->ps2dev; |
| 735 | unsigned char param[2]; | 741 | unsigned char param[2]; |
| 736 | 742 | ||
| 737 | atkbd->extra = 0; | 743 | atkbd->extra = false; |
| 738 | /* | 744 | /* |
| 739 | * For known special keyboards we can go ahead and set the correct set. | 745 | * For known special keyboards we can go ahead and set the correct set. |
| 740 | * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and | 746 | * We check for NCD PS/2 Sun, NorthGate OmniKey 101 and |
| @@ -753,7 +759,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra | |||
| 753 | if (allow_extra) { | 759 | if (allow_extra) { |
| 754 | param[0] = 0x71; | 760 | param[0] = 0x71; |
| 755 | if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) { | 761 | if (!ps2_command(ps2dev, param, ATKBD_CMD_EX_ENABLE)) { |
| 756 | atkbd->extra = 1; | 762 | atkbd->extra = true; |
| 757 | return 2; | 763 | return 2; |
| 758 | } | 764 | } |
| 759 | } | 765 | } |
| @@ -818,7 +824,8 @@ static int atkbd_activate(struct atkbd *atkbd) | |||
| 818 | */ | 824 | */ |
| 819 | 825 | ||
| 820 | if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { | 826 | if (ps2_command(ps2dev, NULL, ATKBD_CMD_ENABLE)) { |
| 821 | printk(KERN_ERR "atkbd.c: Failed to enable keyboard on %s\n", | 827 | dev_err(&ps2dev->serio->dev, |
| 828 | "Failed to enable keyboard on %s\n", | ||
| 822 | ps2dev->serio->phys); | 829 | ps2dev->serio->phys); |
| 823 | return -1; | 830 | return -1; |
| 824 | } | 831 | } |
| @@ -836,7 +843,7 @@ static void atkbd_cleanup(struct serio *serio) | |||
| 836 | struct atkbd *atkbd = serio_get_drvdata(serio); | 843 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 837 | 844 | ||
| 838 | atkbd_disable(atkbd); | 845 | atkbd_disable(atkbd); |
| 839 | ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT); | 846 | ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_DEF); |
| 840 | } | 847 | } |
| 841 | 848 | ||
| 842 | 849 | ||
| @@ -848,13 +855,20 @@ static void atkbd_disconnect(struct serio *serio) | |||
| 848 | { | 855 | { |
| 849 | struct atkbd *atkbd = serio_get_drvdata(serio); | 856 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 850 | 857 | ||
| 858 | sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); | ||
| 859 | |||
| 851 | atkbd_disable(atkbd); | 860 | atkbd_disable(atkbd); |
| 852 | 861 | ||
| 853 | /* make sure we don't have a command in flight */ | 862 | input_unregister_device(atkbd->dev); |
| 863 | |||
| 864 | /* | ||
| 865 | * Make sure we don't have a command in flight. | ||
| 866 | * Note that since atkbd->enabled is false event work will keep | ||
| 867 | * rescheduling itself until it gets canceled and will not try | ||
| 868 | * accessing freed input device or serio port. | ||
| 869 | */ | ||
| 854 | cancel_delayed_work_sync(&atkbd->event_work); | 870 | cancel_delayed_work_sync(&atkbd->event_work); |
| 855 | 871 | ||
| 856 | sysfs_remove_group(&serio->dev.kobj, &atkbd_attribute_group); | ||
| 857 | input_unregister_device(atkbd->dev); | ||
| 858 | serio_close(serio); | 872 | serio_close(serio); |
| 859 | serio_set_drvdata(serio, NULL); | 873 | serio_set_drvdata(serio, NULL); |
| 860 | kfree(atkbd); | 874 | kfree(atkbd); |
| @@ -1060,9 +1074,13 @@ static void atkbd_set_device_attrs(struct atkbd *atkbd) | |||
| 1060 | input_dev->keycodesize = sizeof(unsigned short); | 1074 | input_dev->keycodesize = sizeof(unsigned short); |
| 1061 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); | 1075 | input_dev->keycodemax = ARRAY_SIZE(atkbd_set2_keycode); |
| 1062 | 1076 | ||
| 1063 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) | 1077 | for (i = 0; i < ATKBD_KEYMAP_SIZE; i++) { |
| 1064 | if (atkbd->keycode[i] && atkbd->keycode[i] < ATKBD_SPECIAL) | 1078 | if (atkbd->keycode[i] != KEY_RESERVED && |
| 1079 | atkbd->keycode[i] != ATKBD_KEY_NULL && | ||
| 1080 | atkbd->keycode[i] < ATKBD_SPECIAL) { | ||
| 1065 | __set_bit(atkbd->keycode[i], input_dev->keybit); | 1081 | __set_bit(atkbd->keycode[i], input_dev->keybit); |
| 1082 | } | ||
| 1083 | } | ||
| 1066 | } | 1084 | } |
| 1067 | 1085 | ||
| 1068 | /* | 1086 | /* |
| @@ -1086,16 +1104,18 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
| 1086 | atkbd->dev = dev; | 1104 | atkbd->dev = dev; |
| 1087 | ps2_init(&atkbd->ps2dev, serio); | 1105 | ps2_init(&atkbd->ps2dev, serio); |
| 1088 | INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); | 1106 | INIT_DELAYED_WORK(&atkbd->event_work, atkbd_event_work); |
| 1089 | mutex_init(&atkbd->event_mutex); | 1107 | mutex_init(&atkbd->mutex); |
| 1090 | 1108 | ||
| 1091 | switch (serio->id.type) { | 1109 | switch (serio->id.type) { |
| 1092 | 1110 | ||
| 1093 | case SERIO_8042_XL: | 1111 | case SERIO_8042_XL: |
| 1094 | atkbd->translated = 1; | 1112 | atkbd->translated = true; |
| 1095 | case SERIO_8042: | 1113 | /* Fall through */ |
| 1096 | if (serio->write) | 1114 | |
| 1097 | atkbd->write = 1; | 1115 | case SERIO_8042: |
| 1098 | break; | 1116 | if (serio->write) |
| 1117 | atkbd->write = true; | ||
| 1118 | break; | ||
| 1099 | } | 1119 | } |
| 1100 | 1120 | ||
| 1101 | atkbd->softraw = atkbd_softraw; | 1121 | atkbd->softraw = atkbd_softraw; |
| @@ -1103,7 +1123,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv) | |||
| 1103 | atkbd->scroll = atkbd_scroll; | 1123 | atkbd->scroll = atkbd_scroll; |
| 1104 | 1124 | ||
| 1105 | if (atkbd->softrepeat) | 1125 | if (atkbd->softrepeat) |
| 1106 | atkbd->softraw = 1; | 1126 | atkbd->softraw = true; |
| 1107 | 1127 | ||
| 1108 | serio_set_drvdata(serio, atkbd); | 1128 | serio_set_drvdata(serio, atkbd); |
| 1109 | 1129 | ||
| @@ -1159,19 +1179,24 @@ static int atkbd_reconnect(struct serio *serio) | |||
| 1159 | { | 1179 | { |
| 1160 | struct atkbd *atkbd = serio_get_drvdata(serio); | 1180 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 1161 | struct serio_driver *drv = serio->drv; | 1181 | struct serio_driver *drv = serio->drv; |
| 1182 | int retval = -1; | ||
| 1162 | 1183 | ||
| 1163 | if (!atkbd || !drv) { | 1184 | if (!atkbd || !drv) { |
| 1164 | printk(KERN_DEBUG "atkbd: reconnect request, but serio is disconnected, ignoring...\n"); | 1185 | dev_dbg(&serio->dev, |
| 1186 | "reconnect request, but serio is disconnected, ignoring...\n"); | ||
| 1165 | return -1; | 1187 | return -1; |
| 1166 | } | 1188 | } |
| 1167 | 1189 | ||
| 1190 | mutex_lock(&atkbd->mutex); | ||
| 1191 | |||
| 1168 | atkbd_disable(atkbd); | 1192 | atkbd_disable(atkbd); |
| 1169 | 1193 | ||
| 1170 | if (atkbd->write) { | 1194 | if (atkbd->write) { |
| 1171 | if (atkbd_probe(atkbd)) | 1195 | if (atkbd_probe(atkbd)) |
| 1172 | return -1; | 1196 | goto out; |
| 1197 | |||
| 1173 | if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) | 1198 | if (atkbd->set != atkbd_select_set(atkbd, atkbd->set, atkbd->extra)) |
| 1174 | return -1; | 1199 | goto out; |
| 1175 | 1200 | ||
| 1176 | atkbd_activate(atkbd); | 1201 | atkbd_activate(atkbd); |
| 1177 | 1202 | ||
| @@ -1189,8 +1214,11 @@ static int atkbd_reconnect(struct serio *serio) | |||
| 1189 | } | 1214 | } |
| 1190 | 1215 | ||
| 1191 | atkbd_enable(atkbd); | 1216 | atkbd_enable(atkbd); |
| 1217 | retval = 0; | ||
| 1192 | 1218 | ||
| 1193 | return 0; | 1219 | out: |
| 1220 | mutex_unlock(&atkbd->mutex); | ||
| 1221 | return retval; | ||
| 1194 | } | 1222 | } |
| 1195 | 1223 | ||
| 1196 | static struct serio_device_id atkbd_serio_ids[] = { | 1224 | static struct serio_device_id atkbd_serio_ids[] = { |
| @@ -1234,47 +1262,28 @@ static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf, | |||
| 1234 | ssize_t (*handler)(struct atkbd *, char *)) | 1262 | ssize_t (*handler)(struct atkbd *, char *)) |
| 1235 | { | 1263 | { |
| 1236 | struct serio *serio = to_serio_port(dev); | 1264 | struct serio *serio = to_serio_port(dev); |
| 1237 | int retval; | 1265 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 1238 | |||
| 1239 | retval = serio_pin_driver(serio); | ||
| 1240 | if (retval) | ||
| 1241 | return retval; | ||
| 1242 | |||
| 1243 | if (serio->drv != &atkbd_drv) { | ||
| 1244 | retval = -ENODEV; | ||
| 1245 | goto out; | ||
| 1246 | } | ||
| 1247 | |||
| 1248 | retval = handler((struct atkbd *)serio_get_drvdata(serio), buf); | ||
| 1249 | 1266 | ||
| 1250 | out: | 1267 | return handler(atkbd, buf); |
| 1251 | serio_unpin_driver(serio); | ||
| 1252 | return retval; | ||
| 1253 | } | 1268 | } |
| 1254 | 1269 | ||
| 1255 | static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, | 1270 | static ssize_t atkbd_attr_set_helper(struct device *dev, const char *buf, size_t count, |
| 1256 | ssize_t (*handler)(struct atkbd *, const char *, size_t)) | 1271 | ssize_t (*handler)(struct atkbd *, const char *, size_t)) |
| 1257 | { | 1272 | { |
| 1258 | struct serio *serio = to_serio_port(dev); | 1273 | struct serio *serio = to_serio_port(dev); |
| 1259 | struct atkbd *atkbd; | 1274 | struct atkbd *atkbd = serio_get_drvdata(serio); |
| 1260 | int retval; | 1275 | int retval; |
| 1261 | 1276 | ||
| 1262 | retval = serio_pin_driver(serio); | 1277 | retval = mutex_lock_interruptible(&atkbd->mutex); |
| 1263 | if (retval) | 1278 | if (retval) |
| 1264 | return retval; | 1279 | return retval; |
| 1265 | 1280 | ||
| 1266 | if (serio->drv != &atkbd_drv) { | ||
| 1267 | retval = -ENODEV; | ||
| 1268 | goto out; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | atkbd = serio_get_drvdata(serio); | ||
| 1272 | atkbd_disable(atkbd); | 1281 | atkbd_disable(atkbd); |
| 1273 | retval = handler(atkbd, buf, count); | 1282 | retval = handler(atkbd, buf, count); |
| 1274 | atkbd_enable(atkbd); | 1283 | atkbd_enable(atkbd); |
| 1275 | 1284 | ||
| 1276 | out: | 1285 | mutex_unlock(&atkbd->mutex); |
| 1277 | serio_unpin_driver(serio); | 1286 | |
| 1278 | return retval; | 1287 | return retval; |
| 1279 | } | 1288 | } |
| 1280 | 1289 | ||
| @@ -1288,7 +1297,8 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun | |||
| 1288 | struct input_dev *old_dev, *new_dev; | 1297 | struct input_dev *old_dev, *new_dev; |
| 1289 | unsigned long value; | 1298 | unsigned long value; |
| 1290 | int err; | 1299 | int err; |
| 1291 | unsigned char old_extra, old_set; | 1300 | bool old_extra; |
| 1301 | unsigned char old_set; | ||
| 1292 | 1302 | ||
| 1293 | if (!atkbd->write) | 1303 | if (!atkbd->write) |
| 1294 | return -EIO; | 1304 | return -EIO; |
| @@ -1371,7 +1381,7 @@ static ssize_t atkbd_set_scroll(struct atkbd *atkbd, const char *buf, size_t cou | |||
| 1371 | struct input_dev *old_dev, *new_dev; | 1381 | struct input_dev *old_dev, *new_dev; |
| 1372 | unsigned long value; | 1382 | unsigned long value; |
| 1373 | int err; | 1383 | int err; |
| 1374 | unsigned char old_scroll; | 1384 | bool old_scroll; |
| 1375 | 1385 | ||
| 1376 | if (strict_strtoul(buf, 10, &value) || value > 1) | 1386 | if (strict_strtoul(buf, 10, &value) || value > 1) |
| 1377 | return -EINVAL; | 1387 | return -EINVAL; |
| @@ -1415,7 +1425,8 @@ static ssize_t atkbd_set_set(struct atkbd *atkbd, const char *buf, size_t count) | |||
| 1415 | struct input_dev *old_dev, *new_dev; | 1425 | struct input_dev *old_dev, *new_dev; |
| 1416 | unsigned long value; | 1426 | unsigned long value; |
| 1417 | int err; | 1427 | int err; |
| 1418 | unsigned char old_set, old_extra; | 1428 | unsigned char old_set; |
| 1429 | bool old_extra; | ||
| 1419 | 1430 | ||
| 1420 | if (!atkbd->write) | 1431 | if (!atkbd->write) |
| 1421 | return -EIO; | 1432 | return -EIO; |
| @@ -1465,7 +1476,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t | |||
| 1465 | struct input_dev *old_dev, *new_dev; | 1476 | struct input_dev *old_dev, *new_dev; |
| 1466 | unsigned long value; | 1477 | unsigned long value; |
| 1467 | int err; | 1478 | int err; |
| 1468 | unsigned char old_softrepeat, old_softraw; | 1479 | bool old_softrepeat, old_softraw; |
| 1469 | 1480 | ||
| 1470 | if (!atkbd->write) | 1481 | if (!atkbd->write) |
| 1471 | return -EIO; | 1482 | return -EIO; |
| @@ -1485,7 +1496,7 @@ static ssize_t atkbd_set_softrepeat(struct atkbd *atkbd, const char *buf, size_t | |||
| 1485 | atkbd->dev = new_dev; | 1496 | atkbd->dev = new_dev; |
| 1486 | atkbd->softrepeat = value; | 1497 | atkbd->softrepeat = value; |
| 1487 | if (atkbd->softrepeat) | 1498 | if (atkbd->softrepeat) |
| 1488 | atkbd->softraw = 1; | 1499 | atkbd->softraw = true; |
| 1489 | atkbd_set_device_attrs(atkbd); | 1500 | atkbd_set_device_attrs(atkbd); |
| 1490 | 1501 | ||
| 1491 | err = input_register_device(atkbd->dev); | 1502 | err = input_register_device(atkbd->dev); |
| @@ -1515,7 +1526,7 @@ static ssize_t atkbd_set_softraw(struct atkbd *atkbd, const char *buf, size_t co | |||
| 1515 | struct input_dev *old_dev, *new_dev; | 1526 | struct input_dev *old_dev, *new_dev; |
| 1516 | unsigned long value; | 1527 | unsigned long value; |
| 1517 | int err; | 1528 | int err; |
| 1518 | unsigned char old_softraw; | 1529 | bool old_softraw; |
| 1519 | 1530 | ||
| 1520 | if (strict_strtoul(buf, 10, &value) || value > 1) | 1531 | if (strict_strtoul(buf, 10, &value) || value > 1) |
| 1521 | return -EINVAL; | 1532 | return -EINVAL; |
| @@ -1567,9 +1578,8 @@ static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id) | |||
| 1567 | return 0; | 1578 | return 0; |
| 1568 | } | 1579 | } |
| 1569 | 1580 | ||
| 1570 | static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | 1581 | static const struct dmi_system_id atkbd_dmi_quirk_table[] __initconst = { |
| 1571 | { | 1582 | { |
| 1572 | .ident = "Dell Laptop", | ||
| 1573 | .matches = { | 1583 | .matches = { |
| 1574 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 1584 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 1575 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1585 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
| @@ -1578,7 +1588,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1578 | .driver_data = atkbd_dell_laptop_forced_release_keys, | 1588 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
| 1579 | }, | 1589 | }, |
| 1580 | { | 1590 | { |
| 1581 | .ident = "Dell Laptop", | ||
| 1582 | .matches = { | 1591 | .matches = { |
| 1583 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), | 1592 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer Corporation"), |
| 1584 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 1593 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
| @@ -1587,7 +1596,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1587 | .driver_data = atkbd_dell_laptop_forced_release_keys, | 1596 | .driver_data = atkbd_dell_laptop_forced_release_keys, |
| 1588 | }, | 1597 | }, |
| 1589 | { | 1598 | { |
| 1590 | .ident = "HP 2133", | ||
| 1591 | .matches = { | 1599 | .matches = { |
| 1592 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1600 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 1593 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), | 1601 | DMI_MATCH(DMI_PRODUCT_NAME, "HP 2133"), |
| @@ -1596,7 +1604,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1596 | .driver_data = atkbd_hp_forced_release_keys, | 1604 | .driver_data = atkbd_hp_forced_release_keys, |
| 1597 | }, | 1605 | }, |
| 1598 | { | 1606 | { |
| 1599 | .ident = "HP Pavilion ZV6100", | ||
| 1600 | .matches = { | 1607 | .matches = { |
| 1601 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1608 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 1602 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), | 1609 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"), |
| @@ -1605,7 +1612,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1605 | .driver_data = atkbd_volume_forced_release_keys, | 1612 | .driver_data = atkbd_volume_forced_release_keys, |
| 1606 | }, | 1613 | }, |
| 1607 | { | 1614 | { |
| 1608 | .ident = "HP Presario R4000", | ||
| 1609 | .matches = { | 1615 | .matches = { |
| 1610 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1616 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 1611 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), | 1617 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"), |
| @@ -1614,7 +1620,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1614 | .driver_data = atkbd_volume_forced_release_keys, | 1620 | .driver_data = atkbd_volume_forced_release_keys, |
| 1615 | }, | 1621 | }, |
| 1616 | { | 1622 | { |
| 1617 | .ident = "HP Presario R4100", | ||
| 1618 | .matches = { | 1623 | .matches = { |
| 1619 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1624 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 1620 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), | 1625 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"), |
| @@ -1623,7 +1628,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1623 | .driver_data = atkbd_volume_forced_release_keys, | 1628 | .driver_data = atkbd_volume_forced_release_keys, |
| 1624 | }, | 1629 | }, |
| 1625 | { | 1630 | { |
| 1626 | .ident = "HP Presario R4200", | ||
| 1627 | .matches = { | 1631 | .matches = { |
| 1628 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 1632 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 1629 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), | 1633 | DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"), |
| @@ -1632,7 +1636,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1632 | .driver_data = atkbd_volume_forced_release_keys, | 1636 | .driver_data = atkbd_volume_forced_release_keys, |
| 1633 | }, | 1637 | }, |
| 1634 | { | 1638 | { |
| 1635 | .ident = "Inventec Symphony", | 1639 | /* Inventec Symphony */ |
| 1636 | .matches = { | 1640 | .matches = { |
| 1637 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), | 1641 | DMI_MATCH(DMI_SYS_VENDOR, "INVENTEC"), |
| 1638 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), | 1642 | DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"), |
| @@ -1641,7 +1645,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1641 | .driver_data = atkbd_volume_forced_release_keys, | 1645 | .driver_data = atkbd_volume_forced_release_keys, |
| 1642 | }, | 1646 | }, |
| 1643 | { | 1647 | { |
| 1644 | .ident = "Samsung NC10", | 1648 | /* Samsung NC10 */ |
| 1645 | .matches = { | 1649 | .matches = { |
| 1646 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | 1650 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), |
| 1647 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), | 1651 | DMI_MATCH(DMI_PRODUCT_NAME, "NC10"), |
| @@ -1650,7 +1654,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1650 | .driver_data = atkbd_samsung_forced_release_keys, | 1654 | .driver_data = atkbd_samsung_forced_release_keys, |
| 1651 | }, | 1655 | }, |
| 1652 | { | 1656 | { |
| 1653 | .ident = "Samsung NC20", | 1657 | /* Samsung NC20 */ |
| 1654 | .matches = { | 1658 | .matches = { |
| 1655 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | 1659 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), |
| 1656 | DMI_MATCH(DMI_PRODUCT_NAME, "NC20"), | 1660 | DMI_MATCH(DMI_PRODUCT_NAME, "NC20"), |
| @@ -1659,7 +1663,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1659 | .driver_data = atkbd_samsung_forced_release_keys, | 1663 | .driver_data = atkbd_samsung_forced_release_keys, |
| 1660 | }, | 1664 | }, |
| 1661 | { | 1665 | { |
| 1662 | .ident = "Samsung SQ45S70S", | 1666 | /* Samsung SQ45S70S */ |
| 1663 | .matches = { | 1667 | .matches = { |
| 1664 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | 1668 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), |
| 1665 | DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"), | 1669 | DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"), |
| @@ -1668,7 +1672,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1668 | .driver_data = atkbd_samsung_forced_release_keys, | 1672 | .driver_data = atkbd_samsung_forced_release_keys, |
| 1669 | }, | 1673 | }, |
| 1670 | { | 1674 | { |
| 1671 | .ident = "Fujitsu Amilo PA 1510", | 1675 | /* Fujitsu Amilo PA 1510 */ |
| 1672 | .matches = { | 1676 | .matches = { |
| 1673 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1677 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 1674 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), | 1678 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"), |
| @@ -1677,7 +1681,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1677 | .driver_data = atkbd_volume_forced_release_keys, | 1681 | .driver_data = atkbd_volume_forced_release_keys, |
| 1678 | }, | 1682 | }, |
| 1679 | { | 1683 | { |
| 1680 | .ident = "Fujitsu Amilo Pi 3525", | 1684 | /* Fujitsu Amilo Pi 3525 */ |
| 1681 | .matches = { | 1685 | .matches = { |
| 1682 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1686 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 1683 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"), | 1687 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pi 3525"), |
| @@ -1686,7 +1690,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1686 | .driver_data = atkbd_amilo_pi3525_forced_release_keys, | 1690 | .driver_data = atkbd_amilo_pi3525_forced_release_keys, |
| 1687 | }, | 1691 | }, |
| 1688 | { | 1692 | { |
| 1689 | .ident = "Fujitsu Amilo Xi 3650", | 1693 | /* Fujitsu Amilo Xi 3650 */ |
| 1690 | .matches = { | 1694 | .matches = { |
| 1691 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 1695 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 1692 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"), | 1696 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Xi 3650"), |
| @@ -1695,7 +1699,6 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1695 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, | 1699 | .driver_data = atkbd_amilo_xi3650_forced_release_keys, |
| 1696 | }, | 1700 | }, |
| 1697 | { | 1701 | { |
| 1698 | .ident = "Soltech Corporation TA12", | ||
| 1699 | .matches = { | 1702 | .matches = { |
| 1700 | DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"), | 1703 | DMI_MATCH(DMI_SYS_VENDOR, "Soltech Corporation"), |
| 1701 | DMI_MATCH(DMI_PRODUCT_NAME, "TA12"), | 1704 | DMI_MATCH(DMI_PRODUCT_NAME, "TA12"), |
| @@ -1704,7 +1707,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = { | |||
| 1704 | .driver_data = atkdb_soltech_ta12_forced_release_keys, | 1707 | .driver_data = atkdb_soltech_ta12_forced_release_keys, |
| 1705 | }, | 1708 | }, |
| 1706 | { | 1709 | { |
| 1707 | .ident = "OQO Model 01+", | 1710 | /* OQO Model 01+ */ |
| 1708 | .matches = { | 1711 | .matches = { |
| 1709 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), | 1712 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), |
| 1710 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), | 1713 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), |
diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fe376a27fe57..7d989603f875 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
| 35 | #include <linux/interrupt.h> | 35 | #include <linux/interrupt.h> |
| 36 | #include <linux/irq.h> | 36 | #include <linux/irq.h> |
| 37 | #include <linux/slab.h> | ||
| 37 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
| 38 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
| 39 | #include <linux/sysctl.h> | 40 | #include <linux/sysctl.h> |
| @@ -162,7 +163,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) | |||
| 162 | input_sync(input); | 163 | input_sync(input); |
| 163 | 164 | ||
| 164 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { | 165 | if (bfin_kpad_get_keypressed(bf54x_kpad)) { |
| 165 | disable_irq(bf54x_kpad->irq); | 166 | disable_irq_nosync(bf54x_kpad->irq); |
| 166 | bf54x_kpad->lastkey = key; | 167 | bf54x_kpad->lastkey = key; |
| 167 | mod_timer(&bf54x_kpad->timer, | 168 | mod_timer(&bf54x_kpad->timer, |
| 168 | jiffies + bf54x_kpad->keyup_test_jiffies); | 169 | jiffies + bf54x_kpad->keyup_test_jiffies); |
diff --git a/drivers/input/keyboard/davinci_keyscan.c b/drivers/input/keyboard/davinci_keyscan.c new file mode 100644 index 000000000000..a91ee941b5c1 --- /dev/null +++ b/drivers/input/keyboard/davinci_keyscan.c | |||
| @@ -0,0 +1,346 @@ | |||
| 1 | /* | ||
| 2 | * DaVinci Key Scan Driver for TI platforms | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Texas Instruments, Inc | ||
| 5 | * | ||
| 6 | * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com> | ||
| 7 | * | ||
| 8 | * Intial Code: Sandeep Paulraj <s-paulraj@ti.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This program is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | */ | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/types.h> | ||
| 28 | #include <linux/input.h> | ||
| 29 | #include <linux/kernel.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/platform_device.h> | ||
| 32 | #include <linux/errno.h> | ||
| 33 | #include <linux/slab.h> | ||
| 34 | |||
| 35 | #include <asm/irq.h> | ||
| 36 | |||
| 37 | #include <mach/hardware.h> | ||
| 38 | #include <mach/irqs.h> | ||
| 39 | #include <mach/keyscan.h> | ||
| 40 | |||
| 41 | /* Key scan registers */ | ||
| 42 | #define DAVINCI_KEYSCAN_KEYCTRL 0x0000 | ||
| 43 | #define DAVINCI_KEYSCAN_INTENA 0x0004 | ||
| 44 | #define DAVINCI_KEYSCAN_INTFLAG 0x0008 | ||
| 45 | #define DAVINCI_KEYSCAN_INTCLR 0x000c | ||
| 46 | #define DAVINCI_KEYSCAN_STRBWIDTH 0x0010 | ||
| 47 | #define DAVINCI_KEYSCAN_INTERVAL 0x0014 | ||
| 48 | #define DAVINCI_KEYSCAN_CONTTIME 0x0018 | ||
| 49 | #define DAVINCI_KEYSCAN_CURRENTST 0x001c | ||
| 50 | #define DAVINCI_KEYSCAN_PREVSTATE 0x0020 | ||
| 51 | #define DAVINCI_KEYSCAN_EMUCTRL 0x0024 | ||
| 52 | #define DAVINCI_KEYSCAN_IODFTCTRL 0x002c | ||
| 53 | |||
| 54 | /* Key Control Register (KEYCTRL) */ | ||
| 55 | #define DAVINCI_KEYSCAN_KEYEN 0x00000001 | ||
| 56 | #define DAVINCI_KEYSCAN_PREVMODE 0x00000002 | ||
| 57 | #define DAVINCI_KEYSCAN_CHATOFF 0x00000004 | ||
| 58 | #define DAVINCI_KEYSCAN_AUTODET 0x00000008 | ||
| 59 | #define DAVINCI_KEYSCAN_SCANMODE 0x00000010 | ||
| 60 | #define DAVINCI_KEYSCAN_OUTTYPE 0x00000020 | ||
| 61 | |||
| 62 | /* Masks for the interrupts */ | ||
| 63 | #define DAVINCI_KEYSCAN_INT_CONT 0x00000008 | ||
| 64 | #define DAVINCI_KEYSCAN_INT_OFF 0x00000004 | ||
| 65 | #define DAVINCI_KEYSCAN_INT_ON 0x00000002 | ||
| 66 | #define DAVINCI_KEYSCAN_INT_CHANGE 0x00000001 | ||
| 67 | #define DAVINCI_KEYSCAN_INT_ALL 0x0000000f | ||
| 68 | |||
| 69 | struct davinci_ks { | ||
| 70 | struct input_dev *input; | ||
| 71 | struct davinci_ks_platform_data *pdata; | ||
| 72 | int irq; | ||
| 73 | void __iomem *base; | ||
| 74 | resource_size_t pbase; | ||
| 75 | size_t base_size; | ||
| 76 | unsigned short keymap[]; | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* Initializing the kp Module */ | ||
| 80 | static int __init davinci_ks_initialize(struct davinci_ks *davinci_ks) | ||
| 81 | { | ||
| 82 | struct device *dev = &davinci_ks->input->dev; | ||
| 83 | struct davinci_ks_platform_data *pdata = davinci_ks->pdata; | ||
| 84 | u32 matrix_ctrl; | ||
| 85 | |||
| 86 | /* Enable all interrupts */ | ||
| 87 | __raw_writel(DAVINCI_KEYSCAN_INT_ALL, | ||
| 88 | davinci_ks->base + DAVINCI_KEYSCAN_INTENA); | ||
| 89 | |||
| 90 | /* Clear interrupts if any */ | ||
| 91 | __raw_writel(DAVINCI_KEYSCAN_INT_ALL, | ||
| 92 | davinci_ks->base + DAVINCI_KEYSCAN_INTCLR); | ||
| 93 | |||
| 94 | /* Setup the scan period = strobe + interval */ | ||
| 95 | __raw_writel(pdata->strobe, | ||
| 96 | davinci_ks->base + DAVINCI_KEYSCAN_STRBWIDTH); | ||
| 97 | __raw_writel(pdata->interval, | ||
| 98 | davinci_ks->base + DAVINCI_KEYSCAN_INTERVAL); | ||
| 99 | __raw_writel(0x01, | ||
| 100 | davinci_ks->base + DAVINCI_KEYSCAN_CONTTIME); | ||
| 101 | |||
| 102 | /* Define matrix type */ | ||
| 103 | switch (pdata->matrix_type) { | ||
| 104 | case DAVINCI_KEYSCAN_MATRIX_4X4: | ||
| 105 | matrix_ctrl = 0; | ||
| 106 | break; | ||
| 107 | case DAVINCI_KEYSCAN_MATRIX_5X3: | ||
| 108 | matrix_ctrl = (1 << 6); | ||
| 109 | break; | ||
| 110 | default: | ||
| 111 | dev_err(dev->parent, "wrong matrix type\n"); | ||
| 112 | return -EINVAL; | ||
| 113 | } | ||
| 114 | |||
| 115 | /* Enable key scan module and set matrix type */ | ||
| 116 | __raw_writel(DAVINCI_KEYSCAN_AUTODET | DAVINCI_KEYSCAN_KEYEN | | ||
| 117 | matrix_ctrl, davinci_ks->base + DAVINCI_KEYSCAN_KEYCTRL); | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static irqreturn_t davinci_ks_interrupt(int irq, void *dev_id) | ||
| 123 | { | ||
| 124 | struct davinci_ks *davinci_ks = dev_id; | ||
| 125 | struct device *dev = &davinci_ks->input->dev; | ||
| 126 | unsigned short *keymap = davinci_ks->keymap; | ||
| 127 | int keymapsize = davinci_ks->pdata->keymapsize; | ||
| 128 | u32 prev_status, new_status, changed; | ||
| 129 | bool release; | ||
| 130 | int keycode = KEY_UNKNOWN; | ||
| 131 | int i; | ||
| 132 | |||
| 133 | /* Disable interrupt */ | ||
| 134 | __raw_writel(0x0, davinci_ks->base + DAVINCI_KEYSCAN_INTENA); | ||
| 135 | |||
| 136 | /* Reading previous and new status of the key scan */ | ||
| 137 | prev_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_PREVSTATE); | ||
| 138 | new_status = __raw_readl(davinci_ks->base + DAVINCI_KEYSCAN_CURRENTST); | ||
| 139 | |||
| 140 | changed = prev_status ^ new_status; | ||
| 141 | |||
| 142 | if (changed) { | ||
| 143 | /* | ||
| 144 | * It goes through all bits in 'changed' to ensure | ||
| 145 | * that no key changes are being missed | ||
| 146 | */ | ||
| 147 | for (i = 0 ; i < keymapsize; i++) { | ||
| 148 | if ((changed>>i) & 0x1) { | ||
| 149 | keycode = keymap[i]; | ||
| 150 | release = (new_status >> i) & 0x1; | ||
| 151 | dev_dbg(dev->parent, "key %d %s\n", keycode, | ||
| 152 | release ? "released" : "pressed"); | ||
| 153 | input_report_key(davinci_ks->input, keycode, | ||
| 154 | !release); | ||
| 155 | input_sync(davinci_ks->input); | ||
| 156 | } | ||
| 157 | } | ||
| 158 | /* Clearing interrupt */ | ||
| 159 | __raw_writel(DAVINCI_KEYSCAN_INT_ALL, | ||
| 160 | davinci_ks->base + DAVINCI_KEYSCAN_INTCLR); | ||
| 161 | } | ||
| 162 | |||
| 163 | /* Enable interrupts */ | ||
| 164 | __raw_writel(0x1, davinci_ks->base + DAVINCI_KEYSCAN_INTENA); | ||
| 165 | |||
| 166 | return IRQ_HANDLED; | ||
| 167 | } | ||
| 168 | |||
| 169 | static int __init davinci_ks_probe(struct platform_device *pdev) | ||
| 170 | { | ||
| 171 | struct davinci_ks *davinci_ks; | ||
| 172 | struct input_dev *key_dev; | ||
| 173 | struct resource *res, *mem; | ||
| 174 | struct device *dev = &pdev->dev; | ||
| 175 | struct davinci_ks_platform_data *pdata = pdev->dev.platform_data; | ||
| 176 | int error, i; | ||
| 177 | |||
| 178 | if (pdata->device_enable) { | ||
| 179 | error = pdata->device_enable(dev); | ||
| 180 | if (error < 0) { | ||
| 181 | dev_dbg(dev, "device enable function failed\n"); | ||
| 182 | return error; | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (!pdata->keymap) { | ||
| 187 | dev_dbg(dev, "no keymap from pdata\n"); | ||
| 188 | return -EINVAL; | ||
| 189 | } | ||
| 190 | |||
| 191 | davinci_ks = kzalloc(sizeof(struct davinci_ks) + | ||
| 192 | sizeof(unsigned short) * pdata->keymapsize, GFP_KERNEL); | ||
| 193 | if (!davinci_ks) { | ||
| 194 | dev_dbg(dev, "could not allocate memory for private data\n"); | ||
| 195 | return -ENOMEM; | ||
| 196 | } | ||
| 197 | |||
| 198 | memcpy(davinci_ks->keymap, pdata->keymap, | ||
| 199 | sizeof(unsigned short) * pdata->keymapsize); | ||
| 200 | |||
| 201 | key_dev = input_allocate_device(); | ||
| 202 | if (!key_dev) { | ||
| 203 | dev_dbg(dev, "could not allocate input device\n"); | ||
| 204 | error = -ENOMEM; | ||
| 205 | goto fail1; | ||
| 206 | } | ||
| 207 | |||
| 208 | davinci_ks->input = key_dev; | ||
| 209 | |||
| 210 | davinci_ks->irq = platform_get_irq(pdev, 0); | ||
| 211 | if (davinci_ks->irq < 0) { | ||
| 212 | dev_err(dev, "no key scan irq\n"); | ||
| 213 | error = davinci_ks->irq; | ||
| 214 | goto fail2; | ||
| 215 | } | ||
| 216 | |||
| 217 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 218 | if (!res) { | ||
| 219 | dev_err(dev, "no mem resource\n"); | ||
| 220 | error = -EINVAL; | ||
| 221 | goto fail2; | ||
| 222 | } | ||
| 223 | |||
| 224 | davinci_ks->pbase = res->start; | ||
| 225 | davinci_ks->base_size = resource_size(res); | ||
| 226 | |||
| 227 | mem = request_mem_region(davinci_ks->pbase, davinci_ks->base_size, | ||
| 228 | pdev->name); | ||
| 229 | if (!mem) { | ||
| 230 | dev_err(dev, "key scan registers at %08x are not free\n", | ||
| 231 | davinci_ks->pbase); | ||
| 232 | error = -EBUSY; | ||
| 233 | goto fail2; | ||
| 234 | } | ||
| 235 | |||
| 236 | davinci_ks->base = ioremap(davinci_ks->pbase, davinci_ks->base_size); | ||
| 237 | if (!davinci_ks->base) { | ||
| 238 | dev_err(dev, "can't ioremap MEM resource.\n"); | ||
| 239 | error = -ENOMEM; | ||
| 240 | goto fail3; | ||
| 241 | } | ||
| 242 | |||
| 243 | /* Enable auto repeat feature of Linux input subsystem */ | ||
| 244 | if (pdata->rep) | ||
| 245 | __set_bit(EV_REP, key_dev->evbit); | ||
| 246 | |||
| 247 | /* Setup input device */ | ||
| 248 | __set_bit(EV_KEY, key_dev->evbit); | ||
| 249 | |||
| 250 | /* Setup the platform data */ | ||
| 251 | davinci_ks->pdata = pdata; | ||
| 252 | |||
| 253 | for (i = 0; i < davinci_ks->pdata->keymapsize; i++) | ||
| 254 | __set_bit(davinci_ks->pdata->keymap[i], key_dev->keybit); | ||
| 255 | |||
| 256 | key_dev->name = "davinci_keyscan"; | ||
| 257 | key_dev->phys = "davinci_keyscan/input0"; | ||
| 258 | key_dev->dev.parent = &pdev->dev; | ||
| 259 | key_dev->id.bustype = BUS_HOST; | ||
| 260 | key_dev->id.vendor = 0x0001; | ||
| 261 | key_dev->id.product = 0x0001; | ||
| 262 | key_dev->id.version = 0x0001; | ||
| 263 | key_dev->keycode = davinci_ks->keymap; | ||
| 264 | key_dev->keycodesize = sizeof(davinci_ks->keymap[0]); | ||
| 265 | key_dev->keycodemax = davinci_ks->pdata->keymapsize; | ||
| 266 | |||
| 267 | error = input_register_device(davinci_ks->input); | ||
| 268 | if (error < 0) { | ||
| 269 | dev_err(dev, "unable to register davinci key scan device\n"); | ||
| 270 | goto fail4; | ||
| 271 | } | ||
| 272 | |||
| 273 | error = request_irq(davinci_ks->irq, davinci_ks_interrupt, | ||
| 274 | IRQF_DISABLED, pdev->name, davinci_ks); | ||
| 275 | if (error < 0) { | ||
| 276 | dev_err(dev, "unable to register davinci key scan interrupt\n"); | ||
| 277 | goto fail5; | ||
| 278 | } | ||
| 279 | |||
| 280 | error = davinci_ks_initialize(davinci_ks); | ||
| 281 | if (error < 0) { | ||
| 282 | dev_err(dev, "unable to initialize davinci key scan device\n"); | ||
| 283 | goto fail6; | ||
| 284 | } | ||
| 285 | |||
| 286 | platform_set_drvdata(pdev, davinci_ks); | ||
| 287 | return 0; | ||
| 288 | |||
| 289 | fail6: | ||
| 290 | free_irq(davinci_ks->irq, davinci_ks); | ||
| 291 | fail5: | ||
| 292 | input_unregister_device(davinci_ks->input); | ||
| 293 | key_dev = NULL; | ||
| 294 | fail4: | ||
| 295 | iounmap(davinci_ks->base); | ||
| 296 | fail3: | ||
| 297 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); | ||
| 298 | fail2: | ||
| 299 | input_free_device(key_dev); | ||
| 300 | fail1: | ||
| 301 | kfree(davinci_ks); | ||
| 302 | |||
| 303 | return error; | ||
| 304 | } | ||
| 305 | |||
| 306 | static int __devexit davinci_ks_remove(struct platform_device *pdev) | ||
| 307 | { | ||
| 308 | struct davinci_ks *davinci_ks = platform_get_drvdata(pdev); | ||
| 309 | |||
| 310 | free_irq(davinci_ks->irq, davinci_ks); | ||
| 311 | |||
| 312 | input_unregister_device(davinci_ks->input); | ||
| 313 | |||
| 314 | iounmap(davinci_ks->base); | ||
| 315 | release_mem_region(davinci_ks->pbase, davinci_ks->base_size); | ||
| 316 | |||
| 317 | platform_set_drvdata(pdev, NULL); | ||
| 318 | |||
| 319 | kfree(davinci_ks); | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct platform_driver davinci_ks_driver = { | ||
| 325 | .driver = { | ||
| 326 | .name = "davinci_keyscan", | ||
| 327 | .owner = THIS_MODULE, | ||
| 328 | }, | ||
| 329 | .remove = __devexit_p(davinci_ks_remove), | ||
| 330 | }; | ||
| 331 | |||
| 332 | static int __init davinci_ks_init(void) | ||
| 333 | { | ||
| 334 | return platform_driver_probe(&davinci_ks_driver, davinci_ks_probe); | ||
| 335 | } | ||
| 336 | module_init(davinci_ks_init); | ||
| 337 | |||
| 338 | static void __exit davinci_ks_exit(void) | ||
| 339 | { | ||
| 340 | platform_driver_unregister(&davinci_ks_driver); | ||
| 341 | } | ||
| 342 | module_exit(davinci_ks_exit); | ||
| 343 | |||
| 344 | MODULE_AUTHOR("Miguel Aguilar"); | ||
| 345 | MODULE_DESCRIPTION("Texas Instruments DaVinci Key Scan Driver"); | ||
| 346 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 181d30e3018e..c8242dd190d0 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c | |||
| @@ -22,11 +22,12 @@ | |||
| 22 | 22 | ||
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/input/matrix_keypad.h> | ||
| 28 | #include <linux/slab.h> | ||
| 27 | 29 | ||
| 28 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
| 29 | #include <mach/gpio.h> | ||
| 30 | #include <mach/ep93xx_keypad.h> | 31 | #include <mach/ep93xx_keypad.h> |
| 31 | 32 | ||
| 32 | /* | 33 | /* |
| @@ -60,56 +61,39 @@ | |||
| 60 | #define KEY_REG_KEY1_MASK (0x0000003f) | 61 | #define KEY_REG_KEY1_MASK (0x0000003f) |
| 61 | #define KEY_REG_KEY1_SHIFT (0) | 62 | #define KEY_REG_KEY1_SHIFT (0) |
| 62 | 63 | ||
| 63 | #define keypad_readl(off) __raw_readl(keypad->mmio_base + (off)) | 64 | #define EP93XX_MATRIX_SIZE (EP93XX_MATRIX_ROWS * EP93XX_MATRIX_COLS) |
| 64 | #define keypad_writel(v, off) __raw_writel((v), keypad->mmio_base + (off)) | ||
| 65 | |||
| 66 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) | ||
| 67 | 65 | ||
| 68 | struct ep93xx_keypad { | 66 | struct ep93xx_keypad { |
| 69 | struct ep93xx_keypad_platform_data *pdata; | 67 | struct ep93xx_keypad_platform_data *pdata; |
| 70 | |||
| 71 | struct clk *clk; | ||
| 72 | struct input_dev *input_dev; | 68 | struct input_dev *input_dev; |
| 69 | struct clk *clk; | ||
| 70 | |||
| 73 | void __iomem *mmio_base; | 71 | void __iomem *mmio_base; |
| 74 | 72 | ||
| 75 | int irq; | 73 | unsigned short keycodes[EP93XX_MATRIX_SIZE]; |
| 76 | int enabled; | ||
| 77 | 74 | ||
| 78 | int key1; | 75 | int key1; |
| 79 | int key2; | 76 | int key2; |
| 80 | 77 | ||
| 81 | unsigned int matrix_keycodes[MAX_MATRIX_KEY_NUM]; | 78 | int irq; |
| 82 | }; | ||
| 83 | |||
| 84 | static void ep93xx_keypad_build_keycode(struct ep93xx_keypad *keypad) | ||
| 85 | { | ||
| 86 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | ||
| 87 | struct input_dev *input_dev = keypad->input_dev; | ||
| 88 | int i; | ||
| 89 | |||
| 90 | for (i = 0; i < pdata->matrix_key_map_size; i++) { | ||
| 91 | unsigned int key = pdata->matrix_key_map[i]; | ||
| 92 | int row = (key >> 28) & 0xf; | ||
| 93 | int col = (key >> 24) & 0xf; | ||
| 94 | int code = key & 0xffffff; | ||
| 95 | 79 | ||
| 96 | keypad->matrix_keycodes[(row << 3) + col] = code; | 80 | bool enabled; |
| 97 | __set_bit(code, input_dev->keybit); | 81 | }; |
| 98 | } | ||
| 99 | } | ||
| 100 | 82 | ||
| 101 | static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) | 83 | static irqreturn_t ep93xx_keypad_irq_handler(int irq, void *dev_id) |
| 102 | { | 84 | { |
| 103 | struct ep93xx_keypad *keypad = dev_id; | 85 | struct ep93xx_keypad *keypad = dev_id; |
| 104 | struct input_dev *input_dev = keypad->input_dev; | 86 | struct input_dev *input_dev = keypad->input_dev; |
| 105 | unsigned int status = keypad_readl(KEY_REG); | 87 | unsigned int status; |
| 106 | int keycode, key1, key2; | 88 | int keycode, key1, key2; |
| 107 | 89 | ||
| 90 | status = __raw_readl(keypad->mmio_base + KEY_REG); | ||
| 91 | |||
| 108 | keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; | 92 | keycode = (status & KEY_REG_KEY1_MASK) >> KEY_REG_KEY1_SHIFT; |
| 109 | key1 = keypad->matrix_keycodes[keycode]; | 93 | key1 = keypad->keycodes[keycode]; |
| 110 | 94 | ||
| 111 | keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT; | 95 | keycode = (status & KEY_REG_KEY2_MASK) >> KEY_REG_KEY2_SHIFT; |
| 112 | key2 = keypad->matrix_keycodes[keycode]; | 96 | key2 = keypad->keycodes[keycode]; |
| 113 | 97 | ||
| 114 | if (status & KEY_REG_2KEYS) { | 98 | if (status & KEY_REG_2KEYS) { |
| 115 | if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1) | 99 | if (keypad->key1 && key1 != keypad->key1 && key2 != keypad->key1) |
| @@ -152,7 +136,10 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) | |||
| 152 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; | 136 | struct ep93xx_keypad_platform_data *pdata = keypad->pdata; |
| 153 | unsigned int val = 0; | 137 | unsigned int val = 0; |
| 154 | 138 | ||
| 155 | clk_set_rate(keypad->clk, pdata->flags & EP93XX_KEYPAD_KDIV); | 139 | if (pdata->flags & EP93XX_KEYPAD_KDIV) |
| 140 | clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4); | ||
| 141 | else | ||
| 142 | clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16); | ||
| 156 | 143 | ||
| 157 | if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) | 144 | if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) |
| 158 | val |= KEY_INIT_DIS3KY; | 145 | val |= KEY_INIT_DIS3KY; |
| @@ -167,7 +154,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) | |||
| 167 | 154 | ||
| 168 | val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); | 155 | val |= ((pdata->prescale << KEY_INIT_PRSCL_SHIFT) & KEY_INIT_PRSCL_MASK); |
| 169 | 156 | ||
| 170 | keypad_writel(val, KEY_INIT); | 157 | __raw_writel(val, keypad->mmio_base + KEY_INIT); |
| 171 | } | 158 | } |
| 172 | 159 | ||
| 173 | static int ep93xx_keypad_open(struct input_dev *pdev) | 160 | static int ep93xx_keypad_open(struct input_dev *pdev) |
| @@ -177,7 +164,7 @@ static int ep93xx_keypad_open(struct input_dev *pdev) | |||
| 177 | if (!keypad->enabled) { | 164 | if (!keypad->enabled) { |
| 178 | ep93xx_keypad_config(keypad); | 165 | ep93xx_keypad_config(keypad); |
| 179 | clk_enable(keypad->clk); | 166 | clk_enable(keypad->clk); |
| 180 | keypad->enabled = 1; | 167 | keypad->enabled = true; |
| 181 | } | 168 | } |
| 182 | 169 | ||
| 183 | return 0; | 170 | return 0; |
| @@ -189,7 +176,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev) | |||
| 189 | 176 | ||
| 190 | if (keypad->enabled) { | 177 | if (keypad->enabled) { |
| 191 | clk_disable(keypad->clk); | 178 | clk_disable(keypad->clk); |
| 192 | keypad->enabled = 0; | 179 | keypad->enabled = false; |
| 193 | } | 180 | } |
| 194 | } | 181 | } |
| 195 | 182 | ||
| @@ -211,7 +198,7 @@ static int ep93xx_keypad_suspend(struct platform_device *pdev, | |||
| 211 | 198 | ||
| 212 | if (keypad->enabled) { | 199 | if (keypad->enabled) { |
| 213 | clk_disable(keypad->clk); | 200 | clk_disable(keypad->clk); |
| 214 | keypad->enabled = 0; | 201 | keypad->enabled = false; |
| 215 | } | 202 | } |
| 216 | 203 | ||
| 217 | mutex_unlock(&input_dev->mutex); | 204 | mutex_unlock(&input_dev->mutex); |
| @@ -236,7 +223,7 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) | |||
| 236 | if (!keypad->enabled) { | 223 | if (!keypad->enabled) { |
| 237 | ep93xx_keypad_config(keypad); | 224 | ep93xx_keypad_config(keypad); |
| 238 | clk_enable(keypad->clk); | 225 | clk_enable(keypad->clk); |
| 239 | keypad->enabled = 1; | 226 | keypad->enabled = true; |
| 240 | } | 227 | } |
| 241 | } | 228 | } |
| 242 | 229 | ||
| @@ -252,88 +239,63 @@ static int ep93xx_keypad_resume(struct platform_device *pdev) | |||
| 252 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | 239 | static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) |
| 253 | { | 240 | { |
| 254 | struct ep93xx_keypad *keypad; | 241 | struct ep93xx_keypad *keypad; |
| 255 | struct ep93xx_keypad_platform_data *pdata = pdev->dev.platform_data; | 242 | const struct matrix_keymap_data *keymap_data; |
| 256 | struct input_dev *input_dev; | 243 | struct input_dev *input_dev; |
| 257 | struct resource *res; | 244 | struct resource *res; |
| 258 | int irq, err, i, gpio; | 245 | int err; |
| 259 | |||
| 260 | if (!pdata || | ||
| 261 | !pdata->matrix_key_rows || | ||
| 262 | pdata->matrix_key_rows > MAX_MATRIX_KEY_ROWS || | ||
| 263 | !pdata->matrix_key_cols || | ||
| 264 | pdata->matrix_key_cols > MAX_MATRIX_KEY_COLS) { | ||
| 265 | dev_err(&pdev->dev, "invalid or missing platform data\n"); | ||
| 266 | return -EINVAL; | ||
| 267 | } | ||
| 268 | 246 | ||
| 269 | keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); | 247 | keypad = kzalloc(sizeof(struct ep93xx_keypad), GFP_KERNEL); |
| 270 | if (!keypad) { | 248 | if (!keypad) |
| 271 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 272 | return -ENOMEM; | 249 | return -ENOMEM; |
| 250 | |||
| 251 | keypad->pdata = pdev->dev.platform_data; | ||
| 252 | if (!keypad->pdata) { | ||
| 253 | err = -EINVAL; | ||
| 254 | goto failed_free; | ||
| 273 | } | 255 | } |
| 274 | 256 | ||
| 275 | keypad->pdata = pdata; | 257 | keymap_data = keypad->pdata->keymap_data; |
| 258 | if (!keymap_data) { | ||
| 259 | err = -EINVAL; | ||
| 260 | goto failed_free; | ||
| 261 | } | ||
| 276 | 262 | ||
| 277 | irq = platform_get_irq(pdev, 0); | 263 | keypad->irq = platform_get_irq(pdev, 0); |
| 278 | if (irq < 0) { | 264 | if (!keypad->irq) { |
| 279 | dev_err(&pdev->dev, "failed to get keypad irq\n"); | ||
| 280 | err = -ENXIO; | 265 | err = -ENXIO; |
| 281 | goto failed_free; | 266 | goto failed_free; |
| 282 | } | 267 | } |
| 283 | 268 | ||
| 284 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 269 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 285 | if (!res) { | 270 | if (!res) { |
| 286 | dev_err(&pdev->dev, "failed to get I/O memory\n"); | ||
| 287 | err = -ENXIO; | 271 | err = -ENXIO; |
| 288 | goto failed_free; | 272 | goto failed_free; |
| 289 | } | 273 | } |
| 290 | 274 | ||
| 291 | res = request_mem_region(res->start, resource_size(res), pdev->name); | 275 | res = request_mem_region(res->start, resource_size(res), pdev->name); |
| 292 | if (!res) { | 276 | if (!res) { |
| 293 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
| 294 | err = -EBUSY; | 277 | err = -EBUSY; |
| 295 | goto failed_free; | 278 | goto failed_free; |
| 296 | } | 279 | } |
| 297 | 280 | ||
| 298 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | 281 | keypad->mmio_base = ioremap(res->start, resource_size(res)); |
| 299 | if (keypad->mmio_base == NULL) { | 282 | if (keypad->mmio_base == NULL) { |
| 300 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
| 301 | err = -ENXIO; | 283 | err = -ENXIO; |
| 302 | goto failed_free_mem; | 284 | goto failed_free_mem; |
| 303 | } | 285 | } |
| 304 | 286 | ||
| 305 | /* Request the needed GPIO's */ | 287 | err = ep93xx_keypad_acquire_gpio(pdev); |
| 306 | gpio = EP93XX_GPIO_LINE_ROW0; | 288 | if (err) |
| 307 | for (i = 0; i < keypad->pdata->matrix_key_rows; i++, gpio++) { | 289 | goto failed_free_io; |
| 308 | err = gpio_request(gpio, pdev->name); | ||
| 309 | if (err) { | ||
| 310 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
| 311 | gpio); | ||
| 312 | goto failed_free_rows; | ||
| 313 | } | ||
| 314 | } | ||
| 315 | |||
| 316 | gpio = EP93XX_GPIO_LINE_COL0; | ||
| 317 | for (i = 0; i < keypad->pdata->matrix_key_cols; i++, gpio++) { | ||
| 318 | err = gpio_request(gpio, pdev->name); | ||
| 319 | if (err) { | ||
| 320 | dev_err(&pdev->dev, "failed to request gpio-%d\n", | ||
| 321 | gpio); | ||
| 322 | goto failed_free_cols; | ||
| 323 | } | ||
| 324 | } | ||
| 325 | 290 | ||
| 326 | keypad->clk = clk_get(&pdev->dev, "key_clk"); | 291 | keypad->clk = clk_get(&pdev->dev, NULL); |
| 327 | if (IS_ERR(keypad->clk)) { | 292 | if (IS_ERR(keypad->clk)) { |
| 328 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
| 329 | err = PTR_ERR(keypad->clk); | 293 | err = PTR_ERR(keypad->clk); |
| 330 | goto failed_free_io; | 294 | goto failed_free_gpio; |
| 331 | } | 295 | } |
| 332 | 296 | ||
| 333 | /* Create and register the input driver */ | ||
| 334 | input_dev = input_allocate_device(); | 297 | input_dev = input_allocate_device(); |
| 335 | if (!input_dev) { | 298 | if (!input_dev) { |
| 336 | dev_err(&pdev->dev, "failed to allocate input device\n"); | ||
| 337 | err = -ENOMEM; | 299 | err = -ENOMEM; |
| 338 | goto failed_put_clk; | 300 | goto failed_put_clk; |
| 339 | } | 301 | } |
| @@ -345,9 +307,9 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
| 345 | input_dev->open = ep93xx_keypad_open; | 307 | input_dev->open = ep93xx_keypad_open; |
| 346 | input_dev->close = ep93xx_keypad_close; | 308 | input_dev->close = ep93xx_keypad_close; |
| 347 | input_dev->dev.parent = &pdev->dev; | 309 | input_dev->dev.parent = &pdev->dev; |
| 348 | input_dev->keycode = keypad->matrix_keycodes; | 310 | input_dev->keycode = keypad->keycodes; |
| 349 | input_dev->keycodesize = sizeof(keypad->matrix_keycodes[0]); | 311 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); |
| 350 | input_dev->keycodemax = ARRAY_SIZE(keypad->matrix_keycodes); | 312 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); |
| 351 | 313 | ||
| 352 | input_set_drvdata(input_dev, keypad); | 314 | input_set_drvdata(input_dev, keypad); |
| 353 | 315 | ||
| @@ -355,47 +317,33 @@ static int __devinit ep93xx_keypad_probe(struct platform_device *pdev) | |||
| 355 | if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) | 317 | if (keypad->pdata->flags & EP93XX_KEYPAD_AUTOREPEAT) |
| 356 | input_dev->evbit[0] |= BIT_MASK(EV_REP); | 318 | input_dev->evbit[0] |= BIT_MASK(EV_REP); |
| 357 | 319 | ||
| 358 | ep93xx_keypad_build_keycode(keypad); | 320 | matrix_keypad_build_keymap(keymap_data, 3, |
| 321 | input_dev->keycode, input_dev->keybit); | ||
| 359 | platform_set_drvdata(pdev, keypad); | 322 | platform_set_drvdata(pdev, keypad); |
| 360 | 323 | ||
| 361 | err = request_irq(irq, ep93xx_keypad_irq_handler, IRQF_DISABLED, | 324 | err = request_irq(keypad->irq, ep93xx_keypad_irq_handler, |
| 362 | pdev->name, keypad); | 325 | IRQF_DISABLED, pdev->name, keypad); |
| 363 | if (err) { | 326 | if (err) |
| 364 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 365 | goto failed_free_dev; | 327 | goto failed_free_dev; |
| 366 | } | ||
| 367 | 328 | ||
| 368 | keypad->irq = irq; | ||
| 369 | |||
| 370 | /* Register the input device */ | ||
| 371 | err = input_register_device(input_dev); | 329 | err = input_register_device(input_dev); |
| 372 | if (err) { | 330 | if (err) |
| 373 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
| 374 | goto failed_free_irq; | 331 | goto failed_free_irq; |
| 375 | } | ||
| 376 | 332 | ||
| 377 | device_init_wakeup(&pdev->dev, 1); | 333 | device_init_wakeup(&pdev->dev, 1); |
| 378 | 334 | ||
| 379 | return 0; | 335 | return 0; |
| 380 | 336 | ||
| 381 | failed_free_irq: | 337 | failed_free_irq: |
| 382 | free_irq(irq, pdev); | 338 | free_irq(keypad->irq, pdev); |
| 383 | platform_set_drvdata(pdev, NULL); | 339 | platform_set_drvdata(pdev, NULL); |
| 384 | failed_free_dev: | 340 | failed_free_dev: |
| 385 | input_free_device(input_dev); | 341 | input_free_device(input_dev); |
| 386 | failed_put_clk: | 342 | failed_put_clk: |
| 387 | clk_put(keypad->clk); | 343 | clk_put(keypad->clk); |
| 344 | failed_free_gpio: | ||
| 345 | ep93xx_keypad_release_gpio(pdev); | ||
| 388 | failed_free_io: | 346 | failed_free_io: |
| 389 | i = keypad->pdata->matrix_key_cols - 1; | ||
| 390 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
| 391 | failed_free_cols: | ||
| 392 | for ( ; i >= 0; i--, gpio--) | ||
| 393 | gpio_free(gpio); | ||
| 394 | i = keypad->pdata->matrix_key_rows - 1; | ||
| 395 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
| 396 | failed_free_rows: | ||
| 397 | for ( ; i >= 0; i--, gpio--) | ||
| 398 | gpio_free(gpio); | ||
| 399 | iounmap(keypad->mmio_base); | 347 | iounmap(keypad->mmio_base); |
| 400 | failed_free_mem: | 348 | failed_free_mem: |
| 401 | release_mem_region(res->start, resource_size(res)); | 349 | release_mem_region(res->start, resource_size(res)); |
| @@ -408,7 +356,6 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) | |||
| 408 | { | 356 | { |
| 409 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); | 357 | struct ep93xx_keypad *keypad = platform_get_drvdata(pdev); |
| 410 | struct resource *res; | 358 | struct resource *res; |
| 411 | int i, gpio; | ||
| 412 | 359 | ||
| 413 | free_irq(keypad->irq, pdev); | 360 | free_irq(keypad->irq, pdev); |
| 414 | 361 | ||
| @@ -420,15 +367,7 @@ static int __devexit ep93xx_keypad_remove(struct platform_device *pdev) | |||
| 420 | 367 | ||
| 421 | input_unregister_device(keypad->input_dev); | 368 | input_unregister_device(keypad->input_dev); |
| 422 | 369 | ||
| 423 | i = keypad->pdata->matrix_key_cols - 1; | 370 | ep93xx_keypad_release_gpio(pdev); |
| 424 | gpio = EP93XX_GPIO_LINE_COL0 + i; | ||
| 425 | for ( ; i >= 0; i--, gpio--) | ||
| 426 | gpio_free(gpio); | ||
| 427 | |||
| 428 | i = keypad->pdata->matrix_key_rows - 1; | ||
| 429 | gpio = EP93XX_GPIO_LINE_ROW0 + i; | ||
| 430 | for ( ; i >= 0; i--, gpio--) | ||
| 431 | gpio_free(gpio); | ||
| 432 | 371 | ||
| 433 | iounmap(keypad->mmio_base); | 372 | iounmap(keypad->mmio_base); |
| 434 | 373 | ||
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 77d130914259..b8213fd13c3f 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/irq.h> | 16 | #include <linux/irq.h> |
| 17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
| 18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
| 19 | #include <linux/slab.h> | ||
| 19 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
| 20 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 21 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| @@ -23,25 +24,298 @@ | |||
| 23 | #include <linux/input.h> | 24 | #include <linux/input.h> |
| 24 | #include <linux/gpio_keys.h> | 25 | #include <linux/gpio_keys.h> |
| 25 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
| 26 | 27 | #include <linux/gpio.h> | |
| 27 | #include <asm/gpio.h> | ||
| 28 | 28 | ||
| 29 | struct gpio_button_data { | 29 | struct gpio_button_data { |
| 30 | struct gpio_keys_button *button; | 30 | struct gpio_keys_button *button; |
| 31 | struct input_dev *input; | 31 | struct input_dev *input; |
| 32 | struct timer_list timer; | 32 | struct timer_list timer; |
| 33 | struct work_struct work; | 33 | struct work_struct work; |
| 34 | bool disabled; | ||
| 34 | }; | 35 | }; |
| 35 | 36 | ||
| 36 | struct gpio_keys_drvdata { | 37 | struct gpio_keys_drvdata { |
| 37 | struct input_dev *input; | 38 | struct input_dev *input; |
| 39 | struct mutex disable_lock; | ||
| 40 | unsigned int n_buttons; | ||
| 38 | struct gpio_button_data data[0]; | 41 | struct gpio_button_data data[0]; |
| 39 | }; | 42 | }; |
| 40 | 43 | ||
| 41 | static void gpio_keys_report_event(struct work_struct *work) | 44 | /* |
| 45 | * SYSFS interface for enabling/disabling keys and switches: | ||
| 46 | * | ||
| 47 | * There are 4 attributes under /sys/devices/platform/gpio-keys/ | ||
| 48 | * keys [ro] - bitmap of keys (EV_KEY) which can be | ||
| 49 | * disabled | ||
| 50 | * switches [ro] - bitmap of switches (EV_SW) which can be | ||
| 51 | * disabled | ||
| 52 | * disabled_keys [rw] - bitmap of keys currently disabled | ||
| 53 | * disabled_switches [rw] - bitmap of switches currently disabled | ||
| 54 | * | ||
| 55 | * Userland can change these values and hence disable event generation | ||
| 56 | * for each key (or switch). Disabling a key means its interrupt line | ||
| 57 | * is disabled. | ||
| 58 | * | ||
| 59 | * For example, if we have following switches set up as gpio-keys: | ||
| 60 | * SW_DOCK = 5 | ||
| 61 | * SW_CAMERA_LENS_COVER = 9 | ||
| 62 | * SW_KEYPAD_SLIDE = 10 | ||
| 63 | * SW_FRONT_PROXIMITY = 11 | ||
| 64 | * This is read from switches: | ||
| 65 | * 11-9,5 | ||
| 66 | * Next we want to disable proximity (11) and dock (5), we write: | ||
| 67 | * 11,5 | ||
| 68 | * to file disabled_switches. Now proximity and dock IRQs are disabled. | ||
| 69 | * This can be verified by reading the file disabled_switches: | ||
| 70 | * 11,5 | ||
| 71 | * If we now want to enable proximity (11) switch we write: | ||
| 72 | * 5 | ||
| 73 | * to disabled_switches. | ||
| 74 | * | ||
| 75 | * We can disable only those keys which don't allow sharing the irq. | ||
| 76 | */ | ||
| 77 | |||
| 78 | /** | ||
| 79 | * get_n_events_by_type() - returns maximum number of events per @type | ||
| 80 | * @type: type of button (%EV_KEY, %EV_SW) | ||
| 81 | * | ||
| 82 | * Return value of this function can be used to allocate bitmap | ||
| 83 | * large enough to hold all bits for given type. | ||
| 84 | */ | ||
| 85 | static inline int get_n_events_by_type(int type) | ||
| 86 | { | ||
| 87 | BUG_ON(type != EV_SW && type != EV_KEY); | ||
| 88 | |||
| 89 | return (type == EV_KEY) ? KEY_CNT : SW_CNT; | ||
| 90 | } | ||
| 91 | |||
| 92 | /** | ||
| 93 | * gpio_keys_disable_button() - disables given GPIO button | ||
| 94 | * @bdata: button data for button to be disabled | ||
| 95 | * | ||
| 96 | * Disables button pointed by @bdata. This is done by masking | ||
| 97 | * IRQ line. After this function is called, button won't generate | ||
| 98 | * input events anymore. Note that one can only disable buttons | ||
| 99 | * that don't share IRQs. | ||
| 100 | * | ||
| 101 | * Make sure that @bdata->disable_lock is locked when entering | ||
| 102 | * this function to avoid races when concurrent threads are | ||
| 103 | * disabling buttons at the same time. | ||
| 104 | */ | ||
| 105 | static void gpio_keys_disable_button(struct gpio_button_data *bdata) | ||
| 106 | { | ||
| 107 | if (!bdata->disabled) { | ||
| 108 | /* | ||
| 109 | * Disable IRQ and possible debouncing timer. | ||
| 110 | */ | ||
| 111 | disable_irq(gpio_to_irq(bdata->button->gpio)); | ||
| 112 | if (bdata->button->debounce_interval) | ||
| 113 | del_timer_sync(&bdata->timer); | ||
| 114 | |||
| 115 | bdata->disabled = true; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | /** | ||
| 120 | * gpio_keys_enable_button() - enables given GPIO button | ||
| 121 | * @bdata: button data for button to be disabled | ||
| 122 | * | ||
| 123 | * Enables given button pointed by @bdata. | ||
| 124 | * | ||
| 125 | * Make sure that @bdata->disable_lock is locked when entering | ||
| 126 | * this function to avoid races with concurrent threads trying | ||
| 127 | * to enable the same button at the same time. | ||
| 128 | */ | ||
| 129 | static void gpio_keys_enable_button(struct gpio_button_data *bdata) | ||
| 130 | { | ||
| 131 | if (bdata->disabled) { | ||
| 132 | enable_irq(gpio_to_irq(bdata->button->gpio)); | ||
| 133 | bdata->disabled = false; | ||
| 134 | } | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * gpio_keys_attr_show_helper() - fill in stringified bitmap of buttons | ||
| 139 | * @ddata: pointer to drvdata | ||
| 140 | * @buf: buffer where stringified bitmap is written | ||
| 141 | * @type: button type (%EV_KEY, %EV_SW) | ||
| 142 | * @only_disabled: does caller want only those buttons that are | ||
| 143 | * currently disabled or all buttons that can be | ||
| 144 | * disabled | ||
| 145 | * | ||
| 146 | * This function writes buttons that can be disabled to @buf. If | ||
| 147 | * @only_disabled is true, then @buf contains only those buttons | ||
| 148 | * that are currently disabled. Returns 0 on success or negative | ||
| 149 | * errno on failure. | ||
| 150 | */ | ||
| 151 | static ssize_t gpio_keys_attr_show_helper(struct gpio_keys_drvdata *ddata, | ||
| 152 | char *buf, unsigned int type, | ||
| 153 | bool only_disabled) | ||
| 154 | { | ||
| 155 | int n_events = get_n_events_by_type(type); | ||
| 156 | unsigned long *bits; | ||
| 157 | ssize_t ret; | ||
| 158 | int i; | ||
| 159 | |||
| 160 | bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); | ||
| 161 | if (!bits) | ||
| 162 | return -ENOMEM; | ||
| 163 | |||
| 164 | for (i = 0; i < ddata->n_buttons; i++) { | ||
| 165 | struct gpio_button_data *bdata = &ddata->data[i]; | ||
| 166 | |||
| 167 | if (bdata->button->type != type) | ||
| 168 | continue; | ||
| 169 | |||
| 170 | if (only_disabled && !bdata->disabled) | ||
| 171 | continue; | ||
| 172 | |||
| 173 | __set_bit(bdata->button->code, bits); | ||
| 174 | } | ||
| 175 | |||
| 176 | ret = bitmap_scnlistprintf(buf, PAGE_SIZE - 2, bits, n_events); | ||
| 177 | buf[ret++] = '\n'; | ||
| 178 | buf[ret] = '\0'; | ||
| 179 | |||
| 180 | kfree(bits); | ||
| 181 | |||
| 182 | return ret; | ||
| 183 | } | ||
| 184 | |||
| 185 | /** | ||
| 186 | * gpio_keys_attr_store_helper() - enable/disable buttons based on given bitmap | ||
| 187 | * @ddata: pointer to drvdata | ||
| 188 | * @buf: buffer from userspace that contains stringified bitmap | ||
| 189 | * @type: button type (%EV_KEY, %EV_SW) | ||
| 190 | * | ||
| 191 | * This function parses stringified bitmap from @buf and disables/enables | ||
| 192 | * GPIO buttons accordinly. Returns 0 on success and negative error | ||
| 193 | * on failure. | ||
| 194 | */ | ||
| 195 | static ssize_t gpio_keys_attr_store_helper(struct gpio_keys_drvdata *ddata, | ||
| 196 | const char *buf, unsigned int type) | ||
| 197 | { | ||
| 198 | int n_events = get_n_events_by_type(type); | ||
| 199 | unsigned long *bits; | ||
| 200 | ssize_t error; | ||
| 201 | int i; | ||
| 202 | |||
| 203 | bits = kcalloc(BITS_TO_LONGS(n_events), sizeof(*bits), GFP_KERNEL); | ||
| 204 | if (!bits) | ||
| 205 | return -ENOMEM; | ||
| 206 | |||
| 207 | error = bitmap_parselist(buf, bits, n_events); | ||
| 208 | if (error) | ||
| 209 | goto out; | ||
| 210 | |||
| 211 | /* First validate */ | ||
| 212 | for (i = 0; i < ddata->n_buttons; i++) { | ||
| 213 | struct gpio_button_data *bdata = &ddata->data[i]; | ||
| 214 | |||
| 215 | if (bdata->button->type != type) | ||
| 216 | continue; | ||
| 217 | |||
| 218 | if (test_bit(bdata->button->code, bits) && | ||
| 219 | !bdata->button->can_disable) { | ||
| 220 | error = -EINVAL; | ||
| 221 | goto out; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | mutex_lock(&ddata->disable_lock); | ||
| 226 | |||
| 227 | for (i = 0; i < ddata->n_buttons; i++) { | ||
| 228 | struct gpio_button_data *bdata = &ddata->data[i]; | ||
| 229 | |||
| 230 | if (bdata->button->type != type) | ||
| 231 | continue; | ||
| 232 | |||
| 233 | if (test_bit(bdata->button->code, bits)) | ||
| 234 | gpio_keys_disable_button(bdata); | ||
| 235 | else | ||
| 236 | gpio_keys_enable_button(bdata); | ||
| 237 | } | ||
| 238 | |||
| 239 | mutex_unlock(&ddata->disable_lock); | ||
| 240 | |||
| 241 | out: | ||
| 242 | kfree(bits); | ||
| 243 | return error; | ||
| 244 | } | ||
| 245 | |||
| 246 | #define ATTR_SHOW_FN(name, type, only_disabled) \ | ||
| 247 | static ssize_t gpio_keys_show_##name(struct device *dev, \ | ||
| 248 | struct device_attribute *attr, \ | ||
| 249 | char *buf) \ | ||
| 250 | { \ | ||
| 251 | struct platform_device *pdev = to_platform_device(dev); \ | ||
| 252 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ | ||
| 253 | \ | ||
| 254 | return gpio_keys_attr_show_helper(ddata, buf, \ | ||
| 255 | type, only_disabled); \ | ||
| 256 | } | ||
| 257 | |||
| 258 | ATTR_SHOW_FN(keys, EV_KEY, false); | ||
| 259 | ATTR_SHOW_FN(switches, EV_SW, false); | ||
| 260 | ATTR_SHOW_FN(disabled_keys, EV_KEY, true); | ||
| 261 | ATTR_SHOW_FN(disabled_switches, EV_SW, true); | ||
| 262 | |||
| 263 | /* | ||
| 264 | * ATTRIBUTES: | ||
| 265 | * | ||
| 266 | * /sys/devices/platform/gpio-keys/keys [ro] | ||
| 267 | * /sys/devices/platform/gpio-keys/switches [ro] | ||
| 268 | */ | ||
| 269 | static DEVICE_ATTR(keys, S_IRUGO, gpio_keys_show_keys, NULL); | ||
| 270 | static DEVICE_ATTR(switches, S_IRUGO, gpio_keys_show_switches, NULL); | ||
| 271 | |||
| 272 | #define ATTR_STORE_FN(name, type) \ | ||
| 273 | static ssize_t gpio_keys_store_##name(struct device *dev, \ | ||
| 274 | struct device_attribute *attr, \ | ||
| 275 | const char *buf, \ | ||
| 276 | size_t count) \ | ||
| 277 | { \ | ||
| 278 | struct platform_device *pdev = to_platform_device(dev); \ | ||
| 279 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); \ | ||
| 280 | ssize_t error; \ | ||
| 281 | \ | ||
| 282 | error = gpio_keys_attr_store_helper(ddata, buf, type); \ | ||
| 283 | if (error) \ | ||
| 284 | return error; \ | ||
| 285 | \ | ||
| 286 | return count; \ | ||
| 287 | } | ||
| 288 | |||
| 289 | ATTR_STORE_FN(disabled_keys, EV_KEY); | ||
| 290 | ATTR_STORE_FN(disabled_switches, EV_SW); | ||
| 291 | |||
| 292 | /* | ||
| 293 | * ATTRIBUTES: | ||
| 294 | * | ||
| 295 | * /sys/devices/platform/gpio-keys/disabled_keys [rw] | ||
| 296 | * /sys/devices/platform/gpio-keys/disables_switches [rw] | ||
| 297 | */ | ||
| 298 | static DEVICE_ATTR(disabled_keys, S_IWUSR | S_IRUGO, | ||
| 299 | gpio_keys_show_disabled_keys, | ||
| 300 | gpio_keys_store_disabled_keys); | ||
| 301 | static DEVICE_ATTR(disabled_switches, S_IWUSR | S_IRUGO, | ||
| 302 | gpio_keys_show_disabled_switches, | ||
| 303 | gpio_keys_store_disabled_switches); | ||
| 304 | |||
| 305 | static struct attribute *gpio_keys_attrs[] = { | ||
| 306 | &dev_attr_keys.attr, | ||
| 307 | &dev_attr_switches.attr, | ||
| 308 | &dev_attr_disabled_keys.attr, | ||
| 309 | &dev_attr_disabled_switches.attr, | ||
| 310 | NULL, | ||
| 311 | }; | ||
| 312 | |||
| 313 | static struct attribute_group gpio_keys_attr_group = { | ||
| 314 | .attrs = gpio_keys_attrs, | ||
| 315 | }; | ||
| 316 | |||
| 317 | static void gpio_keys_report_event(struct gpio_button_data *bdata) | ||
| 42 | { | 318 | { |
| 43 | struct gpio_button_data *bdata = | ||
| 44 | container_of(work, struct gpio_button_data, work); | ||
| 45 | struct gpio_keys_button *button = bdata->button; | 319 | struct gpio_keys_button *button = bdata->button; |
| 46 | struct input_dev *input = bdata->input; | 320 | struct input_dev *input = bdata->input; |
| 47 | unsigned int type = button->type ?: EV_KEY; | 321 | unsigned int type = button->type ?: EV_KEY; |
| @@ -51,6 +325,14 @@ static void gpio_keys_report_event(struct work_struct *work) | |||
| 51 | input_sync(input); | 325 | input_sync(input); |
| 52 | } | 326 | } |
| 53 | 327 | ||
| 328 | static void gpio_keys_work_func(struct work_struct *work) | ||
| 329 | { | ||
| 330 | struct gpio_button_data *bdata = | ||
| 331 | container_of(work, struct gpio_button_data, work); | ||
| 332 | |||
| 333 | gpio_keys_report_event(bdata); | ||
| 334 | } | ||
| 335 | |||
| 54 | static void gpio_keys_timer(unsigned long _data) | 336 | static void gpio_keys_timer(unsigned long _data) |
| 55 | { | 337 | { |
| 56 | struct gpio_button_data *data = (struct gpio_button_data *)_data; | 338 | struct gpio_button_data *data = (struct gpio_button_data *)_data; |
| @@ -74,10 +356,69 @@ static irqreturn_t gpio_keys_isr(int irq, void *dev_id) | |||
| 74 | return IRQ_HANDLED; | 356 | return IRQ_HANDLED; |
| 75 | } | 357 | } |
| 76 | 358 | ||
| 359 | static int __devinit gpio_keys_setup_key(struct platform_device *pdev, | ||
| 360 | struct gpio_button_data *bdata, | ||
| 361 | struct gpio_keys_button *button) | ||
| 362 | { | ||
| 363 | char *desc = button->desc ? button->desc : "gpio_keys"; | ||
| 364 | struct device *dev = &pdev->dev; | ||
| 365 | unsigned long irqflags; | ||
| 366 | int irq, error; | ||
| 367 | |||
| 368 | setup_timer(&bdata->timer, gpio_keys_timer, (unsigned long)bdata); | ||
| 369 | INIT_WORK(&bdata->work, gpio_keys_work_func); | ||
| 370 | |||
| 371 | error = gpio_request(button->gpio, desc); | ||
| 372 | if (error < 0) { | ||
| 373 | dev_err(dev, "failed to request GPIO %d, error %d\n", | ||
| 374 | button->gpio, error); | ||
| 375 | goto fail2; | ||
| 376 | } | ||
| 377 | |||
| 378 | error = gpio_direction_input(button->gpio); | ||
| 379 | if (error < 0) { | ||
| 380 | dev_err(dev, "failed to configure" | ||
| 381 | " direction for GPIO %d, error %d\n", | ||
| 382 | button->gpio, error); | ||
| 383 | goto fail3; | ||
| 384 | } | ||
| 385 | |||
| 386 | irq = gpio_to_irq(button->gpio); | ||
| 387 | if (irq < 0) { | ||
| 388 | error = irq; | ||
| 389 | dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", | ||
| 390 | button->gpio, error); | ||
| 391 | goto fail3; | ||
| 392 | } | ||
| 393 | |||
| 394 | irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; | ||
| 395 | /* | ||
| 396 | * If platform has specified that the button can be disabled, | ||
| 397 | * we don't want it to share the interrupt line. | ||
| 398 | */ | ||
| 399 | if (!button->can_disable) | ||
| 400 | irqflags |= IRQF_SHARED; | ||
| 401 | |||
| 402 | error = request_irq(irq, gpio_keys_isr, irqflags, desc, bdata); | ||
| 403 | if (error) { | ||
| 404 | dev_err(dev, "Unable to claim irq %d; error %d\n", | ||
| 405 | irq, error); | ||
| 406 | goto fail3; | ||
| 407 | } | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | |||
| 411 | fail3: | ||
| 412 | gpio_free(button->gpio); | ||
| 413 | fail2: | ||
| 414 | return error; | ||
| 415 | } | ||
| 416 | |||
| 77 | static int __devinit gpio_keys_probe(struct platform_device *pdev) | 417 | static int __devinit gpio_keys_probe(struct platform_device *pdev) |
| 78 | { | 418 | { |
| 79 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 419 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
| 80 | struct gpio_keys_drvdata *ddata; | 420 | struct gpio_keys_drvdata *ddata; |
| 421 | struct device *dev = &pdev->dev; | ||
| 81 | struct input_dev *input; | 422 | struct input_dev *input; |
| 82 | int i, error; | 423 | int i, error; |
| 83 | int wakeup = 0; | 424 | int wakeup = 0; |
| @@ -87,10 +428,15 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 87 | GFP_KERNEL); | 428 | GFP_KERNEL); |
| 88 | input = input_allocate_device(); | 429 | input = input_allocate_device(); |
| 89 | if (!ddata || !input) { | 430 | if (!ddata || !input) { |
| 431 | dev_err(dev, "failed to allocate state\n"); | ||
| 90 | error = -ENOMEM; | 432 | error = -ENOMEM; |
| 91 | goto fail1; | 433 | goto fail1; |
| 92 | } | 434 | } |
| 93 | 435 | ||
| 436 | ddata->input = input; | ||
| 437 | ddata->n_buttons = pdata->nbuttons; | ||
| 438 | mutex_init(&ddata->disable_lock); | ||
| 439 | |||
| 94 | platform_set_drvdata(pdev, ddata); | 440 | platform_set_drvdata(pdev, ddata); |
| 95 | 441 | ||
| 96 | input->name = pdev->name; | 442 | input->name = pdev->name; |
| @@ -106,57 +452,17 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 106 | if (pdata->rep) | 452 | if (pdata->rep) |
| 107 | __set_bit(EV_REP, input->evbit); | 453 | __set_bit(EV_REP, input->evbit); |
| 108 | 454 | ||
| 109 | ddata->input = input; | ||
| 110 | |||
| 111 | for (i = 0; i < pdata->nbuttons; i++) { | 455 | for (i = 0; i < pdata->nbuttons; i++) { |
| 112 | struct gpio_keys_button *button = &pdata->buttons[i]; | 456 | struct gpio_keys_button *button = &pdata->buttons[i]; |
| 113 | struct gpio_button_data *bdata = &ddata->data[i]; | 457 | struct gpio_button_data *bdata = &ddata->data[i]; |
| 114 | int irq; | ||
| 115 | unsigned int type = button->type ?: EV_KEY; | 458 | unsigned int type = button->type ?: EV_KEY; |
| 116 | 459 | ||
| 117 | bdata->input = input; | 460 | bdata->input = input; |
| 118 | bdata->button = button; | 461 | bdata->button = button; |
| 119 | setup_timer(&bdata->timer, | ||
| 120 | gpio_keys_timer, (unsigned long)bdata); | ||
| 121 | INIT_WORK(&bdata->work, gpio_keys_report_event); | ||
| 122 | |||
| 123 | error = gpio_request(button->gpio, button->desc ?: "gpio_keys"); | ||
| 124 | if (error < 0) { | ||
| 125 | pr_err("gpio-keys: failed to request GPIO %d," | ||
| 126 | " error %d\n", button->gpio, error); | ||
| 127 | goto fail2; | ||
| 128 | } | ||
| 129 | 462 | ||
| 130 | error = gpio_direction_input(button->gpio); | 463 | error = gpio_keys_setup_key(pdev, bdata, button); |
| 131 | if (error < 0) { | 464 | if (error) |
| 132 | pr_err("gpio-keys: failed to configure input" | ||
| 133 | " direction for GPIO %d, error %d\n", | ||
| 134 | button->gpio, error); | ||
| 135 | gpio_free(button->gpio); | ||
| 136 | goto fail2; | 465 | goto fail2; |
| 137 | } | ||
| 138 | |||
| 139 | irq = gpio_to_irq(button->gpio); | ||
| 140 | if (irq < 0) { | ||
| 141 | error = irq; | ||
| 142 | pr_err("gpio-keys: Unable to get irq number" | ||
| 143 | " for GPIO %d, error %d\n", | ||
| 144 | button->gpio, error); | ||
| 145 | gpio_free(button->gpio); | ||
| 146 | goto fail2; | ||
| 147 | } | ||
| 148 | |||
| 149 | error = request_irq(irq, gpio_keys_isr, | ||
| 150 | IRQF_SHARED | | ||
| 151 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 152 | button->desc ? button->desc : "gpio_keys", | ||
| 153 | bdata); | ||
| 154 | if (error) { | ||
| 155 | pr_err("gpio-keys: Unable to claim irq %d; error %d\n", | ||
| 156 | irq, error); | ||
| 157 | gpio_free(button->gpio); | ||
| 158 | goto fail2; | ||
| 159 | } | ||
| 160 | 466 | ||
| 161 | if (button->wakeup) | 467 | if (button->wakeup) |
| 162 | wakeup = 1; | 468 | wakeup = 1; |
| @@ -164,17 +470,31 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) | |||
| 164 | input_set_capability(input, type, button->code); | 470 | input_set_capability(input, type, button->code); |
| 165 | } | 471 | } |
| 166 | 472 | ||
| 167 | error = input_register_device(input); | 473 | error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); |
| 168 | if (error) { | 474 | if (error) { |
| 169 | pr_err("gpio-keys: Unable to register input device, " | 475 | dev_err(dev, "Unable to export keys/switches, error: %d\n", |
| 170 | "error: %d\n", error); | 476 | error); |
| 171 | goto fail2; | 477 | goto fail2; |
| 172 | } | 478 | } |
| 173 | 479 | ||
| 480 | error = input_register_device(input); | ||
| 481 | if (error) { | ||
| 482 | dev_err(dev, "Unable to register input device, error: %d\n", | ||
| 483 | error); | ||
| 484 | goto fail3; | ||
| 485 | } | ||
| 486 | |||
| 487 | /* get current state of buttons */ | ||
| 488 | for (i = 0; i < pdata->nbuttons; i++) | ||
| 489 | gpio_keys_report_event(&ddata->data[i]); | ||
| 490 | input_sync(input); | ||
| 491 | |||
| 174 | device_init_wakeup(&pdev->dev, wakeup); | 492 | device_init_wakeup(&pdev->dev, wakeup); |
| 175 | 493 | ||
| 176 | return 0; | 494 | return 0; |
| 177 | 495 | ||
| 496 | fail3: | ||
| 497 | sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); | ||
| 178 | fail2: | 498 | fail2: |
| 179 | while (--i >= 0) { | 499 | while (--i >= 0) { |
| 180 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); | 500 | free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); |
| @@ -199,6 +519,8 @@ static int __devexit gpio_keys_remove(struct platform_device *pdev) | |||
| 199 | struct input_dev *input = ddata->input; | 519 | struct input_dev *input = ddata->input; |
| 200 | int i; | 520 | int i; |
| 201 | 521 | ||
| 522 | sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); | ||
| 523 | |||
| 202 | device_init_wakeup(&pdev->dev, 0); | 524 | device_init_wakeup(&pdev->dev, 0); |
| 203 | 525 | ||
| 204 | for (i = 0; i < pdata->nbuttons; i++) { | 526 | for (i = 0; i < pdata->nbuttons; i++) { |
| @@ -239,18 +561,21 @@ static int gpio_keys_suspend(struct device *dev) | |||
| 239 | static int gpio_keys_resume(struct device *dev) | 561 | static int gpio_keys_resume(struct device *dev) |
| 240 | { | 562 | { |
| 241 | struct platform_device *pdev = to_platform_device(dev); | 563 | struct platform_device *pdev = to_platform_device(dev); |
| 564 | struct gpio_keys_drvdata *ddata = platform_get_drvdata(pdev); | ||
| 242 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; | 565 | struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; |
| 243 | int i; | 566 | int i; |
| 244 | 567 | ||
| 245 | if (device_may_wakeup(&pdev->dev)) { | 568 | for (i = 0; i < pdata->nbuttons; i++) { |
| 246 | for (i = 0; i < pdata->nbuttons; i++) { | 569 | |
| 247 | struct gpio_keys_button *button = &pdata->buttons[i]; | 570 | struct gpio_keys_button *button = &pdata->buttons[i]; |
| 248 | if (button->wakeup) { | 571 | if (button->wakeup && device_may_wakeup(&pdev->dev)) { |
| 249 | int irq = gpio_to_irq(button->gpio); | 572 | int irq = gpio_to_irq(button->gpio); |
| 250 | disable_irq_wake(irq); | 573 | disable_irq_wake(irq); |
| 251 | } | ||
| 252 | } | 574 | } |
| 575 | |||
| 576 | gpio_keys_report_event(&ddata->data[i]); | ||
| 253 | } | 577 | } |
| 578 | input_sync(ddata->input); | ||
| 254 | 579 | ||
| 255 | return 0; | 580 | return 0; |
| 256 | } | 581 | } |
diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c new file mode 100644 index 000000000000..d92c15c39e68 --- /dev/null +++ b/drivers/input/keyboard/imx_keypad.c | |||
| @@ -0,0 +1,595 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the IMX keypad port. | ||
| 3 | * Copyright (C) 2009 Alberto Panizzo <maramaopercheseimorto@gmail.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * <<Power management needs to be implemented>>. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/clk.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/device.h> | ||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/input/matrix_keypad.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/jiffies.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/timer.h> | ||
| 26 | |||
| 27 | /* | ||
| 28 | * Keypad Controller registers (halfword) | ||
| 29 | */ | ||
| 30 | #define KPCR 0x00 /* Keypad Control Register */ | ||
| 31 | |||
| 32 | #define KPSR 0x02 /* Keypad Status Register */ | ||
| 33 | #define KBD_STAT_KPKD (0x1 << 0) /* Key Press Interrupt Status bit (w1c) */ | ||
| 34 | #define KBD_STAT_KPKR (0x1 << 1) /* Key Release Interrupt Status bit (w1c) */ | ||
| 35 | #define KBD_STAT_KDSC (0x1 << 2) /* Key Depress Synch Chain Status bit (w1c)*/ | ||
| 36 | #define KBD_STAT_KRSS (0x1 << 3) /* Key Release Synch Status bit (w1c)*/ | ||
| 37 | #define KBD_STAT_KDIE (0x1 << 8) /* Key Depress Interrupt Enable Status bit */ | ||
| 38 | #define KBD_STAT_KRIE (0x1 << 9) /* Key Release Interrupt Enable */ | ||
| 39 | #define KBD_STAT_KPPEN (0x1 << 10) /* Keypad Clock Enable */ | ||
| 40 | |||
| 41 | #define KDDR 0x04 /* Keypad Data Direction Register */ | ||
| 42 | #define KPDR 0x06 /* Keypad Data Register */ | ||
| 43 | |||
| 44 | #define MAX_MATRIX_KEY_ROWS 8 | ||
| 45 | #define MAX_MATRIX_KEY_COLS 8 | ||
| 46 | #define MATRIX_ROW_SHIFT 3 | ||
| 47 | |||
| 48 | #define MAX_MATRIX_KEY_NUM (MAX_MATRIX_KEY_ROWS * MAX_MATRIX_KEY_COLS) | ||
| 49 | |||
| 50 | struct imx_keypad { | ||
| 51 | |||
| 52 | struct clk *clk; | ||
| 53 | struct input_dev *input_dev; | ||
| 54 | void __iomem *mmio_base; | ||
| 55 | |||
| 56 | int irq; | ||
| 57 | struct timer_list check_matrix_timer; | ||
| 58 | |||
| 59 | /* | ||
| 60 | * The matrix is stable only if no changes are detected after | ||
| 61 | * IMX_KEYPAD_SCANS_FOR_STABILITY scans | ||
| 62 | */ | ||
| 63 | #define IMX_KEYPAD_SCANS_FOR_STABILITY 3 | ||
| 64 | int stable_count; | ||
| 65 | |||
| 66 | bool enabled; | ||
| 67 | |||
| 68 | /* Masks for enabled rows/cols */ | ||
| 69 | unsigned short rows_en_mask; | ||
| 70 | unsigned short cols_en_mask; | ||
| 71 | |||
| 72 | unsigned short keycodes[MAX_MATRIX_KEY_NUM]; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * Matrix states: | ||
| 76 | * -stable: achieved after a complete debounce process. | ||
| 77 | * -unstable: used in the debouncing process. | ||
| 78 | */ | ||
| 79 | unsigned short matrix_stable_state[MAX_MATRIX_KEY_COLS]; | ||
| 80 | unsigned short matrix_unstable_state[MAX_MATRIX_KEY_COLS]; | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* Scan the matrix and return the new state in *matrix_volatile_state. */ | ||
| 84 | static void imx_keypad_scan_matrix(struct imx_keypad *keypad, | ||
| 85 | unsigned short *matrix_volatile_state) | ||
| 86 | { | ||
| 87 | int col; | ||
| 88 | unsigned short reg_val; | ||
| 89 | |||
| 90 | for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) { | ||
| 91 | if ((keypad->cols_en_mask & (1 << col)) == 0) | ||
| 92 | continue; | ||
| 93 | /* | ||
| 94 | * Discharge keypad capacitance: | ||
| 95 | * 2. write 1s on column data. | ||
| 96 | * 3. configure columns as totem-pole to discharge capacitance. | ||
| 97 | * 4. configure columns as open-drain. | ||
| 98 | */ | ||
| 99 | reg_val = readw(keypad->mmio_base + KPDR); | ||
| 100 | reg_val |= 0xff00; | ||
| 101 | writew(reg_val, keypad->mmio_base + KPDR); | ||
| 102 | |||
| 103 | reg_val = readw(keypad->mmio_base + KPCR); | ||
| 104 | reg_val &= ~((keypad->cols_en_mask & 0xff) << 8); | ||
| 105 | writew(reg_val, keypad->mmio_base + KPCR); | ||
| 106 | |||
| 107 | udelay(2); | ||
| 108 | |||
| 109 | reg_val = readw(keypad->mmio_base + KPCR); | ||
| 110 | reg_val |= (keypad->cols_en_mask & 0xff) << 8; | ||
| 111 | writew(reg_val, keypad->mmio_base + KPCR); | ||
| 112 | |||
| 113 | /* | ||
| 114 | * 5. Write a single column to 0, others to 1. | ||
| 115 | * 6. Sample row inputs and save data. | ||
| 116 | * 7. Repeat steps 2 - 6 for remaining columns. | ||
| 117 | */ | ||
| 118 | reg_val = readw(keypad->mmio_base + KPDR); | ||
| 119 | reg_val &= ~(1 << (8 + col)); | ||
| 120 | writew(reg_val, keypad->mmio_base + KPDR); | ||
| 121 | |||
| 122 | /* | ||
| 123 | * Delay added to avoid propagating the 0 from column to row | ||
| 124 | * when scanning. | ||
| 125 | */ | ||
| 126 | udelay(5); | ||
| 127 | |||
| 128 | /* | ||
| 129 | * 1s in matrix_volatile_state[col] means key pressures | ||
| 130 | * throw data from non enabled rows. | ||
| 131 | */ | ||
| 132 | reg_val = readw(keypad->mmio_base + KPDR); | ||
| 133 | matrix_volatile_state[col] = (~reg_val) & keypad->rows_en_mask; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Return in standby mode: | ||
| 138 | * 9. write 0s to columns | ||
| 139 | */ | ||
| 140 | reg_val = readw(keypad->mmio_base + KPDR); | ||
| 141 | reg_val &= 0x00ff; | ||
| 142 | writew(reg_val, keypad->mmio_base + KPDR); | ||
| 143 | } | ||
| 144 | |||
| 145 | /* | ||
| 146 | * Compare the new matrix state (volatile) with the stable one stored in | ||
| 147 | * keypad->matrix_stable_state and fire events if changes are detected. | ||
| 148 | */ | ||
| 149 | static void imx_keypad_fire_events(struct imx_keypad *keypad, | ||
| 150 | unsigned short *matrix_volatile_state) | ||
| 151 | { | ||
| 152 | struct input_dev *input_dev = keypad->input_dev; | ||
| 153 | int row, col; | ||
| 154 | |||
| 155 | for (col = 0; col < MAX_MATRIX_KEY_COLS; col++) { | ||
| 156 | unsigned short bits_changed; | ||
| 157 | int code; | ||
| 158 | |||
| 159 | if ((keypad->cols_en_mask & (1 << col)) == 0) | ||
| 160 | continue; /* Column is not enabled */ | ||
| 161 | |||
| 162 | bits_changed = keypad->matrix_stable_state[col] ^ | ||
| 163 | matrix_volatile_state[col]; | ||
| 164 | |||
| 165 | if (bits_changed == 0) | ||
| 166 | continue; /* Column does not contain changes */ | ||
| 167 | |||
| 168 | for (row = 0; row < MAX_MATRIX_KEY_ROWS; row++) { | ||
| 169 | if ((keypad->rows_en_mask & (1 << row)) == 0) | ||
| 170 | continue; /* Row is not enabled */ | ||
| 171 | if ((bits_changed & (1 << row)) == 0) | ||
| 172 | continue; /* Row does not contain changes */ | ||
| 173 | |||
| 174 | code = MATRIX_SCAN_CODE(row, col, MATRIX_ROW_SHIFT); | ||
| 175 | input_event(input_dev, EV_MSC, MSC_SCAN, code); | ||
| 176 | input_report_key(input_dev, keypad->keycodes[code], | ||
| 177 | matrix_volatile_state[col] & (1 << row)); | ||
| 178 | dev_dbg(&input_dev->dev, "Event code: %d, val: %d", | ||
| 179 | keypad->keycodes[code], | ||
| 180 | matrix_volatile_state[col] & (1 << row)); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | input_sync(input_dev); | ||
| 184 | } | ||
| 185 | |||
| 186 | /* | ||
| 187 | * imx_keypad_check_for_events is the timer handler. | ||
| 188 | */ | ||
| 189 | static void imx_keypad_check_for_events(unsigned long data) | ||
| 190 | { | ||
| 191 | struct imx_keypad *keypad = (struct imx_keypad *) data; | ||
| 192 | unsigned short matrix_volatile_state[MAX_MATRIX_KEY_COLS]; | ||
| 193 | unsigned short reg_val; | ||
| 194 | bool state_changed, is_zero_matrix; | ||
| 195 | int i; | ||
| 196 | |||
| 197 | memset(matrix_volatile_state, 0, sizeof(matrix_volatile_state)); | ||
| 198 | |||
| 199 | imx_keypad_scan_matrix(keypad, matrix_volatile_state); | ||
| 200 | |||
| 201 | state_changed = false; | ||
| 202 | for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) { | ||
| 203 | if ((keypad->cols_en_mask & (1 << i)) == 0) | ||
| 204 | continue; | ||
| 205 | |||
| 206 | if (keypad->matrix_unstable_state[i] ^ matrix_volatile_state[i]) { | ||
| 207 | state_changed = true; | ||
| 208 | break; | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | /* | ||
| 213 | * If the matrix state is changed from the previous scan | ||
| 214 | * (Re)Begin the debouncing process, saving the new state in | ||
| 215 | * keypad->matrix_unstable_state. | ||
| 216 | * else | ||
| 217 | * Increase the count of number of scans with a stable state. | ||
| 218 | */ | ||
| 219 | if (state_changed) { | ||
| 220 | memcpy(keypad->matrix_unstable_state, matrix_volatile_state, | ||
| 221 | sizeof(matrix_volatile_state)); | ||
| 222 | keypad->stable_count = 0; | ||
| 223 | } else | ||
| 224 | keypad->stable_count++; | ||
| 225 | |||
| 226 | /* | ||
| 227 | * If the matrix is not as stable as we want reschedule scan | ||
| 228 | * in the near future. | ||
| 229 | */ | ||
| 230 | if (keypad->stable_count < IMX_KEYPAD_SCANS_FOR_STABILITY) { | ||
| 231 | mod_timer(&keypad->check_matrix_timer, | ||
| 232 | jiffies + msecs_to_jiffies(10)); | ||
| 233 | return; | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * If the matrix state is stable, fire the events and save the new | ||
| 238 | * stable state. Note, if the matrix is kept stable for longer | ||
| 239 | * (keypad->stable_count > IMX_KEYPAD_SCANS_FOR_STABILITY) all | ||
| 240 | * events have already been generated. | ||
| 241 | */ | ||
| 242 | if (keypad->stable_count == IMX_KEYPAD_SCANS_FOR_STABILITY) { | ||
| 243 | imx_keypad_fire_events(keypad, matrix_volatile_state); | ||
| 244 | |||
| 245 | memcpy(keypad->matrix_stable_state, matrix_volatile_state, | ||
| 246 | sizeof(matrix_volatile_state)); | ||
| 247 | } | ||
| 248 | |||
| 249 | is_zero_matrix = true; | ||
| 250 | for (i = 0; i < MAX_MATRIX_KEY_COLS; i++) { | ||
| 251 | if (matrix_volatile_state[i] != 0) { | ||
| 252 | is_zero_matrix = false; | ||
| 253 | break; | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | |||
| 258 | if (is_zero_matrix) { | ||
| 259 | /* | ||
| 260 | * All keys have been released. Enable only the KDI | ||
| 261 | * interrupt for future key presses (clear the KDI | ||
| 262 | * status bit and its sync chain before that). | ||
| 263 | */ | ||
| 264 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 265 | reg_val |= KBD_STAT_KPKD | KBD_STAT_KDSC; | ||
| 266 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 267 | |||
| 268 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 269 | reg_val |= KBD_STAT_KDIE; | ||
| 270 | reg_val &= ~KBD_STAT_KRIE; | ||
| 271 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 272 | } else { | ||
| 273 | /* | ||
| 274 | * Some keys are still pressed. Schedule a rescan in | ||
| 275 | * attempt to detect multiple key presses and enable | ||
| 276 | * the KRI interrupt to react quickly to key release | ||
| 277 | * event. | ||
| 278 | */ | ||
| 279 | mod_timer(&keypad->check_matrix_timer, | ||
| 280 | jiffies + msecs_to_jiffies(60)); | ||
| 281 | |||
| 282 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 283 | reg_val |= KBD_STAT_KPKR | KBD_STAT_KRSS; | ||
| 284 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 285 | |||
| 286 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 287 | reg_val |= KBD_STAT_KRIE; | ||
| 288 | reg_val &= ~KBD_STAT_KDIE; | ||
| 289 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | static irqreturn_t imx_keypad_irq_handler(int irq, void *dev_id) | ||
| 294 | { | ||
| 295 | struct imx_keypad *keypad = dev_id; | ||
| 296 | unsigned short reg_val; | ||
| 297 | |||
| 298 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 299 | |||
| 300 | /* Disable both interrupt types */ | ||
| 301 | reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); | ||
| 302 | /* Clear interrupts status bits */ | ||
| 303 | reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD; | ||
| 304 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 305 | |||
| 306 | if (keypad->enabled) { | ||
| 307 | /* The matrix is supposed to be changed */ | ||
| 308 | keypad->stable_count = 0; | ||
| 309 | |||
| 310 | /* Schedule the scanning procedure near in the future */ | ||
| 311 | mod_timer(&keypad->check_matrix_timer, | ||
| 312 | jiffies + msecs_to_jiffies(2)); | ||
| 313 | } | ||
| 314 | |||
| 315 | return IRQ_HANDLED; | ||
| 316 | } | ||
| 317 | |||
| 318 | static void imx_keypad_config(struct imx_keypad *keypad) | ||
| 319 | { | ||
| 320 | unsigned short reg_val; | ||
| 321 | |||
| 322 | /* | ||
| 323 | * Include enabled rows in interrupt generation (KPCR[7:0]) | ||
| 324 | * Configure keypad columns as open-drain (KPCR[15:8]) | ||
| 325 | */ | ||
| 326 | reg_val = readw(keypad->mmio_base + KPCR); | ||
| 327 | reg_val |= keypad->rows_en_mask & 0xff; /* rows */ | ||
| 328 | reg_val |= (keypad->cols_en_mask & 0xff) << 8; /* cols */ | ||
| 329 | writew(reg_val, keypad->mmio_base + KPCR); | ||
| 330 | |||
| 331 | /* Write 0's to KPDR[15:8] (Colums) */ | ||
| 332 | reg_val = readw(keypad->mmio_base + KPDR); | ||
| 333 | reg_val &= 0x00ff; | ||
| 334 | writew(reg_val, keypad->mmio_base + KPDR); | ||
| 335 | |||
| 336 | /* Configure columns as output, rows as input (KDDR[15:0]) */ | ||
| 337 | writew(0xff00, keypad->mmio_base + KDDR); | ||
| 338 | |||
| 339 | /* | ||
| 340 | * Clear Key Depress and Key Release status bit. | ||
| 341 | * Clear both synchronizer chain. | ||
| 342 | */ | ||
| 343 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 344 | reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD | | ||
| 345 | KBD_STAT_KDSC | KBD_STAT_KRSS; | ||
| 346 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 347 | |||
| 348 | /* Enable KDI and disable KRI (avoid false release events). */ | ||
| 349 | reg_val |= KBD_STAT_KDIE; | ||
| 350 | reg_val &= ~KBD_STAT_KRIE; | ||
| 351 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 352 | } | ||
| 353 | |||
| 354 | static void imx_keypad_inhibit(struct imx_keypad *keypad) | ||
| 355 | { | ||
| 356 | unsigned short reg_val; | ||
| 357 | |||
| 358 | /* Inhibit KDI and KRI interrupts. */ | ||
| 359 | reg_val = readw(keypad->mmio_base + KPSR); | ||
| 360 | reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE); | ||
| 361 | writew(reg_val, keypad->mmio_base + KPSR); | ||
| 362 | |||
| 363 | /* Colums as open drain and disable all rows */ | ||
| 364 | writew(0xff00, keypad->mmio_base + KPCR); | ||
| 365 | } | ||
| 366 | |||
| 367 | static void imx_keypad_close(struct input_dev *dev) | ||
| 368 | { | ||
| 369 | struct imx_keypad *keypad = input_get_drvdata(dev); | ||
| 370 | |||
| 371 | dev_dbg(&dev->dev, ">%s\n", __func__); | ||
| 372 | |||
| 373 | /* Mark keypad as being inactive */ | ||
| 374 | keypad->enabled = false; | ||
| 375 | synchronize_irq(keypad->irq); | ||
| 376 | del_timer_sync(&keypad->check_matrix_timer); | ||
| 377 | |||
| 378 | imx_keypad_inhibit(keypad); | ||
| 379 | |||
| 380 | /* Disable clock unit */ | ||
| 381 | clk_disable(keypad->clk); | ||
| 382 | } | ||
| 383 | |||
| 384 | static int imx_keypad_open(struct input_dev *dev) | ||
| 385 | { | ||
| 386 | struct imx_keypad *keypad = input_get_drvdata(dev); | ||
| 387 | |||
| 388 | dev_dbg(&dev->dev, ">%s\n", __func__); | ||
| 389 | |||
| 390 | /* We became active from now */ | ||
| 391 | keypad->enabled = true; | ||
| 392 | |||
| 393 | /* Enable the kpp clock */ | ||
| 394 | clk_enable(keypad->clk); | ||
| 395 | imx_keypad_config(keypad); | ||
| 396 | |||
| 397 | /* Sanity control, not all the rows must be actived now. */ | ||
| 398 | if ((readw(keypad->mmio_base + KPDR) & keypad->rows_en_mask) == 0) { | ||
| 399 | dev_err(&dev->dev, | ||
| 400 | "too many keys pressed, control pins initialisation\n"); | ||
| 401 | goto open_err; | ||
| 402 | } | ||
| 403 | |||
| 404 | return 0; | ||
| 405 | |||
| 406 | open_err: | ||
| 407 | imx_keypad_close(dev); | ||
| 408 | return -EIO; | ||
| 409 | } | ||
| 410 | |||
| 411 | static int __devinit imx_keypad_probe(struct platform_device *pdev) | ||
| 412 | { | ||
| 413 | const struct matrix_keymap_data *keymap_data = pdev->dev.platform_data; | ||
| 414 | struct imx_keypad *keypad; | ||
| 415 | struct input_dev *input_dev; | ||
| 416 | struct resource *res; | ||
| 417 | int irq, error, i; | ||
| 418 | |||
| 419 | if (keymap_data == NULL) { | ||
| 420 | dev_err(&pdev->dev, "no keymap defined\n"); | ||
| 421 | return -EINVAL; | ||
| 422 | } | ||
| 423 | |||
| 424 | irq = platform_get_irq(pdev, 0); | ||
| 425 | if (irq < 0) { | ||
| 426 | dev_err(&pdev->dev, "no irq defined in platform data\n"); | ||
| 427 | return -EINVAL; | ||
| 428 | } | ||
| 429 | |||
| 430 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 431 | if (res == NULL) { | ||
| 432 | dev_err(&pdev->dev, "no I/O memory defined in platform data\n"); | ||
| 433 | return -EINVAL; | ||
| 434 | } | ||
| 435 | |||
| 436 | res = request_mem_region(res->start, resource_size(res), pdev->name); | ||
| 437 | if (res == NULL) { | ||
| 438 | dev_err(&pdev->dev, "failed to request I/O memory\n"); | ||
| 439 | return -EBUSY; | ||
| 440 | } | ||
| 441 | |||
| 442 | input_dev = input_allocate_device(); | ||
| 443 | if (!input_dev) { | ||
| 444 | dev_err(&pdev->dev, "failed to allocate the input device\n"); | ||
| 445 | error = -ENOMEM; | ||
| 446 | goto failed_rel_mem; | ||
| 447 | } | ||
| 448 | |||
| 449 | keypad = kzalloc(sizeof(struct imx_keypad), GFP_KERNEL); | ||
| 450 | if (!keypad) { | ||
| 451 | dev_err(&pdev->dev, "not enough memory for driver data\n"); | ||
| 452 | error = -ENOMEM; | ||
| 453 | goto failed_free_input; | ||
| 454 | } | ||
| 455 | |||
| 456 | keypad->input_dev = input_dev; | ||
| 457 | keypad->irq = irq; | ||
| 458 | keypad->stable_count = 0; | ||
| 459 | |||
| 460 | setup_timer(&keypad->check_matrix_timer, | ||
| 461 | imx_keypad_check_for_events, (unsigned long) keypad); | ||
| 462 | |||
| 463 | keypad->mmio_base = ioremap(res->start, resource_size(res)); | ||
| 464 | if (keypad->mmio_base == NULL) { | ||
| 465 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | ||
| 466 | error = -ENOMEM; | ||
| 467 | goto failed_free_priv; | ||
| 468 | } | ||
| 469 | |||
| 470 | keypad->clk = clk_get(&pdev->dev, "kpp"); | ||
| 471 | if (IS_ERR(keypad->clk)) { | ||
| 472 | dev_err(&pdev->dev, "failed to get keypad clock\n"); | ||
| 473 | error = PTR_ERR(keypad->clk); | ||
| 474 | goto failed_unmap; | ||
| 475 | } | ||
| 476 | |||
| 477 | /* Search for rows and cols enabled */ | ||
| 478 | for (i = 0; i < keymap_data->keymap_size; i++) { | ||
| 479 | keypad->rows_en_mask |= 1 << KEY_ROW(keymap_data->keymap[i]); | ||
| 480 | keypad->cols_en_mask |= 1 << KEY_COL(keymap_data->keymap[i]); | ||
| 481 | } | ||
| 482 | |||
| 483 | if (keypad->rows_en_mask > ((1 << MAX_MATRIX_KEY_ROWS) - 1) || | ||
| 484 | keypad->cols_en_mask > ((1 << MAX_MATRIX_KEY_COLS) - 1)) { | ||
| 485 | dev_err(&pdev->dev, | ||
| 486 | "invalid key data (too many rows or colums)\n"); | ||
| 487 | error = -EINVAL; | ||
| 488 | goto failed_clock_put; | ||
| 489 | } | ||
| 490 | dev_dbg(&pdev->dev, "enabled rows mask: %x\n", keypad->rows_en_mask); | ||
| 491 | dev_dbg(&pdev->dev, "enabled cols mask: %x\n", keypad->cols_en_mask); | ||
| 492 | |||
| 493 | /* Init the Input device */ | ||
| 494 | input_dev->name = pdev->name; | ||
| 495 | input_dev->id.bustype = BUS_HOST; | ||
| 496 | input_dev->dev.parent = &pdev->dev; | ||
| 497 | input_dev->open = imx_keypad_open; | ||
| 498 | input_dev->close = imx_keypad_close; | ||
| 499 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | ||
| 500 | input_dev->keycode = keypad->keycodes; | ||
| 501 | input_dev->keycodesize = sizeof(keypad->keycodes[0]); | ||
| 502 | input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes); | ||
| 503 | |||
| 504 | matrix_keypad_build_keymap(keymap_data, MATRIX_ROW_SHIFT, | ||
| 505 | keypad->keycodes, input_dev->keybit); | ||
| 506 | |||
| 507 | input_set_capability(input_dev, EV_MSC, MSC_SCAN); | ||
| 508 | input_set_drvdata(input_dev, keypad); | ||
| 509 | |||
| 510 | /* Ensure that the keypad will stay dormant until opened */ | ||
| 511 | imx_keypad_inhibit(keypad); | ||
| 512 | |||
| 513 | error = request_irq(irq, imx_keypad_irq_handler, IRQF_DISABLED, | ||
| 514 | pdev->name, keypad); | ||
| 515 | if (error) { | ||
| 516 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 517 | goto failed_clock_put; | ||
| 518 | } | ||
| 519 | |||
| 520 | /* Register the input device */ | ||
| 521 | error = input_register_device(input_dev); | ||
| 522 | if (error) { | ||
| 523 | dev_err(&pdev->dev, "failed to register input device\n"); | ||
| 524 | goto failed_free_irq; | ||
| 525 | } | ||
| 526 | |||
| 527 | platform_set_drvdata(pdev, keypad); | ||
| 528 | device_init_wakeup(&pdev->dev, 1); | ||
| 529 | |||
| 530 | return 0; | ||
| 531 | |||
| 532 | failed_free_irq: | ||
| 533 | free_irq(irq, pdev); | ||
| 534 | failed_clock_put: | ||
| 535 | clk_put(keypad->clk); | ||
| 536 | failed_unmap: | ||
| 537 | iounmap(keypad->mmio_base); | ||
| 538 | failed_free_priv: | ||
| 539 | kfree(keypad); | ||
| 540 | failed_free_input: | ||
| 541 | input_free_device(input_dev); | ||
| 542 | failed_rel_mem: | ||
| 543 | release_mem_region(res->start, resource_size(res)); | ||
| 544 | return error; | ||
| 545 | } | ||
| 546 | |||
| 547 | static int __devexit imx_keypad_remove(struct platform_device *pdev) | ||
| 548 | { | ||
| 549 | struct imx_keypad *keypad = platform_get_drvdata(pdev); | ||
| 550 | struct resource *res; | ||
| 551 | |||
| 552 | dev_dbg(&pdev->dev, ">%s\n", __func__); | ||
| 553 | |||
| 554 | platform_set_drvdata(pdev, NULL); | ||
| 555 | |||
| 556 | input_unregister_device(keypad->input_dev); | ||
| 557 | |||
| 558 | free_irq(keypad->irq, keypad); | ||
| 559 | clk_put(keypad->clk); | ||
| 560 | |||
| 561 | iounmap(keypad->mmio_base); | ||
| 562 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 563 | release_mem_region(res->start, resource_size(res)); | ||
| 564 | |||
| 565 | kfree(keypad); | ||
| 566 | |||
| 567 | return 0; | ||
| 568 | } | ||
| 569 | |||
| 570 | static struct platform_driver imx_keypad_driver = { | ||
| 571 | .driver = { | ||
| 572 | .name = "imx-keypad", | ||
| 573 | .owner = THIS_MODULE, | ||
| 574 | }, | ||
| 575 | .probe = imx_keypad_probe, | ||
| 576 | .remove = __devexit_p(imx_keypad_remove), | ||
| 577 | }; | ||
| 578 | |||
| 579 | static int __init imx_keypad_init(void) | ||
| 580 | { | ||
| 581 | return platform_driver_register(&imx_keypad_driver); | ||
| 582 | } | ||
| 583 | |||
| 584 | static void __exit imx_keypad_exit(void) | ||
| 585 | { | ||
| 586 | platform_driver_unregister(&imx_keypad_driver); | ||
| 587 | } | ||
| 588 | |||
| 589 | module_init(imx_keypad_init); | ||
| 590 | module_exit(imx_keypad_exit); | ||
| 591 | |||
| 592 | MODULE_AUTHOR("Alberto Panizzo <maramaopercheseimorto@gmail.com>"); | ||
| 593 | MODULE_DESCRIPTION("IMX Keypad Port Driver"); | ||
| 594 | MODULE_LICENSE("GPL v2"); | ||
| 595 | MODULE_ALIAS("platform:imx-keypad"); | ||
diff --git a/drivers/input/keyboard/jornada680_kbd.c b/drivers/input/keyboard/jornada680_kbd.c index 781fc6102860..5fc976dbce0b 100644 --- a/drivers/input/keyboard/jornada680_kbd.c +++ b/drivers/input/keyboard/jornada680_kbd.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
| 25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
| 26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 27 | #include <linux/slab.h> | ||
| 27 | 28 | ||
| 28 | #include <asm/delay.h> | 29 | #include <asm/delay.h> |
| 29 | #include <asm/io.h> | 30 | #include <asm/io.h> |
diff --git a/drivers/input/keyboard/jornada720_kbd.c b/drivers/input/keyboard/jornada720_kbd.c index 4e016d823069..2cd3e1d56ea4 100644 --- a/drivers/input/keyboard/jornada720_kbd.c +++ b/drivers/input/keyboard/jornada720_kbd.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/slab.h> | ||
| 26 | 27 | ||
| 27 | #include <mach/jornada720.h> | 28 | #include <mach/jornada720.h> |
| 28 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index f9847e0fb553..fa9bb6d235e2 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
| @@ -72,9 +72,9 @@ | |||
| 72 | 72 | ||
| 73 | #define DRIVER_DESC "LK keyboard driver" | 73 | #define DRIVER_DESC "LK keyboard driver" |
| 74 | 74 | ||
| 75 | MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); | 75 | MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); |
| 76 | MODULE_DESCRIPTION (DRIVER_DESC); | 76 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 77 | MODULE_LICENSE ("GPL"); | 77 | MODULE_LICENSE("GPL"); |
| 78 | 78 | ||
| 79 | /* | 79 | /* |
| 80 | * Known parameters: | 80 | * Known parameters: |
| @@ -85,27 +85,27 @@ MODULE_LICENSE ("GPL"); | |||
| 85 | * Please notice that there's not yet an API to set these at runtime. | 85 | * Please notice that there's not yet an API to set these at runtime. |
| 86 | */ | 86 | */ |
| 87 | static int bell_volume = 100; /* % */ | 87 | static int bell_volume = 100; /* % */ |
| 88 | module_param (bell_volume, int, 0); | 88 | module_param(bell_volume, int, 0); |
| 89 | MODULE_PARM_DESC (bell_volume, "Bell volume (in %). default is 100%"); | 89 | MODULE_PARM_DESC(bell_volume, "Bell volume (in %). default is 100%"); |
| 90 | 90 | ||
| 91 | static int keyclick_volume = 100; /* % */ | 91 | static int keyclick_volume = 100; /* % */ |
| 92 | module_param (keyclick_volume, int, 0); | 92 | module_param(keyclick_volume, int, 0); |
| 93 | MODULE_PARM_DESC (keyclick_volume, "Keyclick volume (in %), default is 100%"); | 93 | MODULE_PARM_DESC(keyclick_volume, "Keyclick volume (in %), default is 100%"); |
| 94 | 94 | ||
| 95 | static int ctrlclick_volume = 100; /* % */ | 95 | static int ctrlclick_volume = 100; /* % */ |
| 96 | module_param (ctrlclick_volume, int, 0); | 96 | module_param(ctrlclick_volume, int, 0); |
| 97 | MODULE_PARM_DESC (ctrlclick_volume, "Ctrlclick volume (in %), default is 100%"); | 97 | MODULE_PARM_DESC(ctrlclick_volume, "Ctrlclick volume (in %), default is 100%"); |
| 98 | 98 | ||
| 99 | static int lk201_compose_is_alt; | 99 | static int lk201_compose_is_alt; |
| 100 | module_param (lk201_compose_is_alt, int, 0); | 100 | module_param(lk201_compose_is_alt, int, 0); |
| 101 | MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key " | 101 | MODULE_PARM_DESC(lk201_compose_is_alt, |
| 102 | "will act as an Alt key"); | 102 | "If set non-zero, LK201' Compose key will act as an Alt key"); |
| 103 | 103 | ||
| 104 | 104 | ||
| 105 | 105 | ||
| 106 | #undef LKKBD_DEBUG | 106 | #undef LKKBD_DEBUG |
| 107 | #ifdef LKKBD_DEBUG | 107 | #ifdef LKKBD_DEBUG |
| 108 | #define DBG(x...) printk (x) | 108 | #define DBG(x...) printk(x) |
| 109 | #else | 109 | #else |
| 110 | #define DBG(x...) do {} while (0) | 110 | #define DBG(x...) do {} while (0) |
| 111 | #endif | 111 | #endif |
| @@ -122,7 +122,7 @@ MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key " | |||
| 122 | #define LK_MODE_DOWN 0x80 | 122 | #define LK_MODE_DOWN 0x80 |
| 123 | #define LK_MODE_AUTODOWN 0x82 | 123 | #define LK_MODE_AUTODOWN 0x82 |
| 124 | #define LK_MODE_UPDOWN 0x86 | 124 | #define LK_MODE_UPDOWN 0x86 |
| 125 | #define LK_CMD_SET_MODE(mode,div) ((mode) | ((div) << 3)) | 125 | #define LK_CMD_SET_MODE(mode, div) ((mode) | ((div) << 3)) |
| 126 | 126 | ||
| 127 | /* Misc commands */ | 127 | /* Misc commands */ |
| 128 | #define LK_CMD_ENABLE_KEYCLICK 0x1b | 128 | #define LK_CMD_ENABLE_KEYCLICK 0x1b |
| @@ -152,11 +152,8 @@ MODULE_PARM_DESC (lk201_compose_is_alt, "If set non-zero, LK201' Compose key " | |||
| 152 | 152 | ||
| 153 | #define LK_NUM_KEYCODES 256 | 153 | #define LK_NUM_KEYCODES 256 |
| 154 | #define LK_NUM_IGNORE_BYTES 6 | 154 | #define LK_NUM_IGNORE_BYTES 6 |
| 155 | typedef u_int16_t lk_keycode_t; | ||
| 156 | 155 | ||
| 157 | 156 | static unsigned short lkkbd_keycode[LK_NUM_KEYCODES] = { | |
| 158 | |||
| 159 | static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = { | ||
| 160 | [0x56] = KEY_F1, | 157 | [0x56] = KEY_F1, |
| 161 | [0x57] = KEY_F2, | 158 | [0x57] = KEY_F2, |
| 162 | [0x58] = KEY_F3, | 159 | [0x58] = KEY_F3, |
| @@ -268,7 +265,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = { | |||
| 268 | }; | 265 | }; |
| 269 | 266 | ||
| 270 | #define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS) do { \ | 267 | #define CHECK_LED(LK, VAR_ON, VAR_OFF, LED, BITS) do { \ |
| 271 | if (test_bit (LED, (LK)->dev->led)) \ | 268 | if (test_bit(LED, (LK)->dev->led)) \ |
| 272 | VAR_ON |= BITS; \ | 269 | VAR_ON |= BITS; \ |
| 273 | else \ | 270 | else \ |
| 274 | VAR_OFF |= BITS; \ | 271 | VAR_OFF |= BITS; \ |
| @@ -278,7 +275,7 @@ static lk_keycode_t lkkbd_keycode[LK_NUM_KEYCODES] = { | |||
| 278 | * Per-keyboard data | 275 | * Per-keyboard data |
| 279 | */ | 276 | */ |
| 280 | struct lkkbd { | 277 | struct lkkbd { |
| 281 | lk_keycode_t keycode[LK_NUM_KEYCODES]; | 278 | unsigned short keycode[LK_NUM_KEYCODES]; |
| 282 | int ignore_bytes; | 279 | int ignore_bytes; |
| 283 | unsigned char id[LK_NUM_IGNORE_BYTES]; | 280 | unsigned char id[LK_NUM_IGNORE_BYTES]; |
| 284 | struct input_dev *dev; | 281 | struct input_dev *dev; |
| @@ -301,26 +298,25 @@ static struct { | |||
| 301 | unsigned char *name; | 298 | unsigned char *name; |
| 302 | } lk_response[] = { | 299 | } lk_response[] = { |
| 303 | #define RESPONSE(x) { .value = (x), .name = #x, } | 300 | #define RESPONSE(x) { .value = (x), .name = #x, } |
| 304 | RESPONSE (LK_STUCK_KEY), | 301 | RESPONSE(LK_STUCK_KEY), |
| 305 | RESPONSE (LK_SELFTEST_FAILED), | 302 | RESPONSE(LK_SELFTEST_FAILED), |
| 306 | RESPONSE (LK_ALL_KEYS_UP), | 303 | RESPONSE(LK_ALL_KEYS_UP), |
| 307 | RESPONSE (LK_METRONOME), | 304 | RESPONSE(LK_METRONOME), |
| 308 | RESPONSE (LK_OUTPUT_ERROR), | 305 | RESPONSE(LK_OUTPUT_ERROR), |
| 309 | RESPONSE (LK_INPUT_ERROR), | 306 | RESPONSE(LK_INPUT_ERROR), |
| 310 | RESPONSE (LK_KBD_LOCKED), | 307 | RESPONSE(LK_KBD_LOCKED), |
| 311 | RESPONSE (LK_KBD_TEST_MODE_ACK), | 308 | RESPONSE(LK_KBD_TEST_MODE_ACK), |
| 312 | RESPONSE (LK_PREFIX_KEY_DOWN), | 309 | RESPONSE(LK_PREFIX_KEY_DOWN), |
| 313 | RESPONSE (LK_MODE_CHANGE_ACK), | 310 | RESPONSE(LK_MODE_CHANGE_ACK), |
| 314 | RESPONSE (LK_RESPONSE_RESERVED), | 311 | RESPONSE(LK_RESPONSE_RESERVED), |
| 315 | #undef RESPONSE | 312 | #undef RESPONSE |
| 316 | }; | 313 | }; |
| 317 | 314 | ||
| 318 | static unsigned char * | 315 | static unsigned char *response_name(unsigned char value) |
| 319 | response_name (unsigned char value) | ||
| 320 | { | 316 | { |
| 321 | int i; | 317 | int i; |
| 322 | 318 | ||
| 323 | for (i = 0; i < ARRAY_SIZE (lk_response); i++) | 319 | for (i = 0; i < ARRAY_SIZE(lk_response); i++) |
| 324 | if (lk_response[i].value == value) | 320 | if (lk_response[i].value == value) |
| 325 | return lk_response[i].name; | 321 | return lk_response[i].name; |
| 326 | 322 | ||
| @@ -331,8 +327,7 @@ response_name (unsigned char value) | |||
| 331 | /* | 327 | /* |
| 332 | * Calculate volume parameter byte for a given volume. | 328 | * Calculate volume parameter byte for a given volume. |
| 333 | */ | 329 | */ |
| 334 | static unsigned char | 330 | static unsigned char volume_to_hw(int volume_percent) |
| 335 | volume_to_hw (int volume_percent) | ||
| 336 | { | 331 | { |
| 337 | unsigned char ret = 0; | 332 | unsigned char ret = 0; |
| 338 | 333 | ||
| @@ -363,8 +358,7 @@ volume_to_hw (int volume_percent) | |||
| 363 | return ret; | 358 | return ret; |
| 364 | } | 359 | } |
| 365 | 360 | ||
| 366 | static void | 361 | static void lkkbd_detection_done(struct lkkbd *lk) |
| 367 | lkkbd_detection_done (struct lkkbd *lk) | ||
| 368 | { | 362 | { |
| 369 | int i; | 363 | int i; |
| 370 | 364 | ||
| @@ -377,190 +371,202 @@ lkkbd_detection_done (struct lkkbd *lk) | |||
| 377 | * Print keyboard name and modify Compose=Alt on user's request. | 371 | * Print keyboard name and modify Compose=Alt on user's request. |
| 378 | */ | 372 | */ |
| 379 | switch (lk->id[4]) { | 373 | switch (lk->id[4]) { |
| 380 | case 1: | 374 | case 1: |
| 381 | strlcpy (lk->name, "DEC LK201 keyboard", | 375 | strlcpy(lk->name, "DEC LK201 keyboard", sizeof(lk->name)); |
| 382 | sizeof (lk->name)); | 376 | |
| 383 | 377 | if (lk201_compose_is_alt) | |
| 384 | if (lk201_compose_is_alt) | 378 | lk->keycode[0xb1] = KEY_LEFTALT; |
| 385 | lk->keycode[0xb1] = KEY_LEFTALT; | 379 | break; |
| 386 | break; | 380 | |
| 387 | 381 | case 2: | |
| 388 | case 2: | 382 | strlcpy(lk->name, "DEC LK401 keyboard", sizeof(lk->name)); |
| 389 | strlcpy (lk->name, "DEC LK401 keyboard", | 383 | break; |
| 390 | sizeof (lk->name)); | 384 | |
| 391 | break; | 385 | default: |
| 392 | 386 | strlcpy(lk->name, "Unknown DEC keyboard", sizeof(lk->name)); | |
| 393 | default: | 387 | printk(KERN_ERR |
| 394 | strlcpy (lk->name, "Unknown DEC keyboard", | 388 | "lkkbd: keyboard on %s is unknown, please report to " |
| 395 | sizeof (lk->name)); | 389 | "Jan-Benedict Glaw <jbglaw@lug-owl.de>\n", lk->phys); |
| 396 | printk (KERN_ERR "lkkbd: keyboard on %s is unknown, " | 390 | printk(KERN_ERR "lkkbd: keyboard ID'ed as:"); |
| 397 | "please report to Jan-Benedict Glaw " | 391 | for (i = 0; i < LK_NUM_IGNORE_BYTES; i++) |
| 398 | "<jbglaw@lug-owl.de>\n", lk->phys); | 392 | printk(" 0x%02x", lk->id[i]); |
| 399 | printk (KERN_ERR "lkkbd: keyboard ID'ed as:"); | 393 | printk("\n"); |
| 400 | for (i = 0; i < LK_NUM_IGNORE_BYTES; i++) | 394 | break; |
| 401 | printk (" 0x%02x", lk->id[i]); | ||
| 402 | printk ("\n"); | ||
| 403 | break; | ||
| 404 | } | 395 | } |
| 405 | printk (KERN_INFO "lkkbd: keyboard on %s identified as: %s\n", | 396 | |
| 406 | lk->phys, lk->name); | 397 | printk(KERN_INFO "lkkbd: keyboard on %s identified as: %s\n", |
| 398 | lk->phys, lk->name); | ||
| 407 | 399 | ||
| 408 | /* | 400 | /* |
| 409 | * Report errors during keyboard boot-up. | 401 | * Report errors during keyboard boot-up. |
| 410 | */ | 402 | */ |
| 411 | switch (lk->id[2]) { | 403 | switch (lk->id[2]) { |
| 412 | case 0x00: | 404 | case 0x00: |
| 413 | /* All okay */ | 405 | /* All okay */ |
| 414 | break; | 406 | break; |
| 415 | 407 | ||
| 416 | case LK_STUCK_KEY: | 408 | case LK_STUCK_KEY: |
| 417 | printk (KERN_ERR "lkkbd: Stuck key on keyboard at " | 409 | printk(KERN_ERR "lkkbd: Stuck key on keyboard at %s\n", |
| 418 | "%s\n", lk->phys); | 410 | lk->phys); |
| 419 | break; | 411 | break; |
| 420 | 412 | ||
| 421 | case LK_SELFTEST_FAILED: | 413 | case LK_SELFTEST_FAILED: |
| 422 | printk (KERN_ERR "lkkbd: Selftest failed on keyboard " | 414 | printk(KERN_ERR |
| 423 | "at %s, keyboard may not work " | 415 | "lkkbd: Selftest failed on keyboard at %s, " |
| 424 | "properly\n", lk->phys); | 416 | "keyboard may not work properly\n", lk->phys); |
| 425 | break; | 417 | break; |
| 426 | 418 | ||
| 427 | default: | 419 | default: |
| 428 | printk (KERN_ERR "lkkbd: Unknown error %02x on " | 420 | printk(KERN_ERR |
| 429 | "keyboard at %s\n", lk->id[2], | 421 | "lkkbd: Unknown error %02x on keyboard at %s\n", |
| 430 | lk->phys); | 422 | lk->id[2], lk->phys); |
| 431 | break; | 423 | break; |
| 432 | } | 424 | } |
| 433 | 425 | ||
| 434 | /* | 426 | /* |
| 435 | * Try to hint user if there's a stuck key. | 427 | * Try to hint user if there's a stuck key. |
| 436 | */ | 428 | */ |
| 437 | if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0) | 429 | if (lk->id[2] == LK_STUCK_KEY && lk->id[3] != 0) |
| 438 | printk (KERN_ERR "Scancode of stuck key is 0x%02x, keycode " | 430 | printk(KERN_ERR |
| 439 | "is 0x%04x\n", lk->id[3], | 431 | "Scancode of stuck key is 0x%02x, keycode is 0x%04x\n", |
| 440 | lk->keycode[lk->id[3]]); | 432 | lk->id[3], lk->keycode[lk->id[3]]); |
| 441 | |||
| 442 | return; | ||
| 443 | } | 433 | } |
| 444 | 434 | ||
| 445 | /* | 435 | /* |
| 446 | * lkkbd_interrupt() is called by the low level driver when a character | 436 | * lkkbd_interrupt() is called by the low level driver when a character |
| 447 | * is received. | 437 | * is received. |
| 448 | */ | 438 | */ |
| 449 | static irqreturn_t | 439 | static irqreturn_t lkkbd_interrupt(struct serio *serio, |
| 450 | lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags) | 440 | unsigned char data, unsigned int flags) |
| 451 | { | 441 | { |
| 452 | struct lkkbd *lk = serio_get_drvdata (serio); | 442 | struct lkkbd *lk = serio_get_drvdata(serio); |
| 443 | struct input_dev *input_dev = lk->dev; | ||
| 444 | unsigned int keycode; | ||
| 453 | int i; | 445 | int i; |
| 454 | 446 | ||
| 455 | DBG (KERN_INFO "Got byte 0x%02x\n", data); | 447 | DBG(KERN_INFO "Got byte 0x%02x\n", data); |
| 456 | 448 | ||
| 457 | if (lk->ignore_bytes > 0) { | 449 | if (lk->ignore_bytes > 0) { |
| 458 | DBG (KERN_INFO "Ignoring a byte on %s\n", lk->name); | 450 | DBG(KERN_INFO "Ignoring a byte on %s\n", lk->name); |
| 459 | lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; | 451 | lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; |
| 460 | 452 | ||
| 461 | if (lk->ignore_bytes == 0) | 453 | if (lk->ignore_bytes == 0) |
| 462 | lkkbd_detection_done (lk); | 454 | lkkbd_detection_done(lk); |
| 463 | 455 | ||
| 464 | return IRQ_HANDLED; | 456 | return IRQ_HANDLED; |
| 465 | } | 457 | } |
| 466 | 458 | ||
| 467 | switch (data) { | 459 | switch (data) { |
| 468 | case LK_ALL_KEYS_UP: | 460 | case LK_ALL_KEYS_UP: |
| 469 | for (i = 0; i < ARRAY_SIZE (lkkbd_keycode); i++) | 461 | for (i = 0; i < ARRAY_SIZE(lkkbd_keycode); i++) |
| 470 | if (lk->keycode[i] != KEY_RESERVED) | 462 | input_report_key(input_dev, lk->keycode[i], 0); |
| 471 | input_report_key (lk->dev, lk->keycode[i], 0); | 463 | input_sync(input_dev); |
| 472 | input_sync (lk->dev); | 464 | break; |
| 473 | break; | 465 | |
| 474 | 466 | case 0x01: | |
| 475 | case 0x01: | 467 | DBG(KERN_INFO "Got 0x01, scheduling re-initialization\n"); |
| 476 | DBG (KERN_INFO "Got 0x01, scheduling re-initialization\n"); | 468 | lk->ignore_bytes = LK_NUM_IGNORE_BYTES; |
| 477 | lk->ignore_bytes = LK_NUM_IGNORE_BYTES; | 469 | lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; |
| 478 | lk->id[LK_NUM_IGNORE_BYTES - lk->ignore_bytes--] = data; | 470 | schedule_work(&lk->tq); |
| 479 | schedule_work (&lk->tq); | 471 | break; |
| 480 | break; | 472 | |
| 481 | 473 | case LK_METRONOME: | |
| 482 | case LK_METRONOME: | 474 | case LK_OUTPUT_ERROR: |
| 483 | case LK_OUTPUT_ERROR: | 475 | case LK_INPUT_ERROR: |
| 484 | case LK_INPUT_ERROR: | 476 | case LK_KBD_LOCKED: |
| 485 | case LK_KBD_LOCKED: | 477 | case LK_KBD_TEST_MODE_ACK: |
| 486 | case LK_KBD_TEST_MODE_ACK: | 478 | case LK_PREFIX_KEY_DOWN: |
| 487 | case LK_PREFIX_KEY_DOWN: | 479 | case LK_MODE_CHANGE_ACK: |
| 488 | case LK_MODE_CHANGE_ACK: | 480 | case LK_RESPONSE_RESERVED: |
| 489 | case LK_RESPONSE_RESERVED: | 481 | DBG(KERN_INFO "Got %s and don't know how to handle...\n", |
| 490 | DBG (KERN_INFO "Got %s and don't know how to handle...\n", | 482 | response_name(data)); |
| 491 | response_name (data)); | 483 | break; |
| 492 | break; | 484 | |
| 493 | 485 | default: | |
| 494 | default: | 486 | keycode = lk->keycode[data]; |
| 495 | if (lk->keycode[data] != KEY_RESERVED) { | 487 | if (keycode != KEY_RESERVED) { |
| 496 | if (!test_bit (lk->keycode[data], lk->dev->key)) | 488 | input_report_key(input_dev, keycode, |
| 497 | input_report_key (lk->dev, lk->keycode[data], 1); | 489 | !test_bit(keycode, input_dev->key)); |
| 498 | else | 490 | input_sync(input_dev); |
| 499 | input_report_key (lk->dev, lk->keycode[data], 0); | 491 | } else { |
| 500 | input_sync (lk->dev); | 492 | printk(KERN_WARNING |
| 501 | } else | 493 | "%s: Unknown key with scancode 0x%02x on %s.\n", |
| 502 | printk (KERN_WARNING "%s: Unknown key with " | 494 | __FILE__, data, lk->name); |
| 503 | "scancode 0x%02x on %s.\n", | 495 | } |
| 504 | __FILE__, data, lk->name); | ||
| 505 | } | 496 | } |
| 506 | 497 | ||
| 507 | return IRQ_HANDLED; | 498 | return IRQ_HANDLED; |
| 508 | } | 499 | } |
| 509 | 500 | ||
| 501 | static void lkkbd_toggle_leds(struct lkkbd *lk) | ||
| 502 | { | ||
| 503 | struct serio *serio = lk->serio; | ||
| 504 | unsigned char leds_on = 0; | ||
| 505 | unsigned char leds_off = 0; | ||
| 506 | |||
| 507 | CHECK_LED(lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | ||
| 508 | CHECK_LED(lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE); | ||
| 509 | CHECK_LED(lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | ||
| 510 | CHECK_LED(lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | ||
| 511 | if (leds_on != 0) { | ||
| 512 | serio_write(serio, LK_CMD_LED_ON); | ||
| 513 | serio_write(serio, leds_on); | ||
| 514 | } | ||
| 515 | if (leds_off != 0) { | ||
| 516 | serio_write(serio, LK_CMD_LED_OFF); | ||
| 517 | serio_write(serio, leds_off); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | static void lkkbd_toggle_keyclick(struct lkkbd *lk, bool on) | ||
| 522 | { | ||
| 523 | struct serio *serio = lk->serio; | ||
| 524 | |||
| 525 | if (on) { | ||
| 526 | DBG("%s: Activating key clicks\n", __func__); | ||
| 527 | serio_write(serio, LK_CMD_ENABLE_KEYCLICK); | ||
| 528 | serio_write(serio, volume_to_hw(lk->keyclick_volume)); | ||
| 529 | serio_write(serio, LK_CMD_ENABLE_CTRCLICK); | ||
| 530 | serio_write(serio, volume_to_hw(lk->ctrlclick_volume)); | ||
| 531 | } else { | ||
| 532 | DBG("%s: Deactivating key clicks\n", __func__); | ||
| 533 | serio_write(serio, LK_CMD_DISABLE_KEYCLICK); | ||
| 534 | serio_write(serio, LK_CMD_DISABLE_CTRCLICK); | ||
| 535 | } | ||
| 536 | |||
| 537 | } | ||
| 538 | |||
| 510 | /* | 539 | /* |
| 511 | * lkkbd_event() handles events from the input module. | 540 | * lkkbd_event() handles events from the input module. |
| 512 | */ | 541 | */ |
| 513 | static int | 542 | static int lkkbd_event(struct input_dev *dev, |
| 514 | lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | 543 | unsigned int type, unsigned int code, int value) |
| 515 | int value) | ||
| 516 | { | 544 | { |
| 517 | struct lkkbd *lk = input_get_drvdata (dev); | 545 | struct lkkbd *lk = input_get_drvdata(dev); |
| 518 | unsigned char leds_on = 0; | ||
| 519 | unsigned char leds_off = 0; | ||
| 520 | 546 | ||
| 521 | switch (type) { | 547 | switch (type) { |
| 522 | case EV_LED: | 548 | case EV_LED: |
| 523 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 549 | lkkbd_toggle_leds(lk); |
| 524 | CHECK_LED (lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE); | 550 | return 0; |
| 525 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | 551 | |
| 526 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | 552 | case EV_SND: |
| 527 | if (leds_on != 0) { | 553 | switch (code) { |
| 528 | serio_write (lk->serio, LK_CMD_LED_ON); | 554 | case SND_CLICK: |
| 529 | serio_write (lk->serio, leds_on); | 555 | lkkbd_toggle_keyclick(lk, value); |
| 530 | } | ||
| 531 | if (leds_off != 0) { | ||
| 532 | serio_write (lk->serio, LK_CMD_LED_OFF); | ||
| 533 | serio_write (lk->serio, leds_off); | ||
| 534 | } | ||
| 535 | return 0; | 556 | return 0; |
| 536 | 557 | ||
| 537 | case EV_SND: | 558 | case SND_BELL: |
| 538 | switch (code) { | 559 | if (value != 0) |
| 539 | case SND_CLICK: | 560 | serio_write(lk->serio, LK_CMD_SOUND_BELL); |
| 540 | if (value == 0) { | 561 | |
| 541 | DBG ("%s: Deactivating key clicks\n", __func__); | 562 | return 0; |
| 542 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | 563 | } |
| 543 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | 564 | |
| 544 | } else { | 565 | break; |
| 545 | DBG ("%s: Activating key clicks\n", __func__); | 566 | |
| 546 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | 567 | default: |
| 547 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); | 568 | printk(KERN_ERR "%s(): Got unknown type %d, code %d, value %d\n", |
| 548 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | 569 | __func__, type, code, value); |
| 549 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | ||
| 550 | } | ||
| 551 | return 0; | ||
| 552 | |||
| 553 | case SND_BELL: | ||
| 554 | if (value != 0) | ||
| 555 | serio_write (lk->serio, LK_CMD_SOUND_BELL); | ||
| 556 | |||
| 557 | return 0; | ||
| 558 | } | ||
| 559 | break; | ||
| 560 | |||
| 561 | default: | ||
| 562 | printk (KERN_ERR "%s (): Got unknown type %d, code %d, value %d\n", | ||
| 563 | __func__, type, code, value); | ||
| 564 | } | 570 | } |
| 565 | 571 | ||
| 566 | return -1; | 572 | return -1; |
| @@ -570,79 +576,56 @@ lkkbd_event (struct input_dev *dev, unsigned int type, unsigned int code, | |||
| 570 | * lkkbd_reinit() sets leds and beeps to a state the computer remembers they | 576 | * lkkbd_reinit() sets leds and beeps to a state the computer remembers they |
| 571 | * were in. | 577 | * were in. |
| 572 | */ | 578 | */ |
| 573 | static void | 579 | static void lkkbd_reinit(struct work_struct *work) |
| 574 | lkkbd_reinit (struct work_struct *work) | ||
| 575 | { | 580 | { |
| 576 | struct lkkbd *lk = container_of(work, struct lkkbd, tq); | 581 | struct lkkbd *lk = container_of(work, struct lkkbd, tq); |
| 577 | int division; | 582 | int division; |
| 578 | unsigned char leds_on = 0; | ||
| 579 | unsigned char leds_off = 0; | ||
| 580 | 583 | ||
| 581 | /* Ask for ID */ | 584 | /* Ask for ID */ |
| 582 | serio_write (lk->serio, LK_CMD_REQUEST_ID); | 585 | serio_write(lk->serio, LK_CMD_REQUEST_ID); |
| 583 | 586 | ||
| 584 | /* Reset parameters */ | 587 | /* Reset parameters */ |
| 585 | serio_write (lk->serio, LK_CMD_SET_DEFAULTS); | 588 | serio_write(lk->serio, LK_CMD_SET_DEFAULTS); |
| 586 | 589 | ||
| 587 | /* Set LEDs */ | 590 | /* Set LEDs */ |
| 588 | CHECK_LED (lk, leds_on, leds_off, LED_CAPSL, LK_LED_SHIFTLOCK); | 591 | lkkbd_toggle_leds(lk); |
| 589 | CHECK_LED (lk, leds_on, leds_off, LED_COMPOSE, LK_LED_COMPOSE); | ||
| 590 | CHECK_LED (lk, leds_on, leds_off, LED_SCROLLL, LK_LED_SCROLLLOCK); | ||
| 591 | CHECK_LED (lk, leds_on, leds_off, LED_SLEEP, LK_LED_WAIT); | ||
| 592 | if (leds_on != 0) { | ||
| 593 | serio_write (lk->serio, LK_CMD_LED_ON); | ||
| 594 | serio_write (lk->serio, leds_on); | ||
| 595 | } | ||
| 596 | if (leds_off != 0) { | ||
| 597 | serio_write (lk->serio, LK_CMD_LED_OFF); | ||
| 598 | serio_write (lk->serio, leds_off); | ||
| 599 | } | ||
| 600 | 592 | ||
| 601 | /* | 593 | /* |
| 602 | * Try to activate extended LK401 mode. This command will | 594 | * Try to activate extended LK401 mode. This command will |
| 603 | * only work with a LK401 keyboard and grants access to | 595 | * only work with a LK401 keyboard and grants access to |
| 604 | * LAlt, RAlt, RCompose and RShift. | 596 | * LAlt, RAlt, RCompose and RShift. |
| 605 | */ | 597 | */ |
| 606 | serio_write (lk->serio, LK_CMD_ENABLE_LK401); | 598 | serio_write(lk->serio, LK_CMD_ENABLE_LK401); |
| 607 | 599 | ||
| 608 | /* Set all keys to UPDOWN mode */ | 600 | /* Set all keys to UPDOWN mode */ |
| 609 | for (division = 1; division <= 14; division++) | 601 | for (division = 1; division <= 14; division++) |
| 610 | serio_write (lk->serio, LK_CMD_SET_MODE (LK_MODE_UPDOWN, | 602 | serio_write(lk->serio, |
| 611 | division)); | 603 | LK_CMD_SET_MODE(LK_MODE_UPDOWN, division)); |
| 612 | 604 | ||
| 613 | /* Enable bell and set volume */ | 605 | /* Enable bell and set volume */ |
| 614 | serio_write (lk->serio, LK_CMD_ENABLE_BELL); | 606 | serio_write(lk->serio, LK_CMD_ENABLE_BELL); |
| 615 | serio_write (lk->serio, volume_to_hw (lk->bell_volume)); | 607 | serio_write(lk->serio, volume_to_hw(lk->bell_volume)); |
| 616 | 608 | ||
| 617 | /* Enable/disable keyclick (and possibly set volume) */ | 609 | /* Enable/disable keyclick (and possibly set volume) */ |
| 618 | if (test_bit (SND_CLICK, lk->dev->snd)) { | 610 | lkkbd_toggle_keyclick(lk, test_bit(SND_CLICK, lk->dev->snd)); |
| 619 | serio_write (lk->serio, LK_CMD_ENABLE_KEYCLICK); | ||
| 620 | serio_write (lk->serio, volume_to_hw (lk->keyclick_volume)); | ||
| 621 | serio_write (lk->serio, LK_CMD_ENABLE_CTRCLICK); | ||
| 622 | serio_write (lk->serio, volume_to_hw (lk->ctrlclick_volume)); | ||
| 623 | } else { | ||
| 624 | serio_write (lk->serio, LK_CMD_DISABLE_KEYCLICK); | ||
| 625 | serio_write (lk->serio, LK_CMD_DISABLE_CTRCLICK); | ||
| 626 | } | ||
| 627 | 611 | ||
| 628 | /* Sound the bell if needed */ | 612 | /* Sound the bell if needed */ |
| 629 | if (test_bit (SND_BELL, lk->dev->snd)) | 613 | if (test_bit(SND_BELL, lk->dev->snd)) |
| 630 | serio_write (lk->serio, LK_CMD_SOUND_BELL); | 614 | serio_write(lk->serio, LK_CMD_SOUND_BELL); |
| 631 | } | 615 | } |
| 632 | 616 | ||
| 633 | /* | 617 | /* |
| 634 | * lkkbd_connect() probes for a LK keyboard and fills the necessary structures. | 618 | * lkkbd_connect() probes for a LK keyboard and fills the necessary structures. |
| 635 | */ | 619 | */ |
| 636 | static int | 620 | static int lkkbd_connect(struct serio *serio, struct serio_driver *drv) |
| 637 | lkkbd_connect (struct serio *serio, struct serio_driver *drv) | ||
| 638 | { | 621 | { |
| 639 | struct lkkbd *lk; | 622 | struct lkkbd *lk; |
| 640 | struct input_dev *input_dev; | 623 | struct input_dev *input_dev; |
| 641 | int i; | 624 | int i; |
| 642 | int err; | 625 | int err; |
| 643 | 626 | ||
| 644 | lk = kzalloc (sizeof (struct lkkbd), GFP_KERNEL); | 627 | lk = kzalloc(sizeof(struct lkkbd), GFP_KERNEL); |
| 645 | input_dev = input_allocate_device (); | 628 | input_dev = input_allocate_device(); |
| 646 | if (!lk || !input_dev) { | 629 | if (!lk || !input_dev) { |
| 647 | err = -ENOMEM; | 630 | err = -ENOMEM; |
| 648 | goto fail1; | 631 | goto fail1; |
| @@ -650,14 +633,14 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
| 650 | 633 | ||
| 651 | lk->serio = serio; | 634 | lk->serio = serio; |
| 652 | lk->dev = input_dev; | 635 | lk->dev = input_dev; |
| 653 | INIT_WORK (&lk->tq, lkkbd_reinit); | 636 | INIT_WORK(&lk->tq, lkkbd_reinit); |
| 654 | lk->bell_volume = bell_volume; | 637 | lk->bell_volume = bell_volume; |
| 655 | lk->keyclick_volume = keyclick_volume; | 638 | lk->keyclick_volume = keyclick_volume; |
| 656 | lk->ctrlclick_volume = ctrlclick_volume; | 639 | lk->ctrlclick_volume = ctrlclick_volume; |
| 657 | memcpy (lk->keycode, lkkbd_keycode, sizeof (lk_keycode_t) * LK_NUM_KEYCODES); | 640 | memcpy(lk->keycode, lkkbd_keycode, sizeof(lk->keycode)); |
| 658 | 641 | ||
| 659 | strlcpy (lk->name, "DEC LK keyboard", sizeof(lk->name)); | 642 | strlcpy(lk->name, "DEC LK keyboard", sizeof(lk->name)); |
| 660 | snprintf (lk->phys, sizeof(lk->phys), "%s/input0", serio->phys); | 643 | snprintf(lk->phys, sizeof(lk->phys), "%s/input0", serio->phys); |
| 661 | 644 | ||
| 662 | input_dev->name = lk->name; | 645 | input_dev->name = lk->name; |
| 663 | input_dev->phys = lk->phys; | 646 | input_dev->phys = lk->phys; |
| @@ -668,62 +651,61 @@ lkkbd_connect (struct serio *serio, struct serio_driver *drv) | |||
| 668 | input_dev->dev.parent = &serio->dev; | 651 | input_dev->dev.parent = &serio->dev; |
| 669 | input_dev->event = lkkbd_event; | 652 | input_dev->event = lkkbd_event; |
| 670 | 653 | ||
| 671 | input_set_drvdata (input_dev, lk); | 654 | input_set_drvdata(input_dev, lk); |
| 672 | 655 | ||
| 673 | set_bit (EV_KEY, input_dev->evbit); | 656 | __set_bit(EV_KEY, input_dev->evbit); |
| 674 | set_bit (EV_LED, input_dev->evbit); | 657 | __set_bit(EV_LED, input_dev->evbit); |
| 675 | set_bit (EV_SND, input_dev->evbit); | 658 | __set_bit(EV_SND, input_dev->evbit); |
| 676 | set_bit (EV_REP, input_dev->evbit); | 659 | __set_bit(EV_REP, input_dev->evbit); |
| 677 | set_bit (LED_CAPSL, input_dev->ledbit); | 660 | __set_bit(LED_CAPSL, input_dev->ledbit); |
| 678 | set_bit (LED_SLEEP, input_dev->ledbit); | 661 | __set_bit(LED_SLEEP, input_dev->ledbit); |
| 679 | set_bit (LED_COMPOSE, input_dev->ledbit); | 662 | __set_bit(LED_COMPOSE, input_dev->ledbit); |
| 680 | set_bit (LED_SCROLLL, input_dev->ledbit); | 663 | __set_bit(LED_SCROLLL, input_dev->ledbit); |
| 681 | set_bit (SND_BELL, input_dev->sndbit); | 664 | __set_bit(SND_BELL, input_dev->sndbit); |
| 682 | set_bit (SND_CLICK, input_dev->sndbit); | 665 | __set_bit(SND_CLICK, input_dev->sndbit); |
| 683 | 666 | ||
| 684 | input_dev->keycode = lk->keycode; | 667 | input_dev->keycode = lk->keycode; |
| 685 | input_dev->keycodesize = sizeof (lk_keycode_t); | 668 | input_dev->keycodesize = sizeof(lk->keycode[0]); |
| 686 | input_dev->keycodemax = LK_NUM_KEYCODES; | 669 | input_dev->keycodemax = ARRAY_SIZE(lk->keycode); |
| 687 | 670 | ||
| 688 | for (i = 0; i < LK_NUM_KEYCODES; i++) | 671 | for (i = 0; i < LK_NUM_KEYCODES; i++) |
| 689 | __set_bit (lk->keycode[i], input_dev->keybit); | 672 | __set_bit(lk->keycode[i], input_dev->keybit); |
| 690 | __clear_bit(KEY_RESERVED, input_dev->keybit); | 673 | __clear_bit(KEY_RESERVED, input_dev->keybit); |
| 691 | 674 | ||
| 692 | serio_set_drvdata (serio, lk); | 675 | serio_set_drvdata(serio, lk); |
| 693 | 676 | ||
| 694 | err = serio_open (serio, drv); | 677 | err = serio_open(serio, drv); |
| 695 | if (err) | 678 | if (err) |
| 696 | goto fail2; | 679 | goto fail2; |
| 697 | 680 | ||
| 698 | err = input_register_device (lk->dev); | 681 | err = input_register_device(lk->dev); |
| 699 | if (err) | 682 | if (err) |
| 700 | goto fail3; | 683 | goto fail3; |
| 701 | 684 | ||
| 702 | serio_write (lk->serio, LK_CMD_POWERCYCLE_RESET); | 685 | serio_write(lk->serio, LK_CMD_POWERCYCLE_RESET); |
| 703 | 686 | ||
| 704 | return 0; | 687 | return 0; |
| 705 | 688 | ||
| 706 | fail3: serio_close (serio); | 689 | fail3: serio_close(serio); |
| 707 | fail2: serio_set_drvdata (serio, NULL); | 690 | fail2: serio_set_drvdata(serio, NULL); |
| 708 | fail1: input_free_device (input_dev); | 691 | fail1: input_free_device(input_dev); |
| 709 | kfree (lk); | 692 | kfree(lk); |
| 710 | return err; | 693 | return err; |
| 711 | } | 694 | } |
| 712 | 695 | ||
| 713 | /* | 696 | /* |
| 714 | * lkkbd_disconnect() unregisters and closes behind us. | 697 | * lkkbd_disconnect() unregisters and closes behind us. |
| 715 | */ | 698 | */ |
| 716 | static void | 699 | static void lkkbd_disconnect(struct serio *serio) |
| 717 | lkkbd_disconnect (struct serio *serio) | ||
| 718 | { | 700 | { |
| 719 | struct lkkbd *lk = serio_get_drvdata (serio); | 701 | struct lkkbd *lk = serio_get_drvdata(serio); |
| 720 | 702 | ||
| 721 | input_get_device (lk->dev); | 703 | input_get_device(lk->dev); |
| 722 | input_unregister_device (lk->dev); | 704 | input_unregister_device(lk->dev); |
| 723 | serio_close (serio); | 705 | serio_close(serio); |
| 724 | serio_set_drvdata (serio, NULL); | 706 | serio_set_drvdata(serio, NULL); |
| 725 | input_put_device (lk->dev); | 707 | input_put_device(lk->dev); |
| 726 | kfree (lk); | 708 | kfree(lk); |
| 727 | } | 709 | } |
| 728 | 710 | ||
| 729 | static struct serio_device_id lkkbd_serio_ids[] = { | 711 | static struct serio_device_id lkkbd_serio_ids[] = { |
| @@ -752,18 +734,16 @@ static struct serio_driver lkkbd_drv = { | |||
| 752 | /* | 734 | /* |
| 753 | * The functions for insering/removing us as a module. | 735 | * The functions for insering/removing us as a module. |
| 754 | */ | 736 | */ |
| 755 | static int __init | 737 | static int __init lkkbd_init(void) |
| 756 | lkkbd_init (void) | ||
| 757 | { | 738 | { |
| 758 | return serio_register_driver(&lkkbd_drv); | 739 | return serio_register_driver(&lkkbd_drv); |
| 759 | } | 740 | } |
| 760 | 741 | ||
| 761 | static void __exit | 742 | static void __exit lkkbd_exit(void) |
| 762 | lkkbd_exit (void) | ||
| 763 | { | 743 | { |
| 764 | serio_unregister_driver(&lkkbd_drv); | 744 | serio_unregister_driver(&lkkbd_drv); |
| 765 | } | 745 | } |
| 766 | 746 | ||
| 767 | module_init (lkkbd_init); | 747 | module_init(lkkbd_init); |
| 768 | module_exit (lkkbd_exit); | 748 | module_exit(lkkbd_exit); |
| 769 | 749 | ||
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 574eda2a4957..60ac4684f875 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/input.h> | 31 | #include <linux/input.h> |
| 32 | #include <linux/leds.h> | 32 | #include <linux/leds.h> |
| 33 | #include <linux/i2c/lm8323.h> | 33 | #include <linux/i2c/lm8323.h> |
| 34 | #include <linux/slab.h> | ||
| 34 | 35 | ||
| 35 | /* Commands to send to the chip. */ | 36 | /* Commands to send to the chip. */ |
| 36 | #define LM8323_CMD_READ_ID 0x80 /* Read chip ID. */ | 37 | #define LM8323_CMD_READ_ID 0x80 /* Read chip ID. */ |
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index 9caed30f3bbb..b1ab29861e1c 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c | |||
| @@ -192,11 +192,18 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd) | |||
| 192 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) | 192 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id) |
| 193 | { | 193 | { |
| 194 | struct locomokbd *locomokbd = dev_id; | 194 | struct locomokbd *locomokbd = dev_id; |
| 195 | u16 r; | ||
| 196 | |||
| 197 | r = locomo_readl(locomokbd->base + LOCOMO_KIC); | ||
| 198 | if ((r & 0x0001) == 0) | ||
| 199 | return IRQ_HANDLED; | ||
| 200 | |||
| 201 | locomo_writel(r & ~0x0100, locomokbd->base + LOCOMO_KIC); /* Ack */ | ||
| 202 | |||
| 195 | /** wait chattering delay **/ | 203 | /** wait chattering delay **/ |
| 196 | udelay(100); | 204 | udelay(100); |
| 197 | 205 | ||
| 198 | locomokbd_scankeyboard(locomokbd); | 206 | locomokbd_scankeyboard(locomokbd); |
| 199 | |||
| 200 | return IRQ_HANDLED; | 207 | return IRQ_HANDLED; |
| 201 | } | 208 | } |
| 202 | 209 | ||
| @@ -210,6 +217,25 @@ static void locomokbd_timer_callback(unsigned long data) | |||
| 210 | locomokbd_scankeyboard(locomokbd); | 217 | locomokbd_scankeyboard(locomokbd); |
| 211 | } | 218 | } |
| 212 | 219 | ||
| 220 | static int locomokbd_open(struct input_dev *dev) | ||
| 221 | { | ||
| 222 | struct locomokbd *locomokbd = input_get_drvdata(dev); | ||
| 223 | u16 r; | ||
| 224 | |||
| 225 | r = locomo_readl(locomokbd->base + LOCOMO_KIC) | 0x0010; | ||
| 226 | locomo_writel(r, locomokbd->base + LOCOMO_KIC); | ||
| 227 | return 0; | ||
| 228 | } | ||
| 229 | |||
| 230 | static void locomokbd_close(struct input_dev *dev) | ||
| 231 | { | ||
| 232 | struct locomokbd *locomokbd = input_get_drvdata(dev); | ||
| 233 | u16 r; | ||
| 234 | |||
| 235 | r = locomo_readl(locomokbd->base + LOCOMO_KIC) & ~0x0010; | ||
| 236 | locomo_writel(r, locomokbd->base + LOCOMO_KIC); | ||
| 237 | } | ||
| 238 | |||
| 213 | static int __devinit locomokbd_probe(struct locomo_dev *dev) | 239 | static int __devinit locomokbd_probe(struct locomo_dev *dev) |
| 214 | { | 240 | { |
| 215 | struct locomokbd *locomokbd; | 241 | struct locomokbd *locomokbd; |
| @@ -253,6 +279,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) | |||
| 253 | input_dev->id.vendor = 0x0001; | 279 | input_dev->id.vendor = 0x0001; |
| 254 | input_dev->id.product = 0x0001; | 280 | input_dev->id.product = 0x0001; |
| 255 | input_dev->id.version = 0x0100; | 281 | input_dev->id.version = 0x0100; |
| 282 | input_dev->open = locomokbd_open; | ||
| 283 | input_dev->close = locomokbd_close; | ||
| 256 | input_dev->dev.parent = &dev->dev; | 284 | input_dev->dev.parent = &dev->dev; |
| 257 | 285 | ||
| 258 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | 286 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | |
| @@ -261,6 +289,8 @@ static int __devinit locomokbd_probe(struct locomo_dev *dev) | |||
| 261 | input_dev->keycodesize = sizeof(locomokbd_keycode[0]); | 289 | input_dev->keycodesize = sizeof(locomokbd_keycode[0]); |
| 262 | input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode); | 290 | input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode); |
| 263 | 291 | ||
| 292 | input_set_drvdata(input_dev, locomokbd); | ||
| 293 | |||
| 264 | memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode)); | 294 | memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode)); |
| 265 | for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) | 295 | for (i = 0; i < LOCOMOKBD_NUMKEYS; i++) |
| 266 | set_bit(locomokbd->keycode[i], input_dev->keybit); | 296 | set_bit(locomokbd->keycode[i], input_dev->keybit); |
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 91cfe5170265..ffc25cfcef7a 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
| 24 | #include <linux/input/matrix_keypad.h> | 24 | #include <linux/input/matrix_keypad.h> |
| 25 | #include <linux/slab.h> | ||
| 25 | 26 | ||
| 26 | struct matrix_keypad { | 27 | struct matrix_keypad { |
| 27 | const struct matrix_keypad_platform_data *pdata; | 28 | const struct matrix_keypad_platform_data *pdata; |
| @@ -29,11 +30,13 @@ struct matrix_keypad { | |||
| 29 | unsigned short *keycodes; | 30 | unsigned short *keycodes; |
| 30 | unsigned int row_shift; | 31 | unsigned int row_shift; |
| 31 | 32 | ||
| 33 | DECLARE_BITMAP(disabled_gpios, MATRIX_MAX_ROWS); | ||
| 34 | |||
| 32 | uint32_t last_key_state[MATRIX_MAX_COLS]; | 35 | uint32_t last_key_state[MATRIX_MAX_COLS]; |
| 33 | struct delayed_work work; | 36 | struct delayed_work work; |
| 37 | spinlock_t lock; | ||
| 34 | bool scan_pending; | 38 | bool scan_pending; |
| 35 | bool stopped; | 39 | bool stopped; |
| 36 | spinlock_t lock; | ||
| 37 | }; | 40 | }; |
| 38 | 41 | ||
| 39 | /* | 42 | /* |
| @@ -213,38 +216,53 @@ static void matrix_keypad_stop(struct input_dev *dev) | |||
| 213 | } | 216 | } |
| 214 | 217 | ||
| 215 | #ifdef CONFIG_PM | 218 | #ifdef CONFIG_PM |
| 216 | static int matrix_keypad_suspend(struct platform_device *pdev, pm_message_t state) | 219 | static int matrix_keypad_suspend(struct device *dev) |
| 217 | { | 220 | { |
| 221 | struct platform_device *pdev = to_platform_device(dev); | ||
| 218 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | 222 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); |
| 219 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 223 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
| 220 | int i; | 224 | int i; |
| 221 | 225 | ||
| 222 | matrix_keypad_stop(keypad->input_dev); | 226 | matrix_keypad_stop(keypad->input_dev); |
| 223 | 227 | ||
| 224 | if (device_may_wakeup(&pdev->dev)) | 228 | if (device_may_wakeup(&pdev->dev)) { |
| 225 | for (i = 0; i < pdata->num_row_gpios; i++) | 229 | for (i = 0; i < pdata->num_row_gpios; i++) { |
| 226 | enable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | 230 | if (!test_bit(i, keypad->disabled_gpios)) { |
| 231 | unsigned int gpio = pdata->row_gpios[i]; | ||
| 232 | |||
| 233 | if (enable_irq_wake(gpio_to_irq(gpio)) == 0) | ||
| 234 | __set_bit(i, keypad->disabled_gpios); | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 227 | 238 | ||
| 228 | return 0; | 239 | return 0; |
| 229 | } | 240 | } |
| 230 | 241 | ||
| 231 | static int matrix_keypad_resume(struct platform_device *pdev) | 242 | static int matrix_keypad_resume(struct device *dev) |
| 232 | { | 243 | { |
| 244 | struct platform_device *pdev = to_platform_device(dev); | ||
| 233 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); | 245 | struct matrix_keypad *keypad = platform_get_drvdata(pdev); |
| 234 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; | 246 | const struct matrix_keypad_platform_data *pdata = keypad->pdata; |
| 235 | int i; | 247 | int i; |
| 236 | 248 | ||
| 237 | if (device_may_wakeup(&pdev->dev)) | 249 | if (device_may_wakeup(&pdev->dev)) { |
| 238 | for (i = 0; i < pdata->num_row_gpios; i++) | 250 | for (i = 0; i < pdata->num_row_gpios; i++) { |
| 239 | disable_irq_wake(gpio_to_irq(pdata->row_gpios[i])); | 251 | if (test_and_clear_bit(i, keypad->disabled_gpios)) { |
| 252 | unsigned int gpio = pdata->row_gpios[i]; | ||
| 253 | |||
| 254 | disable_irq_wake(gpio_to_irq(gpio)); | ||
| 255 | } | ||
| 256 | } | ||
| 257 | } | ||
| 240 | 258 | ||
| 241 | matrix_keypad_start(keypad->input_dev); | 259 | matrix_keypad_start(keypad->input_dev); |
| 242 | 260 | ||
| 243 | return 0; | 261 | return 0; |
| 244 | } | 262 | } |
| 245 | #else | 263 | |
| 246 | #define matrix_keypad_suspend NULL | 264 | static const SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops, |
| 247 | #define matrix_keypad_resume NULL | 265 | matrix_keypad_suspend, matrix_keypad_resume); |
| 248 | #endif | 266 | #endif |
| 249 | 267 | ||
| 250 | static int __devinit init_matrix_gpio(struct platform_device *pdev, | 268 | static int __devinit init_matrix_gpio(struct platform_device *pdev, |
| @@ -417,11 +435,12 @@ static int __devexit matrix_keypad_remove(struct platform_device *pdev) | |||
| 417 | static struct platform_driver matrix_keypad_driver = { | 435 | static struct platform_driver matrix_keypad_driver = { |
| 418 | .probe = matrix_keypad_probe, | 436 | .probe = matrix_keypad_probe, |
| 419 | .remove = __devexit_p(matrix_keypad_remove), | 437 | .remove = __devexit_p(matrix_keypad_remove), |
| 420 | .suspend = matrix_keypad_suspend, | ||
| 421 | .resume = matrix_keypad_resume, | ||
| 422 | .driver = { | 438 | .driver = { |
| 423 | .name = "matrix-keypad", | 439 | .name = "matrix-keypad", |
| 424 | .owner = THIS_MODULE, | 440 | .owner = THIS_MODULE, |
| 441 | #ifdef CONFIG_PM | ||
| 442 | .pm = &matrix_keypad_pm_ops, | ||
| 443 | #endif | ||
| 425 | }, | 444 | }, |
| 426 | }; | 445 | }; |
| 427 | 446 | ||
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 3b5b948eba39..7fc8185e5c1b 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/i2c.h> | 17 | #include <linux/i2c.h> |
| 18 | #include <linux/slab.h> | ||
| 18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 19 | #include <linux/input.h> | 20 | #include <linux/input.h> |
| 20 | #include <linux/input/matrix_keypad.h> | 21 | #include <linux/input/matrix_keypad.h> |
diff --git a/drivers/input/keyboard/omap-keypad.c b/drivers/input/keyboard/omap-keypad.c index bba85add35a3..a72e61ddca91 100644 --- a/drivers/input/keyboard/omap-keypad.c +++ b/drivers/input/keyboard/omap-keypad.c | |||
| @@ -34,13 +34,14 @@ | |||
| 34 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 35 | #include <linux/mutex.h> | 35 | #include <linux/mutex.h> |
| 36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
| 37 | #include <linux/slab.h> | ||
| 37 | #include <mach/gpio.h> | 38 | #include <mach/gpio.h> |
| 38 | #include <mach/keypad.h> | 39 | #include <plat/keypad.h> |
| 39 | #include <mach/menelaus.h> | 40 | #include <plat/menelaus.h> |
| 40 | #include <asm/irq.h> | 41 | #include <asm/irq.h> |
| 41 | #include <mach/hardware.h> | 42 | #include <mach/hardware.h> |
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 43 | #include <mach/mux.h> | 44 | #include <plat/mux.h> |
| 44 | 45 | ||
| 45 | #undef NEW_BOARD_LEARNING_MODE | 46 | #undef NEW_BOARD_LEARNING_MODE |
| 46 | 47 | ||
diff --git a/drivers/input/keyboard/opencores-kbd.c b/drivers/input/keyboard/opencores-kbd.c index 78cccddbf551..1f1a5563f60a 100644 --- a/drivers/input/keyboard/opencores-kbd.c +++ b/drivers/input/keyboard/opencores-kbd.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | 18 | ||
| 18 | struct opencores_kbd { | 19 | struct opencores_kbd { |
| 19 | struct input_dev *input; | 20 | struct input_dev *input; |
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 79cd3e9fdf2e..0e53b3bc39af 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/clk.h> | 26 | #include <linux/clk.h> |
| 27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
| 28 | #include <linux/input/matrix_keypad.h> | 28 | #include <linux/input/matrix_keypad.h> |
| 29 | #include <linux/slab.h> | ||
| 29 | 30 | ||
| 30 | #include <asm/mach/arch.h> | 31 | #include <asm/mach/arch.h> |
| 31 | #include <asm/mach/map.h> | 32 | #include <asm/mach/map.h> |
diff --git a/drivers/input/keyboard/pxa930_rotary.c b/drivers/input/keyboard/pxa930_rotary.c index 95fbba470e65..b7123a44b6ec 100644 --- a/drivers/input/keyboard/pxa930_rotary.c +++ b/drivers/input/keyboard/pxa930_rotary.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/input.h> | 13 | #include <linux/input.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
| 16 | #include <linux/slab.h> | ||
| 16 | 17 | ||
| 17 | #include <mach/pxa930_rotary.h> | 18 | #include <mach/pxa930_rotary.h> |
| 18 | 19 | ||
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 191cc51d6cf8..31f30087b591 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c | |||
| @@ -362,7 +362,7 @@ static int __devexit qt2160_remove(struct i2c_client *client) | |||
| 362 | return 0; | 362 | return 0; |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | static struct i2c_device_id qt2160_idtable[] = { | 365 | static const struct i2c_device_id qt2160_idtable[] = { |
| 366 | { "qt2160", 0, }, | 366 | { "qt2160", 0, }, |
| 367 | { } | 367 | { } |
| 368 | }; | 368 | }; |
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 887af79b7bff..d7dafd9425b6 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c | |||
| @@ -18,17 +18,11 @@ | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/input.h> | 20 | #include <linux/input.h> |
| 21 | #include <linux/input/sh_keysc.h> | ||
| 22 | #include <linux/bitmap.h> | ||
| 21 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
| 22 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 23 | #include <asm/sh_keysc.h> | 25 | #include <linux/slab.h> |
| 24 | |||
| 25 | #define KYCR1_OFFS 0x00 | ||
| 26 | #define KYCR2_OFFS 0x04 | ||
| 27 | #define KYINDR_OFFS 0x08 | ||
| 28 | #define KYOUTDR_OFFS 0x0c | ||
| 29 | |||
| 30 | #define KYCR2_IRQ_LEVEL 0x10 | ||
| 31 | #define KYCR2_IRQ_DISABLED 0x00 | ||
| 32 | 26 | ||
| 33 | static const struct { | 27 | static const struct { |
| 34 | unsigned char kymd, keyout, keyin; | 28 | unsigned char kymd, keyout, keyin; |
| @@ -36,84 +30,131 @@ static const struct { | |||
| 36 | [SH_KEYSC_MODE_1] = { 0, 6, 5 }, | 30 | [SH_KEYSC_MODE_1] = { 0, 6, 5 }, |
| 37 | [SH_KEYSC_MODE_2] = { 1, 5, 6 }, | 31 | [SH_KEYSC_MODE_2] = { 1, 5, 6 }, |
| 38 | [SH_KEYSC_MODE_3] = { 2, 4, 7 }, | 32 | [SH_KEYSC_MODE_3] = { 2, 4, 7 }, |
| 33 | [SH_KEYSC_MODE_4] = { 3, 6, 6 }, | ||
| 34 | [SH_KEYSC_MODE_5] = { 4, 6, 7 }, | ||
| 35 | [SH_KEYSC_MODE_6] = { 5, 7, 7 }, | ||
| 39 | }; | 36 | }; |
| 40 | 37 | ||
| 41 | struct sh_keysc_priv { | 38 | struct sh_keysc_priv { |
| 42 | void __iomem *iomem_base; | 39 | void __iomem *iomem_base; |
| 43 | struct clk *clk; | 40 | struct clk *clk; |
| 44 | unsigned long last_keys; | 41 | DECLARE_BITMAP(last_keys, SH_KEYSC_MAXKEYS); |
| 45 | struct input_dev *input; | 42 | struct input_dev *input; |
| 46 | struct sh_keysc_info pdata; | 43 | struct sh_keysc_info pdata; |
| 47 | }; | 44 | }; |
| 48 | 45 | ||
| 46 | #define KYCR1 0 | ||
| 47 | #define KYCR2 1 | ||
| 48 | #define KYINDR 2 | ||
| 49 | #define KYOUTDR 3 | ||
| 50 | |||
| 51 | #define KYCR2_IRQ_LEVEL 0x10 | ||
| 52 | #define KYCR2_IRQ_DISABLED 0x00 | ||
| 53 | |||
| 54 | static unsigned long sh_keysc_read(struct sh_keysc_priv *p, int reg_nr) | ||
| 55 | { | ||
| 56 | return ioread16(p->iomem_base + (reg_nr << 2)); | ||
| 57 | } | ||
| 58 | |||
| 59 | static void sh_keysc_write(struct sh_keysc_priv *p, int reg_nr, | ||
| 60 | unsigned long value) | ||
| 61 | { | ||
| 62 | iowrite16(value, p->iomem_base + (reg_nr << 2)); | ||
| 63 | } | ||
| 64 | |||
| 65 | static void sh_keysc_level_mode(struct sh_keysc_priv *p, | ||
| 66 | unsigned long keys_set) | ||
| 67 | { | ||
| 68 | struct sh_keysc_info *pdata = &p->pdata; | ||
| 69 | |||
| 70 | sh_keysc_write(p, KYOUTDR, 0); | ||
| 71 | sh_keysc_write(p, KYCR2, KYCR2_IRQ_LEVEL | (keys_set << 8)); | ||
| 72 | |||
| 73 | if (pdata->kycr2_delay) | ||
| 74 | udelay(pdata->kycr2_delay); | ||
| 75 | } | ||
| 76 | |||
| 77 | static void sh_keysc_map_dbg(struct device *dev, unsigned long *map, | ||
| 78 | const char *str) | ||
| 79 | { | ||
| 80 | int k; | ||
| 81 | |||
| 82 | for (k = 0; k < BITS_TO_LONGS(SH_KEYSC_MAXKEYS); k++) | ||
| 83 | dev_dbg(dev, "%s[%d] 0x%lx\n", str, k, map[k]); | ||
| 84 | } | ||
| 85 | |||
| 49 | static irqreturn_t sh_keysc_isr(int irq, void *dev_id) | 86 | static irqreturn_t sh_keysc_isr(int irq, void *dev_id) |
| 50 | { | 87 | { |
| 51 | struct platform_device *pdev = dev_id; | 88 | struct platform_device *pdev = dev_id; |
| 52 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); | 89 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); |
| 53 | struct sh_keysc_info *pdata = &priv->pdata; | 90 | struct sh_keysc_info *pdata = &priv->pdata; |
| 54 | unsigned long keys, keys1, keys0, mask; | 91 | int keyout_nr = sh_keysc_mode[pdata->mode].keyout; |
| 92 | int keyin_nr = sh_keysc_mode[pdata->mode].keyin; | ||
| 93 | DECLARE_BITMAP(keys, SH_KEYSC_MAXKEYS); | ||
| 94 | DECLARE_BITMAP(keys0, SH_KEYSC_MAXKEYS); | ||
| 95 | DECLARE_BITMAP(keys1, SH_KEYSC_MAXKEYS); | ||
| 55 | unsigned char keyin_set, tmp; | 96 | unsigned char keyin_set, tmp; |
| 56 | int i, k; | 97 | int i, k, n; |
| 57 | 98 | ||
| 58 | dev_dbg(&pdev->dev, "isr!\n"); | 99 | dev_dbg(&pdev->dev, "isr!\n"); |
| 59 | 100 | ||
| 60 | keys1 = ~0; | 101 | bitmap_fill(keys1, SH_KEYSC_MAXKEYS); |
| 61 | keys0 = 0; | 102 | bitmap_zero(keys0, SH_KEYSC_MAXKEYS); |
| 62 | 103 | ||
| 63 | do { | 104 | do { |
| 64 | keys = 0; | 105 | bitmap_zero(keys, SH_KEYSC_MAXKEYS); |
| 65 | keyin_set = 0; | 106 | keyin_set = 0; |
| 66 | 107 | ||
| 67 | iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); | 108 | sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); |
| 109 | |||
| 110 | for (i = 0; i < keyout_nr; i++) { | ||
| 111 | n = keyin_nr * i; | ||
| 68 | 112 | ||
| 69 | for (i = 0; i < sh_keysc_mode[pdata->mode].keyout; i++) { | 113 | /* drive one KEYOUT pin low, read KEYIN pins */ |
| 70 | iowrite16(0xfff ^ (3 << (i * 2)), | 114 | sh_keysc_write(priv, KYOUTDR, 0xffff ^ (3 << (i * 2))); |
| 71 | priv->iomem_base + KYOUTDR_OFFS); | ||
| 72 | udelay(pdata->delay); | 115 | udelay(pdata->delay); |
| 73 | tmp = ioread16(priv->iomem_base + KYINDR_OFFS); | 116 | tmp = sh_keysc_read(priv, KYINDR); |
| 74 | keys |= tmp << (sh_keysc_mode[pdata->mode].keyin * i); | ||
| 75 | tmp ^= (1 << sh_keysc_mode[pdata->mode].keyin) - 1; | ||
| 76 | keyin_set |= tmp; | ||
| 77 | } | ||
| 78 | 117 | ||
| 79 | iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); | 118 | /* set bit if key press has been detected */ |
| 80 | iowrite16(KYCR2_IRQ_LEVEL | (keyin_set << 8), | 119 | for (k = 0; k < keyin_nr; k++) { |
| 81 | priv->iomem_base + KYCR2_OFFS); | 120 | if (tmp & (1 << k)) |
| 121 | __set_bit(n + k, keys); | ||
| 122 | } | ||
| 82 | 123 | ||
| 83 | if (pdata->kycr2_delay) | 124 | /* keep track of which KEYIN bits that have been set */ |
| 84 | udelay(pdata->kycr2_delay); | 125 | keyin_set |= tmp ^ ((1 << keyin_nr) - 1); |
| 126 | } | ||
| 85 | 127 | ||
| 86 | keys ^= ~0; | 128 | sh_keysc_level_mode(priv, keyin_set); |
| 87 | keys &= (1 << (sh_keysc_mode[pdata->mode].keyin * | ||
| 88 | sh_keysc_mode[pdata->mode].keyout)) - 1; | ||
| 89 | keys1 &= keys; | ||
| 90 | keys0 |= keys; | ||
| 91 | 129 | ||
| 92 | dev_dbg(&pdev->dev, "keys 0x%08lx\n", keys); | 130 | bitmap_complement(keys, keys, SH_KEYSC_MAXKEYS); |
| 131 | bitmap_and(keys1, keys1, keys, SH_KEYSC_MAXKEYS); | ||
| 132 | bitmap_or(keys0, keys0, keys, SH_KEYSC_MAXKEYS); | ||
| 93 | 133 | ||
| 94 | } while (ioread16(priv->iomem_base + KYCR2_OFFS) & 0x01); | 134 | sh_keysc_map_dbg(&pdev->dev, keys, "keys"); |
| 95 | 135 | ||
| 96 | dev_dbg(&pdev->dev, "last_keys 0x%08lx keys0 0x%08lx keys1 0x%08lx\n", | 136 | } while (sh_keysc_read(priv, KYCR2) & 0x01); |
| 97 | priv->last_keys, keys0, keys1); | 137 | |
| 138 | sh_keysc_map_dbg(&pdev->dev, priv->last_keys, "last_keys"); | ||
| 139 | sh_keysc_map_dbg(&pdev->dev, keys0, "keys0"); | ||
| 140 | sh_keysc_map_dbg(&pdev->dev, keys1, "keys1"); | ||
| 98 | 141 | ||
| 99 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { | 142 | for (i = 0; i < SH_KEYSC_MAXKEYS; i++) { |
| 100 | k = pdata->keycodes[i]; | 143 | k = pdata->keycodes[i]; |
| 101 | if (!k) | 144 | if (!k) |
| 102 | continue; | 145 | continue; |
| 103 | 146 | ||
| 104 | mask = 1 << i; | 147 | if (test_bit(i, keys0) == test_bit(i, priv->last_keys)) |
| 105 | |||
| 106 | if (!((priv->last_keys ^ keys0) & mask)) | ||
| 107 | continue; | 148 | continue; |
| 108 | 149 | ||
| 109 | if ((keys1 | keys0) & mask) { | 150 | if (test_bit(i, keys1) || test_bit(i, keys0)) { |
| 110 | input_event(priv->input, EV_KEY, k, 1); | 151 | input_event(priv->input, EV_KEY, k, 1); |
| 111 | priv->last_keys |= mask; | 152 | __set_bit(i, priv->last_keys); |
| 112 | } | 153 | } |
| 113 | 154 | ||
| 114 | if (!(keys1 & mask)) { | 155 | if (!test_bit(i, keys1)) { |
| 115 | input_event(priv->input, EV_KEY, k, 0); | 156 | input_event(priv->input, EV_KEY, k, 0); |
| 116 | priv->last_keys &= ~mask; | 157 | __clear_bit(i, priv->last_keys); |
| 117 | } | 158 | } |
| 118 | 159 | ||
| 119 | } | 160 | } |
| @@ -122,8 +163,6 @@ static irqreturn_t sh_keysc_isr(int irq, void *dev_id) | |||
| 122 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
| 123 | } | 164 | } |
| 124 | 165 | ||
| 125 | #define res_size(res) ((res)->end - (res)->start + 1) | ||
| 126 | |||
| 127 | static int __devinit sh_keysc_probe(struct platform_device *pdev) | 166 | static int __devinit sh_keysc_probe(struct platform_device *pdev) |
| 128 | { | 167 | { |
| 129 | struct sh_keysc_priv *priv; | 168 | struct sh_keysc_priv *priv; |
| @@ -164,7 +203,7 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
| 164 | memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); | 203 | memcpy(&priv->pdata, pdev->dev.platform_data, sizeof(priv->pdata)); |
| 165 | pdata = &priv->pdata; | 204 | pdata = &priv->pdata; |
| 166 | 205 | ||
| 167 | priv->iomem_base = ioremap_nocache(res->start, res_size(res)); | 206 | priv->iomem_base = ioremap_nocache(res->start, resource_size(res)); |
| 168 | if (priv->iomem_base == NULL) { | 207 | if (priv->iomem_base == NULL) { |
| 169 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); | 208 | dev_err(&pdev->dev, "failed to remap I/O memory\n"); |
| 170 | error = -ENXIO; | 209 | error = -ENXIO; |
| @@ -220,10 +259,9 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) | |||
| 220 | 259 | ||
| 221 | clk_enable(priv->clk); | 260 | clk_enable(priv->clk); |
| 222 | 261 | ||
| 223 | iowrite16((sh_keysc_mode[pdata->mode].kymd << 8) | | 262 | sh_keysc_write(priv, KYCR1, (sh_keysc_mode[pdata->mode].kymd << 8) | |
| 224 | pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); | 263 | pdata->scan_timing); |
| 225 | iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); | 264 | sh_keysc_level_mode(priv, 0); |
| 226 | iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); | ||
| 227 | 265 | ||
| 228 | device_init_wakeup(&pdev->dev, 1); | 266 | device_init_wakeup(&pdev->dev, 1); |
| 229 | 267 | ||
| @@ -248,7 +286,7 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) | |||
| 248 | { | 286 | { |
| 249 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); | 287 | struct sh_keysc_priv *priv = platform_get_drvdata(pdev); |
| 250 | 288 | ||
| 251 | iowrite16(KYCR2_IRQ_DISABLED, priv->iomem_base + KYCR2_OFFS); | 289 | sh_keysc_write(priv, KYCR2, KYCR2_IRQ_DISABLED); |
| 252 | 290 | ||
| 253 | input_unregister_device(priv->input); | 291 | input_unregister_device(priv->input); |
| 254 | free_irq(platform_get_irq(pdev, 0), pdev); | 292 | free_irq(platform_get_irq(pdev, 0), pdev); |
| @@ -270,7 +308,7 @@ static int sh_keysc_suspend(struct device *dev) | |||
| 270 | int irq = platform_get_irq(pdev, 0); | 308 | int irq = platform_get_irq(pdev, 0); |
| 271 | unsigned short value; | 309 | unsigned short value; |
| 272 | 310 | ||
| 273 | value = ioread16(priv->iomem_base + KYCR1_OFFS); | 311 | value = sh_keysc_read(priv, KYCR1); |
| 274 | 312 | ||
| 275 | if (device_may_wakeup(dev)) { | 313 | if (device_may_wakeup(dev)) { |
| 276 | value |= 0x80; | 314 | value |= 0x80; |
| @@ -279,7 +317,7 @@ static int sh_keysc_suspend(struct device *dev) | |||
| 279 | value &= ~0x80; | 317 | value &= ~0x80; |
| 280 | } | 318 | } |
| 281 | 319 | ||
| 282 | iowrite16(value, priv->iomem_base + KYCR1_OFFS); | 320 | sh_keysc_write(priv, KYCR1, value); |
| 283 | 321 | ||
| 284 | return 0; | 322 | return 0; |
| 285 | } | 323 | } |
| @@ -295,7 +333,7 @@ static int sh_keysc_resume(struct device *dev) | |||
| 295 | return 0; | 333 | return 0; |
| 296 | } | 334 | } |
| 297 | 335 | ||
| 298 | static struct dev_pm_ops sh_keysc_dev_pm_ops = { | 336 | static const struct dev_pm_ops sh_keysc_dev_pm_ops = { |
| 299 | .suspend = sh_keysc_suspend, | 337 | .suspend = sh_keysc_suspend, |
| 300 | .resume = sh_keysc_resume, | 338 | .resume = sh_keysc_resume, |
| 301 | }; | 339 | }; |
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c index 42cb3faf7336..3910f269cfc8 100644 --- a/drivers/input/keyboard/tosakbd.c +++ b/drivers/input/keyboard/tosakbd.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/slab.h> | ||
| 21 | 22 | ||
| 22 | #include <mach/gpio.h> | 23 | #include <mach/gpio.h> |
| 23 | #include <mach/tosa.h> | 24 | #include <mach/tosa.h> |
diff --git a/drivers/input/keyboard/twl4030_keypad.c b/drivers/input/keyboard/twl4030_keypad.c index 9a2977c21696..7aa59e07b689 100644 --- a/drivers/input/keyboard/twl4030_keypad.c +++ b/drivers/input/keyboard/twl4030_keypad.c | |||
| @@ -31,7 +31,8 @@ | |||
| 31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
| 32 | #include <linux/input.h> | 32 | #include <linux/input.h> |
| 33 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
| 34 | #include <linux/i2c/twl4030.h> | 34 | #include <linux/i2c/twl.h> |
| 35 | #include <linux/slab.h> | ||
| 35 | 36 | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| @@ -133,7 +134,7 @@ struct twl4030_keypad { | |||
| 133 | static int twl4030_kpread(struct twl4030_keypad *kp, | 134 | static int twl4030_kpread(struct twl4030_keypad *kp, |
| 134 | u8 *data, u32 reg, u8 num_bytes) | 135 | u8 *data, u32 reg, u8 num_bytes) |
| 135 | { | 136 | { |
| 136 | int ret = twl4030_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); | 137 | int ret = twl_i2c_read(TWL4030_MODULE_KEYPAD, data, reg, num_bytes); |
| 137 | 138 | ||
| 138 | if (ret < 0) | 139 | if (ret < 0) |
| 139 | dev_warn(kp->dbg_dev, | 140 | dev_warn(kp->dbg_dev, |
| @@ -145,7 +146,7 @@ static int twl4030_kpread(struct twl4030_keypad *kp, | |||
| 145 | 146 | ||
| 146 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) | 147 | static int twl4030_kpwrite_u8(struct twl4030_keypad *kp, u8 data, u32 reg) |
| 147 | { | 148 | { |
| 148 | int ret = twl4030_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); | 149 | int ret = twl_i2c_write_u8(TWL4030_MODULE_KEYPAD, data, reg); |
| 149 | 150 | ||
| 150 | if (ret < 0) | 151 | if (ret < 0) |
| 151 | dev_warn(kp->dbg_dev, | 152 | dev_warn(kp->dbg_dev, |
| @@ -253,14 +254,6 @@ static irqreturn_t do_kp_irq(int irq, void *_kp) | |||
| 253 | u8 reg; | 254 | u8 reg; |
| 254 | int ret; | 255 | int ret; |
| 255 | 256 | ||
| 256 | #ifdef CONFIG_LOCKDEP | ||
| 257 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | ||
| 258 | * we don't want and can't tolerate. Although it might be | ||
| 259 | * friendlier not to borrow this thread context... | ||
| 260 | */ | ||
| 261 | local_irq_enable(); | ||
| 262 | #endif | ||
| 263 | |||
| 264 | /* Read & Clear TWL4030 pending interrupt */ | 257 | /* Read & Clear TWL4030 pending interrupt */ |
| 265 | ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); | 258 | ret = twl4030_kpread(kp, ®, KEYP_ISR1, 1); |
| 266 | 259 | ||
| @@ -403,7 +396,8 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev) | |||
| 403 | * | 396 | * |
| 404 | * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... | 397 | * NOTE: we assume this host is wired to TWL4040 INT1, not INT2 ... |
| 405 | */ | 398 | */ |
| 406 | error = request_irq(kp->irq, do_kp_irq, 0, pdev->name, kp); | 399 | error = request_threaded_irq(kp->irq, NULL, do_kp_irq, |
| 400 | 0, pdev->name, kp); | ||
| 407 | if (error) { | 401 | if (error) { |
| 408 | dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", | 402 | dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n", |
| 409 | kp->irq); | 403 | kp->irq); |
diff --git a/drivers/input/keyboard/w90p910_keypad.c b/drivers/input/keyboard/w90p910_keypad.c index 6032def03707..4ef764cc493c 100644 --- a/drivers/input/keyboard/w90p910_keypad.c +++ b/drivers/input/keyboard/w90p910_keypad.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
| 20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | 23 | ||
| 23 | #include <mach/w90p910_keypad.h> | 24 | #include <mach/w90p910_keypad.h> |
| 24 | 25 | ||
diff --git a/drivers/input/misc/88pm860x_onkey.c b/drivers/input/misc/88pm860x_onkey.c new file mode 100644 index 000000000000..40dabd8487b5 --- /dev/null +++ b/drivers/input/misc/88pm860x_onkey.c | |||
| @@ -0,0 +1,156 @@ | |||
| 1 | /* | ||
| 2 | * 88pm860x_onkey.c - Marvell 88PM860x ONKEY driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009-2010 Marvell International Ltd. | ||
| 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
| 6 | * | ||
| 7 | * This file is subject to the terms and conditions of the GNU General | ||
| 8 | * Public License. See the file "COPYING" in the main directory of this | ||
| 9 | * archive for more details. | ||
| 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 | #include <linux/kernel.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/i2c.h> | ||
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/mfd/88pm860x.h> | ||
| 28 | #include <linux/slab.h> | ||
| 29 | |||
| 30 | #define PM8607_WAKEUP 0x0b | ||
| 31 | |||
| 32 | #define LONG_ONKEY_EN (1 << 1) | ||
| 33 | #define ONKEY_STATUS (1 << 0) | ||
| 34 | |||
| 35 | struct pm860x_onkey_info { | ||
| 36 | struct input_dev *idev; | ||
| 37 | struct pm860x_chip *chip; | ||
| 38 | struct i2c_client *i2c; | ||
| 39 | struct device *dev; | ||
| 40 | int irq; | ||
| 41 | }; | ||
| 42 | |||
| 43 | /* 88PM860x gives us an interrupt when ONKEY is held */ | ||
| 44 | static irqreturn_t pm860x_onkey_handler(int irq, void *data) | ||
| 45 | { | ||
| 46 | struct pm860x_onkey_info *info = data; | ||
| 47 | int ret; | ||
| 48 | |||
| 49 | ret = pm860x_reg_read(info->i2c, PM8607_STATUS_2); | ||
| 50 | ret &= ONKEY_STATUS; | ||
| 51 | input_report_key(info->idev, KEY_POWER, ret); | ||
| 52 | input_sync(info->idev); | ||
| 53 | |||
| 54 | /* Enable 8-second long onkey detection */ | ||
| 55 | pm860x_set_bits(info->i2c, PM8607_WAKEUP, 3, LONG_ONKEY_EN); | ||
| 56 | return IRQ_HANDLED; | ||
| 57 | } | ||
| 58 | |||
| 59 | static int __devinit pm860x_onkey_probe(struct platform_device *pdev) | ||
| 60 | { | ||
| 61 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 62 | struct pm860x_onkey_info *info; | ||
| 63 | int irq, ret; | ||
| 64 | |||
| 65 | irq = platform_get_irq(pdev, 0); | ||
| 66 | if (irq < 0) { | ||
| 67 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
| 68 | return -EINVAL; | ||
| 69 | } | ||
| 70 | |||
| 71 | info = kzalloc(sizeof(struct pm860x_onkey_info), GFP_KERNEL); | ||
| 72 | if (!info) | ||
| 73 | return -ENOMEM; | ||
| 74 | info->chip = chip; | ||
| 75 | info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | ||
| 76 | info->dev = &pdev->dev; | ||
| 77 | info->irq = irq + chip->irq_base; | ||
| 78 | |||
| 79 | info->idev = input_allocate_device(); | ||
| 80 | if (!info->idev) { | ||
| 81 | dev_err(chip->dev, "Failed to allocate input dev\n"); | ||
| 82 | ret = -ENOMEM; | ||
| 83 | goto out; | ||
| 84 | } | ||
| 85 | |||
| 86 | info->idev->name = "88pm860x_on"; | ||
| 87 | info->idev->phys = "88pm860x_on/input0"; | ||
| 88 | info->idev->id.bustype = BUS_I2C; | ||
| 89 | info->idev->dev.parent = &pdev->dev; | ||
| 90 | info->irq = irq; | ||
| 91 | info->idev->evbit[0] = BIT_MASK(EV_KEY); | ||
| 92 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | ||
| 93 | |||
| 94 | ret = input_register_device(info->idev); | ||
| 95 | if (ret) { | ||
| 96 | dev_err(chip->dev, "Can't register input device: %d\n", ret); | ||
| 97 | goto out_reg; | ||
| 98 | } | ||
| 99 | |||
| 100 | ret = request_threaded_irq(info->irq, NULL, pm860x_onkey_handler, | ||
| 101 | IRQF_ONESHOT, "onkey", info); | ||
| 102 | if (ret < 0) { | ||
| 103 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
| 104 | info->irq, ret); | ||
| 105 | goto out_irq; | ||
| 106 | } | ||
| 107 | |||
| 108 | platform_set_drvdata(pdev, info); | ||
| 109 | return 0; | ||
| 110 | |||
| 111 | out_irq: | ||
| 112 | input_unregister_device(info->idev); | ||
| 113 | kfree(info); | ||
| 114 | return ret; | ||
| 115 | |||
| 116 | out_reg: | ||
| 117 | input_free_device(info->idev); | ||
| 118 | out: | ||
| 119 | kfree(info); | ||
| 120 | return ret; | ||
| 121 | } | ||
| 122 | |||
| 123 | static int __devexit pm860x_onkey_remove(struct platform_device *pdev) | ||
| 124 | { | ||
| 125 | struct pm860x_onkey_info *info = platform_get_drvdata(pdev); | ||
| 126 | |||
| 127 | free_irq(info->irq, info); | ||
| 128 | input_unregister_device(info->idev); | ||
| 129 | kfree(info); | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static struct platform_driver pm860x_onkey_driver = { | ||
| 134 | .driver = { | ||
| 135 | .name = "88pm860x-onkey", | ||
| 136 | .owner = THIS_MODULE, | ||
| 137 | }, | ||
| 138 | .probe = pm860x_onkey_probe, | ||
| 139 | .remove = __devexit_p(pm860x_onkey_remove), | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __init pm860x_onkey_init(void) | ||
| 143 | { | ||
| 144 | return platform_driver_register(&pm860x_onkey_driver); | ||
| 145 | } | ||
| 146 | module_init(pm860x_onkey_init); | ||
| 147 | |||
| 148 | static void __exit pm860x_onkey_exit(void) | ||
| 149 | { | ||
| 150 | platform_driver_unregister(&pm860x_onkey_driver); | ||
| 151 | } | ||
| 152 | module_exit(pm860x_onkey_exit); | ||
| 153 | |||
| 154 | MODULE_DESCRIPTION("Marvell 88PM860x ONKEY driver"); | ||
| 155 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
| 156 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index a9bb2544b2de..23140a3bb8e0 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
| @@ -12,6 +12,16 @@ menuconfig INPUT_MISC | |||
| 12 | 12 | ||
| 13 | if INPUT_MISC | 13 | if INPUT_MISC |
| 14 | 14 | ||
| 15 | config INPUT_88PM860X_ONKEY | ||
| 16 | tristate "88PM860x ONKEY support" | ||
| 17 | depends on MFD_88PM860X | ||
| 18 | help | ||
| 19 | Support the ONKEY of Marvell 88PM860x PMICs as an input device | ||
| 20 | reporting power button status. | ||
| 21 | |||
| 22 | To compile this driver as a module, choose M here: the module | ||
| 23 | will be called 88pm860x_onkey. | ||
| 24 | |||
| 15 | config INPUT_PCSPKR | 25 | config INPUT_PCSPKR |
| 16 | tristate "PC Speaker support" | 26 | tristate "PC Speaker support" |
| 17 | depends on PCSPKR_PLATFORM | 27 | depends on PCSPKR_PLATFORM |
| @@ -80,6 +90,7 @@ config INPUT_WISTRON_BTNS | |||
| 80 | tristate "x86 Wistron laptop button interface" | 90 | tristate "x86 Wistron laptop button interface" |
| 81 | depends on X86 && !X86_64 | 91 | depends on X86 && !X86_64 |
| 82 | select INPUT_POLLDEV | 92 | select INPUT_POLLDEV |
| 93 | select INPUT_SPARSEKMAP | ||
| 83 | select NEW_LEDS | 94 | select NEW_LEDS |
| 84 | select LEDS_CLASS | 95 | select LEDS_CLASS |
| 85 | select CHECK_SIGNATURE | 96 | select CHECK_SIGNATURE |
| @@ -203,6 +214,17 @@ config INPUT_TWL4030_PWRBUTTON | |||
| 203 | To compile this driver as a module, choose M here. The module will | 214 | To compile this driver as a module, choose M here. The module will |
| 204 | be called twl4030_pwrbutton. | 215 | be called twl4030_pwrbutton. |
| 205 | 216 | ||
| 217 | config INPUT_TWL4030_VIBRA | ||
| 218 | tristate "Support for TWL4030 Vibrator" | ||
| 219 | depends on TWL4030_CORE | ||
| 220 | select TWL4030_CODEC | ||
| 221 | select INPUT_FF_MEMLESS | ||
| 222 | help | ||
| 223 | This option enables support for TWL4030 Vibrator Driver. | ||
| 224 | |||
| 225 | To compile this driver as a module, choose M here. The module will | ||
| 226 | be called twl4030_vibra. | ||
| 227 | |||
| 206 | config INPUT_UINPUT | 228 | config INPUT_UINPUT |
| 207 | tristate "User level driver support" | 229 | tristate "User level driver support" |
| 208 | help | 230 | help |
| @@ -281,6 +303,7 @@ config INPUT_RB532_BUTTON | |||
| 281 | config INPUT_DM355EVM | 303 | config INPUT_DM355EVM |
| 282 | tristate "TI DaVinci DM355 EVM Keypad and IR Remote" | 304 | tristate "TI DaVinci DM355 EVM Keypad and IR Remote" |
| 283 | depends on MFD_DM355EVM_MSP | 305 | depends on MFD_DM355EVM_MSP |
| 306 | select INPUT_SPARSEKMAP | ||
| 284 | help | 307 | help |
| 285 | Supports the pushbuttons and IR remote used with | 308 | Supports the pushbuttons and IR remote used with |
| 286 | the DM355 EVM board. | 309 | the DM355 EVM board. |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index a8b84854fb7b..7e95a5d474dc 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_INPUT_88PM860X_ONKEY) += 88pm860x_onkey.o | ||
| 7 | obj-$(CONFIG_INPUT_APANEL) += apanel.o | 8 | obj-$(CONFIG_INPUT_APANEL) += apanel.o |
| 8 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o | 9 | obj-$(CONFIG_INPUT_ATI_REMOTE) += ati_remote.o |
| 9 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o | 10 | obj-$(CONFIG_INPUT_ATI_REMOTE2) += ati_remote2.o |
| @@ -25,6 +26,7 @@ obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o | |||
| 25 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o | 26 | obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o |
| 26 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o | 27 | obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o |
| 27 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o | 28 | obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o |
| 29 | obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o | ||
| 28 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o | 30 | obj-$(CONFIG_INPUT_UINPUT) += uinput.o |
| 29 | obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o | 31 | obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o |
| 30 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o | 32 | obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o |
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index 71b82434264d..a8d2b8db4e35 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c | |||
| @@ -149,7 +149,7 @@ static void apanel_shutdown(struct i2c_client *client) | |||
| 149 | apanel_remove(client); | 149 | apanel_remove(client); |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static struct i2c_device_id apanel_id[] = { | 152 | static const struct i2c_device_id apanel_id[] = { |
| 153 | { "fujitsu_apanel", 0 }, | 153 | { "fujitsu_apanel", 0 }, |
| 154 | { } | 154 | { } |
| 155 | }; | 155 | }; |
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index e290fde35e74..614b65d78fe9 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c | |||
| @@ -766,7 +766,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
| 766 | ati_remote->interface = interface; | 766 | ati_remote->interface = interface; |
| 767 | 767 | ||
| 768 | usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); | 768 | usb_make_path(udev, ati_remote->phys, sizeof(ati_remote->phys)); |
| 769 | strlcpy(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); | 769 | strlcat(ati_remote->phys, "/input0", sizeof(ati_remote->phys)); |
| 770 | 770 | ||
| 771 | if (udev->manufacturer) | 771 | if (udev->manufacturer) |
| 772 | strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); | 772 | strlcpy(ati_remote->name, udev->manufacturer, sizeof(ati_remote->name)); |
diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0501f0e65157..2124b99378bb 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/usb/input.h> | 12 | #include <linux/usb/input.h> |
| 13 | #include <linux/slab.h> | ||
| 13 | 14 | ||
| 14 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" | 15 | #define DRIVER_DESC "ATI/Philips USB RF remote driver" |
| 15 | #define DRIVER_VERSION "0.3" | 16 | #define DRIVER_VERSION "0.3" |
| @@ -474,10 +475,11 @@ static void ati_remote2_complete_key(struct urb *urb) | |||
| 474 | } | 475 | } |
| 475 | 476 | ||
| 476 | static int ati_remote2_getkeycode(struct input_dev *idev, | 477 | static int ati_remote2_getkeycode(struct input_dev *idev, |
| 477 | int scancode, int *keycode) | 478 | unsigned int scancode, unsigned int *keycode) |
| 478 | { | 479 | { |
| 479 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | 480 | struct ati_remote2 *ar2 = input_get_drvdata(idev); |
| 480 | int index, mode; | 481 | unsigned int mode; |
| 482 | int index; | ||
| 481 | 483 | ||
| 482 | mode = scancode >> 8; | 484 | mode = scancode >> 8; |
| 483 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) | 485 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
| @@ -491,10 +493,12 @@ static int ati_remote2_getkeycode(struct input_dev *idev, | |||
| 491 | return 0; | 493 | return 0; |
| 492 | } | 494 | } |
| 493 | 495 | ||
| 494 | static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) | 496 | static int ati_remote2_setkeycode(struct input_dev *idev, |
| 497 | unsigned int scancode, unsigned int keycode) | ||
| 495 | { | 498 | { |
| 496 | struct ati_remote2 *ar2 = input_get_drvdata(idev); | 499 | struct ati_remote2 *ar2 = input_get_drvdata(idev); |
| 497 | int index, mode, old_keycode; | 500 | unsigned int mode, old_keycode; |
| 501 | int index; | ||
| 498 | 502 | ||
| 499 | mode = scancode >> 8; | 503 | mode = scancode >> 8; |
| 500 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) | 504 | if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) |
| @@ -504,9 +508,6 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc | |||
| 504 | if (index < 0) | 508 | if (index < 0) |
| 505 | return -EINVAL; | 509 | return -EINVAL; |
| 506 | 510 | ||
| 507 | if (keycode < KEY_RESERVED || keycode > KEY_MAX) | ||
| 508 | return -EINVAL; | ||
| 509 | |||
| 510 | old_keycode = ar2->keycode[mode][index]; | 511 | old_keycode = ar2->keycode[mode][index]; |
| 511 | ar2->keycode[mode][index] = keycode; | 512 | ar2->keycode[mode][index] = keycode; |
| 512 | __set_bit(keycode, idev->keybit); | 513 | __set_bit(keycode, idev->keybit); |
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c index 1b871917340a..dfaa9a045ed8 100644 --- a/drivers/input/misc/atlas_btns.c +++ b/drivers/input/misc/atlas_btns.c | |||
| @@ -47,7 +47,7 @@ static acpi_status acpi_atlas_button_setup(acpi_handle region_handle, | |||
| 47 | 47 | ||
| 48 | static acpi_status acpi_atlas_button_handler(u32 function, | 48 | static acpi_status acpi_atlas_button_handler(u32 function, |
| 49 | acpi_physical_address address, | 49 | acpi_physical_address address, |
| 50 | u32 bit_width, acpi_integer *value, | 50 | u32 bit_width, u64 *value, |
| 51 | void *handler_context, void *region_context) | 51 | void *handler_context, void *region_context) |
| 52 | { | 52 | { |
| 53 | acpi_status status; | 53 | acpi_status status; |
diff --git a/drivers/input/misc/bfin_rotary.c b/drivers/input/misc/bfin_rotary.c index 690f3fafa03b..4f72bdd69410 100644 --- a/drivers/input/misc/bfin_rotary.c +++ b/drivers/input/misc/bfin_rotary.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/pm.h> | 13 | #include <linux/pm.h> |
| 14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
| 15 | #include <linux/input.h> | 15 | #include <linux/input.h> |
| 16 | #include <linux/slab.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/portmux.h> | 18 | #include <asm/portmux.h> |
| 18 | #include <asm/bfin_rotary.h> | 19 | #include <asm/bfin_rotary.h> |
| @@ -247,7 +248,7 @@ static int bfin_rotary_resume(struct device *dev) | |||
| 247 | return 0; | 248 | return 0; |
| 248 | } | 249 | } |
| 249 | 250 | ||
| 250 | static struct dev_pm_ops bfin_rotary_pm_ops = { | 251 | static const struct dev_pm_ops bfin_rotary_pm_ops = { |
| 251 | .suspend = bfin_rotary_suspend, | 252 | .suspend = bfin_rotary_suspend, |
| 252 | .resume = bfin_rotary_resume, | 253 | .resume = bfin_rotary_resume, |
| 253 | }; | 254 | }; |
diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index ee73d7219c92..fd8407a29631 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | #include <linux/slab.h> | ||
| 25 | 26 | ||
| 26 | #define BUTTONS_POLL_INTERVAL 30 /* msec */ | 27 | #define BUTTONS_POLL_INTERVAL 30 /* msec */ |
| 27 | #define BUTTONS_COUNT_THRESHOLD 3 | 28 | #define BUTTONS_COUNT_THRESHOLD 3 |
diff --git a/drivers/input/misc/dm355evm_keys.c b/drivers/input/misc/dm355evm_keys.c index f2b67dc81d80..19af682c24fb 100644 --- a/drivers/input/misc/dm355evm_keys.c +++ b/drivers/input/misc/dm355evm_keys.c | |||
| @@ -10,7 +10,9 @@ | |||
| 10 | */ | 10 | */ |
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
| 13 | #include <linux/slab.h> | ||
| 13 | #include <linux/input.h> | 14 | #include <linux/input.h> |
| 15 | #include <linux/input/sparse-keymap.h> | ||
| 14 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 15 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 16 | 18 | ||
| @@ -33,12 +35,8 @@ struct dm355evm_keys { | |||
| 33 | int irq; | 35 | int irq; |
| 34 | }; | 36 | }; |
| 35 | 37 | ||
| 36 | /* These initial keycodes can be remapped by dm355evm_setkeycode(). */ | 38 | /* These initial keycodes can be remapped */ |
| 37 | static struct { | 39 | static const struct key_entry dm355evm_keys[] = { |
| 38 | u16 event; | ||
| 39 | u16 keycode; | ||
| 40 | } dm355evm_keys[] = { | ||
| 41 | |||
| 42 | /* | 40 | /* |
| 43 | * Pushbuttons on the EVM board ... note that the labels for these | 41 | * Pushbuttons on the EVM board ... note that the labels for these |
| 44 | * are SW10/SW11/etc on the PC board. The left/right orientation | 42 | * are SW10/SW11/etc on the PC board. The left/right orientation |
| @@ -47,11 +45,11 @@ static struct { | |||
| 47 | * is to the right. (That is, rotate the board counter-clockwise | 45 | * is to the right. (That is, rotate the board counter-clockwise |
| 48 | * by 90 degrees from the SW10/etc and "DM355 EVM" labels.) | 46 | * by 90 degrees from the SW10/etc and "DM355 EVM" labels.) |
| 49 | */ | 47 | */ |
| 50 | { 0x00d8, KEY_OK, }, /* SW12 */ | 48 | { KE_KEY, 0x00d8, { KEY_OK } }, /* SW12 */ |
| 51 | { 0x00b8, KEY_UP, }, /* SW13 */ | 49 | { KE_KEY, 0x00b8, { KEY_UP } }, /* SW13 */ |
| 52 | { 0x00e8, KEY_DOWN, }, /* SW11 */ | 50 | { KE_KEY, 0x00e8, { KEY_DOWN } }, /* SW11 */ |
| 53 | { 0x0078, KEY_LEFT, }, /* SW14 */ | 51 | { KE_KEY, 0x0078, { KEY_LEFT } }, /* SW14 */ |
| 54 | { 0x00f0, KEY_RIGHT, }, /* SW10 */ | 52 | { KE_KEY, 0x00f0, { KEY_RIGHT } }, /* SW10 */ |
| 55 | 53 | ||
| 56 | /* | 54 | /* |
| 57 | * IR buttons ... codes assigned to match the universal remote | 55 | * IR buttons ... codes assigned to match the universal remote |
| @@ -65,35 +63,35 @@ static struct { | |||
| 65 | * RC5 codes are 14 bits, with two start bits (0x3 prefix) | 63 | * RC5 codes are 14 bits, with two start bits (0x3 prefix) |
| 66 | * and a toggle bit (masked out below). | 64 | * and a toggle bit (masked out below). |
| 67 | */ | 65 | */ |
| 68 | { 0x300c, KEY_POWER, }, /* NOTE: docs omit this */ | 66 | { KE_KEY, 0x300c, { KEY_POWER } }, /* NOTE: docs omit this */ |
| 69 | { 0x3000, KEY_NUMERIC_0, }, | 67 | { KE_KEY, 0x3000, { KEY_NUMERIC_0 } }, |
| 70 | { 0x3001, KEY_NUMERIC_1, }, | 68 | { KE_KEY, 0x3001, { KEY_NUMERIC_1 } }, |
| 71 | { 0x3002, KEY_NUMERIC_2, }, | 69 | { KE_KEY, 0x3002, { KEY_NUMERIC_2 } }, |
| 72 | { 0x3003, KEY_NUMERIC_3, }, | 70 | { KE_KEY, 0x3003, { KEY_NUMERIC_3 } }, |
| 73 | { 0x3004, KEY_NUMERIC_4, }, | 71 | { KE_KEY, 0x3004, { KEY_NUMERIC_4 } }, |
| 74 | { 0x3005, KEY_NUMERIC_5, }, | 72 | { KE_KEY, 0x3005, { KEY_NUMERIC_5 } }, |
| 75 | { 0x3006, KEY_NUMERIC_6, }, | 73 | { KE_KEY, 0x3006, { KEY_NUMERIC_6 } }, |
| 76 | { 0x3007, KEY_NUMERIC_7, }, | 74 | { KE_KEY, 0x3007, { KEY_NUMERIC_7 } }, |
| 77 | { 0x3008, KEY_NUMERIC_8, }, | 75 | { KE_KEY, 0x3008, { KEY_NUMERIC_8 } }, |
| 78 | { 0x3009, KEY_NUMERIC_9, }, | 76 | { KE_KEY, 0x3009, { KEY_NUMERIC_9 } }, |
| 79 | { 0x3022, KEY_ENTER, }, | 77 | { KE_KEY, 0x3022, { KEY_ENTER } }, |
| 80 | { 0x30ec, KEY_MODE, }, /* "tv/vcr/..." */ | 78 | { KE_KEY, 0x30ec, { KEY_MODE } }, /* "tv/vcr/..." */ |
| 81 | { 0x300f, KEY_SELECT, }, /* "info" */ | 79 | { KE_KEY, 0x300f, { KEY_SELECT } }, /* "info" */ |
| 82 | { 0x3020, KEY_CHANNELUP, }, /* "up" */ | 80 | { KE_KEY, 0x3020, { KEY_CHANNELUP } }, /* "up" */ |
| 83 | { 0x302e, KEY_MENU, }, /* "in/out" */ | 81 | { KE_KEY, 0x302e, { KEY_MENU } }, /* "in/out" */ |
| 84 | { 0x3011, KEY_VOLUMEDOWN, }, /* "left" */ | 82 | { KE_KEY, 0x3011, { KEY_VOLUMEDOWN } }, /* "left" */ |
| 85 | { 0x300d, KEY_MUTE, }, /* "ok" */ | 83 | { KE_KEY, 0x300d, { KEY_MUTE } }, /* "ok" */ |
| 86 | { 0x3010, KEY_VOLUMEUP, }, /* "right" */ | 84 | { KE_KEY, 0x3010, { KEY_VOLUMEUP } }, /* "right" */ |
| 87 | { 0x301e, KEY_SUBTITLE, }, /* "cc" */ | 85 | { KE_KEY, 0x301e, { KEY_SUBTITLE } }, /* "cc" */ |
| 88 | { 0x3021, KEY_CHANNELDOWN, }, /* "down" */ | 86 | { KE_KEY, 0x3021, { KEY_CHANNELDOWN } },/* "down" */ |
| 89 | { 0x3022, KEY_PREVIOUS, }, | 87 | { KE_KEY, 0x3022, { KEY_PREVIOUS } }, |
| 90 | { 0x3026, KEY_SLEEP, }, | 88 | { KE_KEY, 0x3026, { KEY_SLEEP } }, |
| 91 | { 0x3172, KEY_REWIND, }, /* NOTE: docs wrongly say 0x30ca */ | 89 | { KE_KEY, 0x3172, { KEY_REWIND } }, /* NOTE: docs wrongly say 0x30ca */ |
| 92 | { 0x3175, KEY_PLAY, }, | 90 | { KE_KEY, 0x3175, { KEY_PLAY } }, |
| 93 | { 0x3174, KEY_FASTFORWARD, }, | 91 | { KE_KEY, 0x3174, { KEY_FASTFORWARD } }, |
| 94 | { 0x3177, KEY_RECORD, }, | 92 | { KE_KEY, 0x3177, { KEY_RECORD } }, |
| 95 | { 0x3176, KEY_STOP, }, | 93 | { KE_KEY, 0x3176, { KEY_STOP } }, |
| 96 | { 0x3169, KEY_PAUSE, }, | 94 | { KE_KEY, 0x3169, { KEY_PAUSE } }, |
| 97 | }; | 95 | }; |
| 98 | 96 | ||
| 99 | /* | 97 | /* |
| @@ -105,19 +103,18 @@ static struct { | |||
| 105 | */ | 103 | */ |
| 106 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | 104 | static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) |
| 107 | { | 105 | { |
| 108 | struct dm355evm_keys *keys = _keys; | 106 | static u16 last_event; |
| 109 | int status; | 107 | struct dm355evm_keys *keys = _keys; |
| 108 | const struct key_entry *ke; | ||
| 109 | unsigned int keycode; | ||
| 110 | int status; | ||
| 111 | u16 event; | ||
| 110 | 112 | ||
| 111 | /* For simplicity we ignore INPUT_COUNT and just read | 113 | /* For simplicity we ignore INPUT_COUNT and just read |
| 112 | * events until we get the "queue empty" indicator. | 114 | * events until we get the "queue empty" indicator. |
| 113 | * Reading INPUT_LOW decrements the count. | 115 | * Reading INPUT_LOW decrements the count. |
| 114 | */ | 116 | */ |
| 115 | for (;;) { | 117 | for (;;) { |
| 116 | static u16 last_event; | ||
| 117 | u16 event; | ||
| 118 | int keycode; | ||
| 119 | int i; | ||
| 120 | |||
| 121 | status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH); | 118 | status = dm355evm_msp_read(DM355EVM_MSP_INPUT_HIGH); |
| 122 | if (status < 0) { | 119 | if (status < 0) { |
| 123 | dev_dbg(keys->dev, "input high err %d\n", | 120 | dev_dbg(keys->dev, "input high err %d\n", |
| @@ -156,14 +153,9 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | |||
| 156 | /* ignore the RC5 toggle bit */ | 153 | /* ignore the RC5 toggle bit */ |
| 157 | event &= ~0x0800; | 154 | event &= ~0x0800; |
| 158 | 155 | ||
| 159 | /* find the key, or leave it as unknown */ | 156 | /* find the key, or report it as unknown */ |
| 160 | keycode = KEY_UNKNOWN; | 157 | ke = sparse_keymap_entry_from_scancode(keys->input, event); |
| 161 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) { | 158 | keycode = ke ? ke->keycode : KEY_UNKNOWN; |
| 162 | if (dm355evm_keys[i].event != event) | ||
| 163 | continue; | ||
| 164 | keycode = dm355evm_keys[i].keycode; | ||
| 165 | break; | ||
| 166 | } | ||
| 167 | dev_dbg(keys->dev, | 159 | dev_dbg(keys->dev, |
| 168 | "input event 0x%04x--> keycode %d\n", | 160 | "input event 0x%04x--> keycode %d\n", |
| 169 | event, keycode); | 161 | event, keycode); |
| @@ -174,36 +166,8 @@ static irqreturn_t dm355evm_keys_irq(int irq, void *_keys) | |||
| 174 | input_report_key(keys->input, keycode, 0); | 166 | input_report_key(keys->input, keycode, 0); |
| 175 | input_sync(keys->input); | 167 | input_sync(keys->input); |
| 176 | } | 168 | } |
| 177 | return IRQ_HANDLED; | ||
| 178 | } | ||
| 179 | 169 | ||
| 180 | static int dm355evm_setkeycode(struct input_dev *dev, int index, int keycode) | 170 | return IRQ_HANDLED; |
| 181 | { | ||
| 182 | u16 old_keycode; | ||
| 183 | unsigned i; | ||
| 184 | |||
| 185 | if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys)) | ||
| 186 | return -EINVAL; | ||
| 187 | |||
| 188 | old_keycode = dm355evm_keys[index].keycode; | ||
| 189 | dm355evm_keys[index].keycode = keycode; | ||
| 190 | set_bit(keycode, dev->keybit); | ||
| 191 | |||
| 192 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) { | ||
| 193 | if (dm355evm_keys[index].keycode == old_keycode) | ||
| 194 | goto done; | ||
| 195 | } | ||
| 196 | clear_bit(old_keycode, dev->keybit); | ||
| 197 | done: | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int dm355evm_getkeycode(struct input_dev *dev, int index, int *keycode) | ||
| 202 | { | ||
| 203 | if (((unsigned)index) >= ARRAY_SIZE(dm355evm_keys)) | ||
| 204 | return -EINVAL; | ||
| 205 | |||
| 206 | return dm355evm_keys[index].keycode; | ||
| 207 | } | 171 | } |
| 208 | 172 | ||
| 209 | /*----------------------------------------------------------------------*/ | 173 | /*----------------------------------------------------------------------*/ |
| @@ -213,7 +177,6 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
| 213 | struct dm355evm_keys *keys; | 177 | struct dm355evm_keys *keys; |
| 214 | struct input_dev *input; | 178 | struct input_dev *input; |
| 215 | int status; | 179 | int status; |
| 216 | int i; | ||
| 217 | 180 | ||
| 218 | /* allocate instance struct and input dev */ | 181 | /* allocate instance struct and input dev */ |
| 219 | keys = kzalloc(sizeof *keys, GFP_KERNEL); | 182 | keys = kzalloc(sizeof *keys, GFP_KERNEL); |
| @@ -242,31 +205,30 @@ static int __devinit dm355evm_keys_probe(struct platform_device *pdev) | |||
| 242 | input->id.product = 0x0355; | 205 | input->id.product = 0x0355; |
| 243 | input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); | 206 | input->id.version = dm355evm_msp_read(DM355EVM_MSP_FIRMREV); |
| 244 | 207 | ||
| 245 | input->evbit[0] = BIT(EV_KEY); | 208 | status = sparse_keymap_setup(input, dm355evm_keys, NULL); |
| 246 | for (i = 0; i < ARRAY_SIZE(dm355evm_keys); i++) | 209 | if (status) |
| 247 | __set_bit(dm355evm_keys[i].keycode, input->keybit); | 210 | goto fail1; |
| 248 | |||
| 249 | input->setkeycode = dm355evm_setkeycode; | ||
| 250 | input->getkeycode = dm355evm_getkeycode; | ||
| 251 | 211 | ||
| 252 | /* REVISIT: flush the event queue? */ | 212 | /* REVISIT: flush the event queue? */ |
| 253 | 213 | ||
| 254 | status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq, | 214 | status = request_threaded_irq(keys->irq, NULL, dm355evm_keys_irq, |
| 255 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys); | 215 | IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), keys); |
| 256 | if (status < 0) | 216 | if (status < 0) |
| 257 | goto fail1; | 217 | goto fail2; |
| 258 | 218 | ||
| 259 | /* register */ | 219 | /* register */ |
| 260 | status = input_register_device(input); | 220 | status = input_register_device(input); |
| 261 | if (status < 0) | 221 | if (status < 0) |
| 262 | goto fail2; | 222 | goto fail3; |
| 263 | 223 | ||
| 264 | platform_set_drvdata(pdev, keys); | 224 | platform_set_drvdata(pdev, keys); |
| 265 | 225 | ||
| 266 | return 0; | 226 | return 0; |
| 267 | 227 | ||
| 268 | fail2: | 228 | fail3: |
| 269 | free_irq(keys->irq, keys); | 229 | free_irq(keys->irq, keys); |
| 230 | fail2: | ||
| 231 | sparse_keymap_free(input); | ||
| 270 | fail1: | 232 | fail1: |
| 271 | input_free_device(input); | 233 | input_free_device(input); |
| 272 | kfree(keys); | 234 | kfree(keys); |
| @@ -280,6 +242,7 @@ static int __devexit dm355evm_keys_remove(struct platform_device *pdev) | |||
| 280 | struct dm355evm_keys *keys = platform_get_drvdata(pdev); | 242 | struct dm355evm_keys *keys = platform_get_drvdata(pdev); |
| 281 | 243 | ||
| 282 | free_irq(keys->irq, keys); | 244 | free_irq(keys->irq, keys); |
| 245 | sparse_keymap_free(keys->input); | ||
| 283 | input_unregister_device(keys->input); | 246 | input_unregister_device(keys->input); |
| 284 | kfree(keys); | 247 | kfree(keys); |
| 285 | 248 | ||
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c index ea821b546969..ad730e15afc0 100644 --- a/drivers/input/misc/hp_sdc_rtc.c +++ b/drivers/input/misc/hp_sdc_rtc.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | 35 | ||
| 36 | #include <linux/hp_sdc.h> | 36 | #include <linux/hp_sdc.h> |
| 37 | #include <linux/errno.h> | 37 | #include <linux/errno.h> |
| 38 | #include <linux/smp_lock.h> | ||
| 39 | #include <linux/types.h> | 38 | #include <linux/types.h> |
| 40 | #include <linux/init.h> | 39 | #include <linux/init.h> |
| 41 | #include <linux/module.h> | 40 | #include <linux/module.h> |
| @@ -409,7 +408,6 @@ static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait) | |||
| 409 | 408 | ||
| 410 | static int hp_sdc_rtc_open(struct inode *inode, struct file *file) | 409 | static int hp_sdc_rtc_open(struct inode *inode, struct file *file) |
| 411 | { | 410 | { |
| 412 | cycle_kernel_lock(); | ||
| 413 | return 0; | 411 | return 0; |
| 414 | } | 412 | } |
| 415 | 413 | ||
diff --git a/drivers/input/misc/pcap_keys.c b/drivers/input/misc/pcap_keys.c index 7ea969347ca9..99335c286250 100644 --- a/drivers/input/misc/pcap_keys.c +++ b/drivers/input/misc/pcap_keys.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
| 18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 19 | #include <linux/mfd/ezx-pcap.h> | 19 | #include <linux/mfd/ezx-pcap.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | 21 | ||
| 21 | struct pcap_keys { | 22 | struct pcap_keys { |
| 22 | struct pcap_chip *pcap; | 23 | struct pcap_chip *pcap; |
diff --git a/drivers/input/misc/pcf50633-input.c b/drivers/input/misc/pcf50633-input.c index 039dcb00ebd9..95562735728d 100644 --- a/drivers/input/misc/pcf50633-input.c +++ b/drivers/input/misc/pcf50633-input.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
| 21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
| 23 | #include <linux/slab.h> | ||
| 23 | 24 | ||
| 24 | #include <linux/mfd/pcf50633/core.h> | 25 | #include <linux/mfd/pcf50633/core.h> |
| 25 | 26 | ||
| @@ -55,7 +56,6 @@ pcf50633_input_irq(int irq, void *data) | |||
| 55 | static int __devinit pcf50633_input_probe(struct platform_device *pdev) | 56 | static int __devinit pcf50633_input_probe(struct platform_device *pdev) |
| 56 | { | 57 | { |
| 57 | struct pcf50633_input *input; | 58 | struct pcf50633_input *input; |
| 58 | struct pcf50633_subdev_pdata *pdata = pdev->dev.platform_data; | ||
| 59 | struct input_dev *input_dev; | 59 | struct input_dev *input_dev; |
| 60 | int ret; | 60 | int ret; |
| 61 | 61 | ||
| @@ -71,7 +71,7 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | platform_set_drvdata(pdev, input); | 73 | platform_set_drvdata(pdev, input); |
| 74 | input->pcf = pdata->pcf; | 74 | input->pcf = dev_to_pcf50633(pdev->dev.parent); |
| 75 | input->input_dev = input_dev; | 75 | input->input_dev = input_dev; |
| 76 | 76 | ||
| 77 | input_dev->name = "PCF50633 PMU events"; | 77 | input_dev->name = "PCF50633 PMU events"; |
| @@ -85,9 +85,9 @@ static int __devinit pcf50633_input_probe(struct platform_device *pdev) | |||
| 85 | kfree(input); | 85 | kfree(input); |
| 86 | return ret; | 86 | return ret; |
| 87 | } | 87 | } |
| 88 | pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYR, | 88 | pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYR, |
| 89 | pcf50633_input_irq, input); | 89 | pcf50633_input_irq, input); |
| 90 | pcf50633_register_irq(pdata->pcf, PCF50633_IRQ_ONKEYF, | 90 | pcf50633_register_irq(input->pcf, PCF50633_IRQ_ONKEYF, |
| 91 | pcf50633_input_irq, input); | 91 | pcf50633_input_irq, input); |
| 92 | 92 | ||
| 93 | return 0; | 93 | return 0; |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index 21cb755a54fb..ea4e1fd12651 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -127,7 +127,7 @@ static void pcspkr_shutdown(struct platform_device *dev) | |||
| 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); | 127 | pcspkr_event(NULL, EV_SND, SND_BELL, 0); |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static struct dev_pm_ops pcspkr_pm_ops = { | 130 | static const struct dev_pm_ops pcspkr_pm_ops = { |
| 131 | .suspend = pcspkr_suspend, | 131 | .suspend = pcspkr_suspend, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
diff --git a/drivers/input/misc/powermate.c b/drivers/input/misc/powermate.c index a53c4885fbad..668913d12044 100644 --- a/drivers/input/misc/powermate.c +++ b/drivers/input/misc/powermate.c | |||
| @@ -338,7 +338,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
| 338 | pm->input = input_dev; | 338 | pm->input = input_dev; |
| 339 | 339 | ||
| 340 | usb_make_path(udev, pm->phys, sizeof(pm->phys)); | 340 | usb_make_path(udev, pm->phys, sizeof(pm->phys)); |
| 341 | strlcpy(pm->phys, "/input0", sizeof(pm->phys)); | 341 | strlcat(pm->phys, "/input0", sizeof(pm->phys)); |
| 342 | 342 | ||
| 343 | spin_lock_init(&pm->lock); | 343 | spin_lock_init(&pm->lock); |
| 344 | 344 | ||
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c index 3b9f588fc747..1f8e0108962e 100644 --- a/drivers/input/misc/rotary_encoder.c +++ b/drivers/input/misc/rotary_encoder.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 23 | #include <linux/gpio.h> | 23 | #include <linux/gpio.h> |
| 24 | #include <linux/rotary_encoder.h> | 24 | #include <linux/rotary_encoder.h> |
| 25 | #include <linux/slab.h> | ||
| 25 | 26 | ||
| 26 | #define DRV_NAME "rotary-encoder" | 27 | #define DRV_NAME "rotary-encoder" |
| 27 | 28 | ||
| @@ -152,6 +153,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
| 152 | goto exit_unregister_input; | 153 | goto exit_unregister_input; |
| 153 | } | 154 | } |
| 154 | 155 | ||
| 156 | err = gpio_direction_input(pdata->gpio_a); | ||
| 157 | if (err) { | ||
| 158 | dev_err(&pdev->dev, "unable to set GPIO %d for input\n", | ||
| 159 | pdata->gpio_a); | ||
| 160 | goto exit_unregister_input; | ||
| 161 | } | ||
| 162 | |||
| 155 | err = gpio_request(pdata->gpio_b, DRV_NAME); | 163 | err = gpio_request(pdata->gpio_b, DRV_NAME); |
| 156 | if (err) { | 164 | if (err) { |
| 157 | dev_err(&pdev->dev, "unable to request GPIO %d\n", | 165 | dev_err(&pdev->dev, "unable to request GPIO %d\n", |
| @@ -159,6 +167,13 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) | |||
| 159 | goto exit_free_gpio_a; | 167 | goto exit_free_gpio_a; |
| 160 | } | 168 | } |
| 161 | 169 | ||
| 170 | err = gpio_direction_input(pdata->gpio_b); | ||
| 171 | if (err) { | ||
| 172 | dev_err(&pdev->dev, "unable to set GPIO %d for input\n", | ||
| 173 | pdata->gpio_b); | ||
| 174 | goto exit_free_gpio_a; | ||
| 175 | } | ||
| 176 | |||
| 162 | /* request the IRQs */ | 177 | /* request the IRQs */ |
| 163 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, | 178 | err = request_irq(encoder->irq_a, &rotary_encoder_irq, |
| 164 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, | 179 | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, |
diff --git a/drivers/input/misc/sgi_btns.c b/drivers/input/misc/sgi_btns.c index be3a15f5b25d..1a80c0dab83b 100644 --- a/drivers/input/misc/sgi_btns.c +++ b/drivers/input/misc/sgi_btns.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
| 25 | #include <linux/slab.h> | ||
| 25 | 26 | ||
| 26 | #ifdef CONFIG_SGI_IP22 | 27 | #ifdef CONFIG_SGI_IP22 |
| 27 | #include <asm/sgi/ioc.h> | 28 | #include <asm/sgi/ioc.h> |
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index b064419b90a2..0d45422f8095 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
| 10 | #include <linux/input.h> | 10 | #include <linux/input.h> |
| 11 | #include <linux/of_device.h> | 11 | #include <linux/of_device.h> |
| 12 | #include <linux/slab.h> | ||
| 12 | 13 | ||
| 13 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| 14 | 15 | ||
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c index f5fc9974a111..e9069b87fde2 100644 --- a/drivers/input/misc/twl4030-pwrbutton.c +++ b/drivers/input/misc/twl4030-pwrbutton.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | #include <linux/input.h> | 27 | #include <linux/input.h> |
| 28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
| 29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
| 30 | #include <linux/i2c/twl4030.h> | 30 | #include <linux/i2c/twl.h> |
| 31 | 31 | ||
| 32 | #define PWR_PWRON_IRQ (1 << 0) | 32 | #define PWR_PWRON_IRQ (1 << 0) |
| 33 | 33 | ||
| @@ -39,18 +39,8 @@ static irqreturn_t powerbutton_irq(int irq, void *_pwr) | |||
| 39 | int err; | 39 | int err; |
| 40 | u8 value; | 40 | u8 value; |
| 41 | 41 | ||
| 42 | #ifdef CONFIG_LOCKDEP | 42 | err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, |
| 43 | /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which | 43 | STS_HW_CONDITIONS); |
| 44 | * we don't want and can't tolerate since this is a threaded | ||
| 45 | * IRQ and can sleep due to the i2c reads it has to issue. | ||
| 46 | * Although it might be friendlier not to borrow this thread | ||
| 47 | * context... | ||
| 48 | */ | ||
| 49 | local_irq_enable(); | ||
| 50 | #endif | ||
| 51 | |||
| 52 | err = twl4030_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &value, | ||
| 53 | STS_HW_CONDITIONS); | ||
| 54 | if (!err) { | 44 | if (!err) { |
| 55 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); | 45 | input_report_key(pwr, KEY_POWER, value & PWR_PWRON_IRQ); |
| 56 | input_sync(pwr); | 46 | input_sync(pwr); |
| @@ -80,7 +70,7 @@ static int __devinit twl4030_pwrbutton_probe(struct platform_device *pdev) | |||
| 80 | pwr->phys = "twl4030_pwrbutton/input0"; | 70 | pwr->phys = "twl4030_pwrbutton/input0"; |
| 81 | pwr->dev.parent = &pdev->dev; | 71 | pwr->dev.parent = &pdev->dev; |
| 82 | 72 | ||
| 83 | err = request_irq(irq, powerbutton_irq, | 73 | err = request_threaded_irq(irq, NULL, powerbutton_irq, |
| 84 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 74 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, |
| 85 | "twl4030_pwrbutton", pwr); | 75 | "twl4030_pwrbutton", pwr); |
| 86 | if (err < 0) { | 76 | if (err < 0) { |
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c new file mode 100644 index 000000000000..fee9eac8e04a --- /dev/null +++ b/drivers/input/misc/twl4030-vibra.c | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | /* | ||
| 2 | * twl4030-vibra.c - TWL4030 Vibrator driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008-2010 Nokia Corporation | ||
| 5 | * | ||
| 6 | * Written by Henrik Saari <henrik.saari@nokia.com> | ||
| 7 | * Updates by Felipe Balbi <felipe.balbi@nokia.com> | ||
| 8 | * Input by Jari Vanhala <ext-jari.vanhala@nokia.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 22 | * 02110-1301 USA | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/jiffies.h> | ||
| 28 | #include <linux/platform_device.h> | ||
| 29 | #include <linux/workqueue.h> | ||
| 30 | #include <linux/i2c/twl.h> | ||
| 31 | #include <linux/mfd/twl4030-codec.h> | ||
| 32 | #include <linux/input.h> | ||
| 33 | #include <linux/slab.h> | ||
| 34 | |||
| 35 | /* MODULE ID2 */ | ||
| 36 | #define LEDEN 0x00 | ||
| 37 | |||
| 38 | /* ForceFeedback */ | ||
| 39 | #define EFFECT_DIR_180_DEG 0x8000 /* range is 0 - 0xFFFF */ | ||
| 40 | |||
| 41 | struct vibra_info { | ||
| 42 | struct device *dev; | ||
| 43 | struct input_dev *input_dev; | ||
| 44 | |||
| 45 | struct workqueue_struct *workqueue; | ||
| 46 | struct work_struct play_work; | ||
| 47 | |||
| 48 | bool enabled; | ||
| 49 | int speed; | ||
| 50 | int direction; | ||
| 51 | |||
| 52 | bool coexist; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static void vibra_disable_leds(void) | ||
| 56 | { | ||
| 57 | u8 reg; | ||
| 58 | |||
| 59 | /* Disable LEDA & LEDB, cannot be used with vibra (PWM) */ | ||
| 60 | twl_i2c_read_u8(TWL4030_MODULE_LED, ®, LEDEN); | ||
| 61 | reg &= ~0x03; | ||
| 62 | twl_i2c_write_u8(TWL4030_MODULE_LED, LEDEN, reg); | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Powers H-Bridge and enables audio clk */ | ||
| 66 | static void vibra_enable(struct vibra_info *info) | ||
| 67 | { | ||
| 68 | u8 reg; | ||
| 69 | |||
| 70 | twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); | ||
| 71 | |||
| 72 | /* turn H-Bridge on */ | ||
| 73 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 74 | ®, TWL4030_REG_VIBRA_CTL); | ||
| 75 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 76 | (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); | ||
| 77 | |||
| 78 | twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); | ||
| 79 | |||
| 80 | info->enabled = true; | ||
| 81 | } | ||
| 82 | |||
| 83 | static void vibra_disable(struct vibra_info *info) | ||
| 84 | { | ||
| 85 | u8 reg; | ||
| 86 | |||
| 87 | /* Power down H-Bridge */ | ||
| 88 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 89 | ®, TWL4030_REG_VIBRA_CTL); | ||
| 90 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 91 | (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); | ||
| 92 | |||
| 93 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); | ||
| 94 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); | ||
| 95 | |||
| 96 | info->enabled = false; | ||
| 97 | } | ||
| 98 | |||
| 99 | static void vibra_play_work(struct work_struct *work) | ||
| 100 | { | ||
| 101 | struct vibra_info *info = container_of(work, | ||
| 102 | struct vibra_info, play_work); | ||
| 103 | int dir; | ||
| 104 | int pwm; | ||
| 105 | u8 reg; | ||
| 106 | |||
| 107 | dir = info->direction; | ||
| 108 | pwm = info->speed; | ||
| 109 | |||
| 110 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 111 | ®, TWL4030_REG_VIBRA_CTL); | ||
| 112 | if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { | ||
| 113 | |||
| 114 | if (!info->enabled) | ||
| 115 | vibra_enable(info); | ||
| 116 | |||
| 117 | /* set vibra rotation direction */ | ||
| 118 | twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 119 | ®, TWL4030_REG_VIBRA_CTL); | ||
| 120 | reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : | ||
| 121 | (reg & ~TWL4030_VIBRA_DIR); | ||
| 122 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 123 | reg, TWL4030_REG_VIBRA_CTL); | ||
| 124 | |||
| 125 | /* set PWM, 1 = max, 255 = min */ | ||
| 126 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | ||
| 127 | 256 - pwm, TWL4030_REG_VIBRA_SET); | ||
| 128 | } else { | ||
| 129 | if (info->enabled) | ||
| 130 | vibra_disable(info); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | /*** Input/ForceFeedback ***/ | ||
| 135 | |||
| 136 | static int vibra_play(struct input_dev *input, void *data, | ||
| 137 | struct ff_effect *effect) | ||
| 138 | { | ||
| 139 | struct vibra_info *info = input_get_drvdata(input); | ||
| 140 | |||
| 141 | info->speed = effect->u.rumble.strong_magnitude >> 8; | ||
| 142 | if (!info->speed) | ||
| 143 | info->speed = effect->u.rumble.weak_magnitude >> 9; | ||
| 144 | info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; | ||
| 145 | queue_work(info->workqueue, &info->play_work); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int twl4030_vibra_open(struct input_dev *input) | ||
| 150 | { | ||
| 151 | struct vibra_info *info = input_get_drvdata(input); | ||
| 152 | |||
| 153 | info->workqueue = create_singlethread_workqueue("vibra"); | ||
| 154 | if (info->workqueue == NULL) { | ||
| 155 | dev_err(&input->dev, "couldn't create workqueue\n"); | ||
| 156 | return -ENOMEM; | ||
| 157 | } | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | static void twl4030_vibra_close(struct input_dev *input) | ||
| 162 | { | ||
| 163 | struct vibra_info *info = input_get_drvdata(input); | ||
| 164 | |||
| 165 | cancel_work_sync(&info->play_work); | ||
| 166 | INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ | ||
| 167 | destroy_workqueue(info->workqueue); | ||
| 168 | info->workqueue = NULL; | ||
| 169 | |||
| 170 | if (info->enabled) | ||
| 171 | vibra_disable(info); | ||
| 172 | } | ||
| 173 | |||
| 174 | /*** Module ***/ | ||
| 175 | #if CONFIG_PM | ||
| 176 | static int twl4030_vibra_suspend(struct device *dev) | ||
| 177 | { | ||
| 178 | struct platform_device *pdev = to_platform_device(dev); | ||
| 179 | struct vibra_info *info = platform_get_drvdata(pdev); | ||
| 180 | |||
| 181 | if (info->enabled) | ||
| 182 | vibra_disable(info); | ||
| 183 | |||
| 184 | return 0; | ||
| 185 | } | ||
| 186 | |||
| 187 | static int twl4030_vibra_resume(struct device *dev) | ||
| 188 | { | ||
| 189 | vibra_disable_leds(); | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, | ||
| 194 | twl4030_vibra_suspend, twl4030_vibra_resume); | ||
| 195 | #endif | ||
| 196 | |||
| 197 | static int __devinit twl4030_vibra_probe(struct platform_device *pdev) | ||
| 198 | { | ||
| 199 | struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; | ||
| 200 | struct vibra_info *info; | ||
| 201 | int ret; | ||
| 202 | |||
| 203 | if (!pdata) { | ||
| 204 | dev_dbg(&pdev->dev, "platform_data not available\n"); | ||
| 205 | return -EINVAL; | ||
| 206 | } | ||
| 207 | |||
| 208 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
| 209 | if (!info) | ||
| 210 | return -ENOMEM; | ||
| 211 | |||
| 212 | info->dev = &pdev->dev; | ||
| 213 | info->coexist = pdata->coexist; | ||
| 214 | INIT_WORK(&info->play_work, vibra_play_work); | ||
| 215 | |||
| 216 | info->input_dev = input_allocate_device(); | ||
| 217 | if (info->input_dev == NULL) { | ||
| 218 | dev_err(&pdev->dev, "couldn't allocate input device\n"); | ||
| 219 | ret = -ENOMEM; | ||
| 220 | goto err_kzalloc; | ||
| 221 | } | ||
| 222 | |||
| 223 | input_set_drvdata(info->input_dev, info); | ||
| 224 | |||
| 225 | info->input_dev->name = "twl4030:vibrator"; | ||
| 226 | info->input_dev->id.version = 1; | ||
| 227 | info->input_dev->dev.parent = pdev->dev.parent; | ||
| 228 | info->input_dev->open = twl4030_vibra_open; | ||
| 229 | info->input_dev->close = twl4030_vibra_close; | ||
| 230 | __set_bit(FF_RUMBLE, info->input_dev->ffbit); | ||
| 231 | |||
| 232 | ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); | ||
| 233 | if (ret < 0) { | ||
| 234 | dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); | ||
| 235 | goto err_ialloc; | ||
| 236 | } | ||
| 237 | |||
| 238 | ret = input_register_device(info->input_dev); | ||
| 239 | if (ret < 0) { | ||
| 240 | dev_dbg(&pdev->dev, "couldn't register input device\n"); | ||
| 241 | goto err_iff; | ||
| 242 | } | ||
| 243 | |||
| 244 | vibra_disable_leds(); | ||
| 245 | |||
| 246 | platform_set_drvdata(pdev, info); | ||
| 247 | return 0; | ||
| 248 | |||
| 249 | err_iff: | ||
| 250 | input_ff_destroy(info->input_dev); | ||
| 251 | err_ialloc: | ||
| 252 | input_free_device(info->input_dev); | ||
| 253 | err_kzalloc: | ||
| 254 | kfree(info); | ||
| 255 | return ret; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int __devexit twl4030_vibra_remove(struct platform_device *pdev) | ||
| 259 | { | ||
| 260 | struct vibra_info *info = platform_get_drvdata(pdev); | ||
| 261 | |||
| 262 | /* this also free ff-memless and calls close if needed */ | ||
| 263 | input_unregister_device(info->input_dev); | ||
| 264 | kfree(info); | ||
| 265 | platform_set_drvdata(pdev, NULL); | ||
| 266 | |||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static struct platform_driver twl4030_vibra_driver = { | ||
| 271 | .probe = twl4030_vibra_probe, | ||
| 272 | .remove = __devexit_p(twl4030_vibra_remove), | ||
| 273 | .driver = { | ||
| 274 | .name = "twl4030_codec_vibra", | ||
| 275 | .owner = THIS_MODULE, | ||
| 276 | #ifdef CONFIG_PM | ||
| 277 | .pm = &twl4030_vibra_pm_ops, | ||
| 278 | #endif | ||
| 279 | }, | ||
| 280 | }; | ||
| 281 | |||
| 282 | static int __init twl4030_vibra_init(void) | ||
| 283 | { | ||
| 284 | return platform_driver_register(&twl4030_vibra_driver); | ||
| 285 | } | ||
| 286 | module_init(twl4030_vibra_init); | ||
| 287 | |||
| 288 | static void __exit twl4030_vibra_exit(void) | ||
| 289 | { | ||
| 290 | platform_driver_unregister(&twl4030_vibra_driver); | ||
| 291 | } | ||
| 292 | module_exit(twl4030_vibra_exit); | ||
| 293 | |||
| 294 | MODULE_ALIAS("platform:twl4030_codec_vibra"); | ||
| 295 | |||
| 296 | MODULE_DESCRIPTION("TWL4030 Vibra driver"); | ||
| 297 | MODULE_LICENSE("GPL"); | ||
| 298 | MODULE_AUTHOR("Nokia Corporation"); | ||
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index d3f57245420a..1477466076ad 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
| 35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
| 36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
| 37 | #include <linux/smp_lock.h> | ||
| 38 | #include <linux/fs.h> | 37 | #include <linux/fs.h> |
| 39 | #include <linux/miscdevice.h> | 38 | #include <linux/miscdevice.h> |
| 40 | #include <linux/uinput.h> | 39 | #include <linux/uinput.h> |
| @@ -284,7 +283,6 @@ static int uinput_open(struct inode *inode, struct file *file) | |||
| 284 | if (!newdev) | 283 | if (!newdev) |
| 285 | return -ENOMEM; | 284 | return -ENOMEM; |
| 286 | 285 | ||
| 287 | lock_kernel(); | ||
| 288 | mutex_init(&newdev->mutex); | 286 | mutex_init(&newdev->mutex); |
| 289 | spin_lock_init(&newdev->requests_lock); | 287 | spin_lock_init(&newdev->requests_lock); |
| 290 | init_waitqueue_head(&newdev->requests_waitq); | 288 | init_waitqueue_head(&newdev->requests_waitq); |
| @@ -292,7 +290,7 @@ static int uinput_open(struct inode *inode, struct file *file) | |||
| 292 | newdev->state = UIST_NEW_DEVICE; | 290 | newdev->state = UIST_NEW_DEVICE; |
| 293 | 291 | ||
| 294 | file->private_data = newdev; | 292 | file->private_data = newdev; |
| 295 | unlock_kernel(); | 293 | nonseekable_open(inode, file); |
| 296 | 294 | ||
| 297 | return 0; | 295 | return 0; |
| 298 | } | 296 | } |
diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index 33309fe44e20..64f1de7960c6 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <linux/io.h> | 56 | #include <linux/io.h> |
| 57 | #include <linux/bitrev.h> | 57 | #include <linux/bitrev.h> |
| 58 | #include <linux/bitops.h> | 58 | #include <linux/bitops.h> |
| 59 | #include <linux/slab.h> | ||
| 59 | 60 | ||
| 60 | #define DRVNAME "winbond-cir" | 61 | #define DRVNAME "winbond-cir" |
| 61 | 62 | ||
| @@ -385,26 +386,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) | |||
| 385 | } | 386 | } |
| 386 | 387 | ||
| 387 | static int | 388 | static int |
| 388 | wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 389 | wbcir_getkeycode(struct input_dev *dev, |
| 390 | unsigned int scancode, unsigned int *keycode) | ||
| 389 | { | 391 | { |
| 390 | struct wbcir_data *data = input_get_drvdata(dev); | 392 | struct wbcir_data *data = input_get_drvdata(dev); |
| 391 | 393 | ||
| 392 | *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); | 394 | *keycode = wbcir_do_getkeycode(data, scancode); |
| 393 | return 0; | 395 | return 0; |
| 394 | } | 396 | } |
| 395 | 397 | ||
| 396 | static int | 398 | static int |
| 397 | wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) | 399 | wbcir_setkeycode(struct input_dev *dev, |
| 400 | unsigned int scancode, unsigned int keycode) | ||
| 398 | { | 401 | { |
| 399 | struct wbcir_data *data = input_get_drvdata(dev); | 402 | struct wbcir_data *data = input_get_drvdata(dev); |
| 400 | struct wbcir_keyentry *keyentry; | 403 | struct wbcir_keyentry *keyentry; |
| 401 | struct wbcir_keyentry *new_keyentry; | 404 | struct wbcir_keyentry *new_keyentry; |
| 402 | unsigned long flags; | 405 | unsigned long flags; |
| 403 | unsigned int old_keycode = KEY_RESERVED; | 406 | unsigned int old_keycode = KEY_RESERVED; |
| 404 | u32 scancode = (u32)sscancode; | ||
| 405 | |||
| 406 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 407 | return -EINVAL; | ||
| 408 | 407 | ||
| 409 | new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); | 408 | new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); |
| 410 | if (!new_keyentry) | 409 | if (!new_keyentry) |
| @@ -538,6 +537,7 @@ wbcir_reset_irdata(struct wbcir_data *data) | |||
| 538 | data->irdata_count = 0; | 537 | data->irdata_count = 0; |
| 539 | data->irdata_off = 0; | 538 | data->irdata_off = 0; |
| 540 | data->irdata_error = 0; | 539 | data->irdata_error = 0; |
| 540 | data->idle_count = 0; | ||
| 541 | } | 541 | } |
| 542 | 542 | ||
| 543 | /* Adds one bit of irdata */ | 543 | /* Adds one bit of irdata */ |
| @@ -768,7 +768,7 @@ wbcir_parse_rc6(struct device *dev, struct wbcir_data *data) | |||
| 768 | return; | 768 | return; |
| 769 | } | 769 | } |
| 770 | 770 | ||
| 771 | dev_info(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " | 771 | dev_dbg(dev, "IR-RC6 ad 0x%02X cm 0x%02X cu 0x%04X " |
| 772 | "toggle %u mode %u scan 0x%08X\n", | 772 | "toggle %u mode %u scan 0x%08X\n", |
| 773 | address, | 773 | address, |
| 774 | command, | 774 | command, |
| @@ -1006,7 +1006,6 @@ wbcir_irq_handler(int irqno, void *cookie) | |||
| 1006 | } | 1006 | } |
| 1007 | 1007 | ||
| 1008 | wbcir_reset_irdata(data); | 1008 | wbcir_reset_irdata(data); |
| 1009 | data->idle_count = 0; | ||
| 1010 | } | 1009 | } |
| 1011 | 1010 | ||
| 1012 | out: | 1011 | out: |
| @@ -1018,7 +1017,7 @@ out: | |||
| 1018 | 1017 | ||
| 1019 | /***************************************************************************** | 1018 | /***************************************************************************** |
| 1020 | * | 1019 | * |
| 1021 | * SUSPEND/RESUME FUNCTIONS | 1020 | * SETUP/INIT/SUSPEND/RESUME FUNCTIONS |
| 1022 | * | 1021 | * |
| 1023 | *****************************************************************************/ | 1022 | *****************************************************************************/ |
| 1024 | 1023 | ||
| @@ -1197,7 +1196,16 @@ finish: | |||
| 1197 | } | 1196 | } |
| 1198 | 1197 | ||
| 1199 | /* Disable interrupts */ | 1198 | /* Disable interrupts */ |
| 1199 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1200 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | 1200 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); |
| 1201 | |||
| 1202 | /* | ||
| 1203 | * ACPI will set the HW disable bit for SP3 which means that the | ||
| 1204 | * output signals are left in an undefined state which may cause | ||
| 1205 | * spurious interrupts which we need to ignore until the hardware | ||
| 1206 | * is reinitialized. | ||
| 1207 | */ | ||
| 1208 | disable_irq(data->irq); | ||
| 1201 | } | 1209 | } |
| 1202 | 1210 | ||
| 1203 | static int | 1211 | static int |
| @@ -1207,37 +1215,15 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state) | |||
| 1207 | return 0; | 1215 | return 0; |
| 1208 | } | 1216 | } |
| 1209 | 1217 | ||
| 1210 | static int | ||
| 1211 | wbcir_resume(struct pnp_dev *device) | ||
| 1212 | { | ||
| 1213 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
| 1214 | |||
| 1215 | /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ | ||
| 1216 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07); | ||
| 1217 | |||
| 1218 | /* Clear CEIR_EN */ | ||
| 1219 | wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x00, 0x01); | ||
| 1220 | |||
| 1221 | /* Enable interrupts */ | ||
| 1222 | wbcir_reset_irdata(data); | ||
| 1223 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1224 | |||
| 1225 | return 0; | ||
| 1226 | } | ||
| 1227 | |||
| 1228 | |||
| 1229 | |||
| 1230 | /***************************************************************************** | ||
| 1231 | * | ||
| 1232 | * SETUP/INIT FUNCTIONS | ||
| 1233 | * | ||
| 1234 | *****************************************************************************/ | ||
| 1235 | |||
| 1236 | static void | 1218 | static void |
| 1237 | wbcir_cfg_ceir(struct wbcir_data *data) | 1219 | wbcir_init_hw(struct wbcir_data *data) |
| 1238 | { | 1220 | { |
| 1239 | u8 tmp; | 1221 | u8 tmp; |
| 1240 | 1222 | ||
| 1223 | /* Disable interrupts */ | ||
| 1224 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1225 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1226 | |||
| 1241 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ | 1227 | /* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ |
| 1242 | tmp = protocol << 4; | 1228 | tmp = protocol << 4; |
| 1243 | if (invert) | 1229 | if (invert) |
| @@ -1264,6 +1250,93 @@ wbcir_cfg_ceir(struct wbcir_data *data) | |||
| 1264 | * set SP3_IRRX_SW to binary 01, helpfully not documented | 1250 | * set SP3_IRRX_SW to binary 01, helpfully not documented |
| 1265 | */ | 1251 | */ |
| 1266 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); | 1252 | outb(0x10, data->ebase + WBCIR_REG_ECEIR_CTS); |
| 1253 | |||
| 1254 | /* Enable extended mode */ | ||
| 1255 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
| 1256 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
| 1257 | |||
| 1258 | /* | ||
| 1259 | * Configure baud generator, IR data will be sampled at | ||
| 1260 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
| 1261 | * | ||
| 1262 | * The ECIR registers include a flag to change the | ||
| 1263 | * 24Mhz clock freq to 48Mhz. | ||
| 1264 | * | ||
| 1265 | * It's not documented in the specs, but fifo levels | ||
| 1266 | * other than 16 seems to be unsupported. | ||
| 1267 | */ | ||
| 1268 | |||
| 1269 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
| 1270 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
| 1271 | |||
| 1272 | /* Set baud divisor to generate one byte per bit/cell */ | ||
| 1273 | switch (protocol) { | ||
| 1274 | case IR_PROTOCOL_RC5: | ||
| 1275 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1276 | break; | ||
| 1277 | case IR_PROTOCOL_RC6: | ||
| 1278 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1279 | break; | ||
| 1280 | case IR_PROTOCOL_NEC: | ||
| 1281 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1282 | break; | ||
| 1283 | } | ||
| 1284 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
| 1285 | |||
| 1286 | /* Set CEIR mode */ | ||
| 1287 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1288 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
| 1289 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
| 1290 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
| 1291 | |||
| 1292 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
| 1293 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1294 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
| 1295 | |||
| 1296 | /* Disable timer */ | ||
| 1297 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
| 1298 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
| 1299 | |||
| 1300 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
| 1301 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
| 1302 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
| 1303 | |||
| 1304 | /* Disable CRC */ | ||
| 1305 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
| 1306 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
| 1307 | |||
| 1308 | /* Set RX/TX (de)modulation freq, not really used */ | ||
| 1309 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1310 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
| 1311 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
| 1312 | |||
| 1313 | /* Set invert and pin direction */ | ||
| 1314 | if (invert) | ||
| 1315 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1316 | else | ||
| 1317 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1318 | |||
| 1319 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
| 1320 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1321 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
| 1322 | |||
| 1323 | /* Clear AUX status bits */ | ||
| 1324 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 1325 | |||
| 1326 | /* Enable interrupts */ | ||
| 1327 | wbcir_reset_irdata(data); | ||
| 1328 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1329 | } | ||
| 1330 | |||
| 1331 | static int | ||
| 1332 | wbcir_resume(struct pnp_dev *device) | ||
| 1333 | { | ||
| 1334 | struct wbcir_data *data = pnp_get_drvdata(device); | ||
| 1335 | |||
| 1336 | wbcir_init_hw(data); | ||
| 1337 | enable_irq(data->irq); | ||
| 1338 | |||
| 1339 | return 0; | ||
| 1267 | } | 1340 | } |
| 1268 | 1341 | ||
| 1269 | static int __devinit | 1342 | static int __devinit |
| @@ -1393,86 +1466,7 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) | |||
| 1393 | 1466 | ||
| 1394 | device_init_wakeup(&device->dev, 1); | 1467 | device_init_wakeup(&device->dev, 1); |
| 1395 | 1468 | ||
| 1396 | wbcir_cfg_ceir(data); | 1469 | wbcir_init_hw(data); |
| 1397 | |||
| 1398 | /* Disable interrupts */ | ||
| 1399 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1400 | outb(WBCIR_IRQ_NONE, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1401 | |||
| 1402 | /* Enable extended mode */ | ||
| 1403 | wbcir_select_bank(data, WBCIR_BANK_2); | ||
| 1404 | outb(WBCIR_EXT_ENABLE, data->sbase + WBCIR_REG_SP3_EXCR1); | ||
| 1405 | |||
| 1406 | /* | ||
| 1407 | * Configure baud generator, IR data will be sampled at | ||
| 1408 | * a bitrate of: (24Mhz * prescaler) / (divisor * 16). | ||
| 1409 | * | ||
| 1410 | * The ECIR registers include a flag to change the | ||
| 1411 | * 24Mhz clock freq to 48Mhz. | ||
| 1412 | * | ||
| 1413 | * It's not documented in the specs, but fifo levels | ||
| 1414 | * other than 16 seems to be unsupported. | ||
| 1415 | */ | ||
| 1416 | |||
| 1417 | /* prescaler 1.0, tx/rx fifo lvl 16 */ | ||
| 1418 | outb(0x30, data->sbase + WBCIR_REG_SP3_EXCR2); | ||
| 1419 | |||
| 1420 | /* Set baud divisor to generate one byte per bit/cell */ | ||
| 1421 | switch (protocol) { | ||
| 1422 | case IR_PROTOCOL_RC5: | ||
| 1423 | outb(0xA7, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1424 | break; | ||
| 1425 | case IR_PROTOCOL_RC6: | ||
| 1426 | outb(0x53, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1427 | break; | ||
| 1428 | case IR_PROTOCOL_NEC: | ||
| 1429 | outb(0x69, data->sbase + WBCIR_REG_SP3_BGDL); | ||
| 1430 | break; | ||
| 1431 | } | ||
| 1432 | outb(0x00, data->sbase + WBCIR_REG_SP3_BGDH); | ||
| 1433 | |||
| 1434 | /* Set CEIR mode */ | ||
| 1435 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1436 | outb(0xC0, data->sbase + WBCIR_REG_SP3_MCR); | ||
| 1437 | inb(data->sbase + WBCIR_REG_SP3_LSR); /* Clear LSR */ | ||
| 1438 | inb(data->sbase + WBCIR_REG_SP3_MSR); /* Clear MSR */ | ||
| 1439 | |||
| 1440 | /* Disable RX demod, run-length encoding/decoding, set freq span */ | ||
| 1441 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1442 | outb(0x10, data->sbase + WBCIR_REG_SP3_RCCFG); | ||
| 1443 | |||
| 1444 | /* Disable timer */ | ||
| 1445 | wbcir_select_bank(data, WBCIR_BANK_4); | ||
| 1446 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR1); | ||
| 1447 | |||
| 1448 | /* Enable MSR interrupt, Clear AUX_IRX */ | ||
| 1449 | wbcir_select_bank(data, WBCIR_BANK_5); | ||
| 1450 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCR2); | ||
| 1451 | |||
| 1452 | /* Disable CRC */ | ||
| 1453 | wbcir_select_bank(data, WBCIR_BANK_6); | ||
| 1454 | outb(0x20, data->sbase + WBCIR_REG_SP3_IRCR3); | ||
| 1455 | |||
| 1456 | /* Set RX/TX (de)modulation freq, not really used */ | ||
| 1457 | wbcir_select_bank(data, WBCIR_BANK_7); | ||
| 1458 | outb(0xF2, data->sbase + WBCIR_REG_SP3_IRRXDC); | ||
| 1459 | outb(0x69, data->sbase + WBCIR_REG_SP3_IRTXMC); | ||
| 1460 | |||
| 1461 | /* Set invert and pin direction */ | ||
| 1462 | if (invert) | ||
| 1463 | outb(0x10, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1464 | else | ||
| 1465 | outb(0x00, data->sbase + WBCIR_REG_SP3_IRCFG4); | ||
| 1466 | |||
| 1467 | /* Set FIFO thresholds (RX = 8, TX = 3), reset RX/TX */ | ||
| 1468 | wbcir_select_bank(data, WBCIR_BANK_0); | ||
| 1469 | outb(0x97, data->sbase + WBCIR_REG_SP3_FCR); | ||
| 1470 | |||
| 1471 | /* Clear AUX status bits */ | ||
| 1472 | outb(0xE0, data->sbase + WBCIR_REG_SP3_ASCR); | ||
| 1473 | |||
| 1474 | /* Enable interrupts */ | ||
| 1475 | outb(WBCIR_IRQ_RX | WBCIR_IRQ_ERR, data->sbase + WBCIR_REG_SP3_IER); | ||
| 1476 | 1470 | ||
| 1477 | return 0; | 1471 | return 0; |
| 1478 | 1472 | ||
diff --git a/drivers/input/misc/wistron_btns.c b/drivers/input/misc/wistron_btns.c index a932179c4c9e..04d5a4a3181f 100644 --- a/drivers/input/misc/wistron_btns.c +++ b/drivers/input/misc/wistron_btns.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/dmi.h> | 21 | #include <linux/dmi.h> |
| 22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 23 | #include <linux/input-polldev.h> | 23 | #include <linux/input-polldev.h> |
| 24 | #include <linux/input/sparse-keymap.h> | ||
| 24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 25 | #include <linux/jiffies.h> | 26 | #include <linux/jiffies.h> |
| 26 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| @@ -28,6 +29,7 @@ | |||
| 28 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 29 | #include <linux/preempt.h> | 30 | #include <linux/preempt.h> |
| 30 | #include <linux/string.h> | 31 | #include <linux/string.h> |
| 32 | #include <linux/slab.h> | ||
| 31 | #include <linux/types.h> | 33 | #include <linux/types.h> |
| 32 | #include <linux/platform_device.h> | 34 | #include <linux/platform_device.h> |
| 33 | #include <linux/leds.h> | 35 | #include <linux/leds.h> |
| @@ -224,19 +226,8 @@ static void bios_set_state(u8 subsys, int enable) | |||
| 224 | 226 | ||
| 225 | /* Hardware database */ | 227 | /* Hardware database */ |
| 226 | 228 | ||
| 227 | struct key_entry { | 229 | #define KE_WIFI (KE_LAST + 1) |
| 228 | char type; /* See KE_* below */ | 230 | #define KE_BLUETOOTH (KE_LAST + 2) |
| 229 | u8 code; | ||
| 230 | union { | ||
| 231 | u16 keycode; /* For KE_KEY */ | ||
| 232 | struct { /* For KE_SW */ | ||
| 233 | u8 code; | ||
| 234 | u8 value; | ||
| 235 | } sw; | ||
| 236 | }; | ||
| 237 | }; | ||
| 238 | |||
| 239 | enum { KE_END, KE_KEY, KE_SW, KE_WIFI, KE_BLUETOOTH }; | ||
| 240 | 231 | ||
| 241 | #define FE_MAIL_LED 0x01 | 232 | #define FE_MAIL_LED 0x01 |
| 242 | #define FE_WIFI_LED 0x02 | 233 | #define FE_WIFI_LED 0x02 |
| @@ -644,10 +635,10 @@ static struct key_entry keymap_prestigio[] __initdata = { | |||
| 644 | * a list of buttons and their key codes (reported when loading this module | 635 | * a list of buttons and their key codes (reported when loading this module |
| 645 | * with force=1) and the output of dmidecode to $MODULE_AUTHOR. | 636 | * with force=1) and the output of dmidecode to $MODULE_AUTHOR. |
| 646 | */ | 637 | */ |
| 647 | static struct dmi_system_id dmi_ids[] __initdata = { | 638 | static const struct dmi_system_id __initconst dmi_ids[] = { |
| 648 | { | 639 | { |
| 640 | /* Fujitsu-Siemens Amilo Pro V2000 */ | ||
| 649 | .callback = dmi_matched, | 641 | .callback = dmi_matched, |
| 650 | .ident = "Fujitsu-Siemens Amilo Pro V2000", | ||
| 651 | .matches = { | 642 | .matches = { |
| 652 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 643 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 653 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), | 644 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2000"), |
| @@ -655,8 +646,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 655 | .driver_data = keymap_fs_amilo_pro_v2000 | 646 | .driver_data = keymap_fs_amilo_pro_v2000 |
| 656 | }, | 647 | }, |
| 657 | { | 648 | { |
| 649 | /* Fujitsu-Siemens Amilo Pro Edition V3505 */ | ||
| 658 | .callback = dmi_matched, | 650 | .callback = dmi_matched, |
| 659 | .ident = "Fujitsu-Siemens Amilo Pro Edition V3505", | ||
| 660 | .matches = { | 651 | .matches = { |
| 661 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 652 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 662 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), | 653 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro Edition V3505"), |
| @@ -664,8 +655,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 664 | .driver_data = keymap_fs_amilo_pro_v3505 | 655 | .driver_data = keymap_fs_amilo_pro_v3505 |
| 665 | }, | 656 | }, |
| 666 | { | 657 | { |
| 658 | /* Fujitsu-Siemens Amilo M7400 */ | ||
| 667 | .callback = dmi_matched, | 659 | .callback = dmi_matched, |
| 668 | .ident = "Fujitsu-Siemens Amilo M7400", | ||
| 669 | .matches = { | 660 | .matches = { |
| 670 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 661 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 671 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), | 662 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO M "), |
| @@ -673,8 +664,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 673 | .driver_data = keymap_fs_amilo_pro_v2000 | 664 | .driver_data = keymap_fs_amilo_pro_v2000 |
| 674 | }, | 665 | }, |
| 675 | { | 666 | { |
| 667 | /* Maxdata Pro 7000 DX */ | ||
| 676 | .callback = dmi_matched, | 668 | .callback = dmi_matched, |
| 677 | .ident = "Maxdata Pro 7000 DX", | ||
| 678 | .matches = { | 669 | .matches = { |
| 679 | DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), | 670 | DMI_MATCH(DMI_SYS_VENDOR, "MAXDATA"), |
| 680 | DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), | 671 | DMI_MATCH(DMI_PRODUCT_NAME, "Pro 7000"), |
| @@ -682,8 +673,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 682 | .driver_data = keymap_fs_amilo_pro_v2000 | 673 | .driver_data = keymap_fs_amilo_pro_v2000 |
| 683 | }, | 674 | }, |
| 684 | { | 675 | { |
| 676 | /* Fujitsu N3510 */ | ||
| 685 | .callback = dmi_matched, | 677 | .callback = dmi_matched, |
| 686 | .ident = "Fujitsu N3510", | ||
| 687 | .matches = { | 678 | .matches = { |
| 688 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 679 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 689 | DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), | 680 | DMI_MATCH(DMI_PRODUCT_NAME, "N3510"), |
| @@ -691,8 +682,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 691 | .driver_data = keymap_fujitsu_n3510 | 682 | .driver_data = keymap_fujitsu_n3510 |
| 692 | }, | 683 | }, |
| 693 | { | 684 | { |
| 685 | /* Acer Aspire 1500 */ | ||
| 694 | .callback = dmi_matched, | 686 | .callback = dmi_matched, |
| 695 | .ident = "Acer Aspire 1500", | ||
| 696 | .matches = { | 687 | .matches = { |
| 697 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 688 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 698 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), | 689 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1500"), |
| @@ -700,8 +691,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 700 | .driver_data = keymap_acer_aspire_1500 | 691 | .driver_data = keymap_acer_aspire_1500 |
| 701 | }, | 692 | }, |
| 702 | { | 693 | { |
| 694 | /* Acer Aspire 1600 */ | ||
| 703 | .callback = dmi_matched, | 695 | .callback = dmi_matched, |
| 704 | .ident = "Acer Aspire 1600", | ||
| 705 | .matches = { | 696 | .matches = { |
| 706 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 697 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 707 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), | 698 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1600"), |
| @@ -709,8 +700,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 709 | .driver_data = keymap_acer_aspire_1600 | 700 | .driver_data = keymap_acer_aspire_1600 |
| 710 | }, | 701 | }, |
| 711 | { | 702 | { |
| 703 | /* Acer Aspire 3020 */ | ||
| 712 | .callback = dmi_matched, | 704 | .callback = dmi_matched, |
| 713 | .ident = "Acer Aspire 3020", | ||
| 714 | .matches = { | 705 | .matches = { |
| 715 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 706 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 716 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), | 707 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3020"), |
| @@ -718,8 +709,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 718 | .driver_data = keymap_acer_aspire_5020 | 709 | .driver_data = keymap_acer_aspire_5020 |
| 719 | }, | 710 | }, |
| 720 | { | 711 | { |
| 712 | /* Acer Aspire 5020 */ | ||
| 721 | .callback = dmi_matched, | 713 | .callback = dmi_matched, |
| 722 | .ident = "Acer Aspire 5020", | ||
| 723 | .matches = { | 714 | .matches = { |
| 724 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 715 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 725 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), | 716 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5020"), |
| @@ -727,8 +718,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 727 | .driver_data = keymap_acer_aspire_5020 | 718 | .driver_data = keymap_acer_aspire_5020 |
| 728 | }, | 719 | }, |
| 729 | { | 720 | { |
| 721 | /* Acer TravelMate 2100 */ | ||
| 730 | .callback = dmi_matched, | 722 | .callback = dmi_matched, |
| 731 | .ident = "Acer TravelMate 2100", | ||
| 732 | .matches = { | 723 | .matches = { |
| 733 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 724 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 734 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), | 725 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2100"), |
| @@ -736,8 +727,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 736 | .driver_data = keymap_acer_aspire_5020 | 727 | .driver_data = keymap_acer_aspire_5020 |
| 737 | }, | 728 | }, |
| 738 | { | 729 | { |
| 730 | /* Acer TravelMate 2410 */ | ||
| 739 | .callback = dmi_matched, | 731 | .callback = dmi_matched, |
| 740 | .ident = "Acer TravelMate 2410", | ||
| 741 | .matches = { | 732 | .matches = { |
| 742 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 733 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 743 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), | 734 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2410"), |
| @@ -745,8 +736,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 745 | .driver_data = keymap_acer_travelmate_2410 | 736 | .driver_data = keymap_acer_travelmate_2410 |
| 746 | }, | 737 | }, |
| 747 | { | 738 | { |
| 739 | /* Acer TravelMate C300 */ | ||
| 748 | .callback = dmi_matched, | 740 | .callback = dmi_matched, |
| 749 | .ident = "Acer TravelMate C300", | ||
| 750 | .matches = { | 741 | .matches = { |
| 751 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 742 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 752 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), | 743 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C300"), |
| @@ -754,8 +745,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 754 | .driver_data = keymap_acer_travelmate_300 | 745 | .driver_data = keymap_acer_travelmate_300 |
| 755 | }, | 746 | }, |
| 756 | { | 747 | { |
| 748 | /* Acer TravelMate C100 */ | ||
| 757 | .callback = dmi_matched, | 749 | .callback = dmi_matched, |
| 758 | .ident = "Acer TravelMate C100", | ||
| 759 | .matches = { | 750 | .matches = { |
| 760 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 751 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 761 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), | 752 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C100"), |
| @@ -763,8 +754,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 763 | .driver_data = keymap_acer_travelmate_300 | 754 | .driver_data = keymap_acer_travelmate_300 |
| 764 | }, | 755 | }, |
| 765 | { | 756 | { |
| 757 | /* Acer TravelMate C110 */ | ||
| 766 | .callback = dmi_matched, | 758 | .callback = dmi_matched, |
| 767 | .ident = "Acer TravelMate C110", | ||
| 768 | .matches = { | 759 | .matches = { |
| 769 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 760 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 770 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), | 761 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate C110"), |
| @@ -772,8 +763,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 772 | .driver_data = keymap_acer_travelmate_110 | 763 | .driver_data = keymap_acer_travelmate_110 |
| 773 | }, | 764 | }, |
| 774 | { | 765 | { |
| 766 | /* Acer TravelMate 380 */ | ||
| 775 | .callback = dmi_matched, | 767 | .callback = dmi_matched, |
| 776 | .ident = "Acer TravelMate 380", | ||
| 777 | .matches = { | 768 | .matches = { |
| 778 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 769 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 779 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), | 770 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 380"), |
| @@ -781,8 +772,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 781 | .driver_data = keymap_acer_travelmate_380 | 772 | .driver_data = keymap_acer_travelmate_380 |
| 782 | }, | 773 | }, |
| 783 | { | 774 | { |
| 775 | /* Acer TravelMate 370 */ | ||
| 784 | .callback = dmi_matched, | 776 | .callback = dmi_matched, |
| 785 | .ident = "Acer TravelMate 370", | ||
| 786 | .matches = { | 777 | .matches = { |
| 787 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 778 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 788 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), | 779 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 370"), |
| @@ -790,8 +781,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 790 | .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ | 781 | .driver_data = keymap_acer_travelmate_380 /* keyboard minus 1 key */ |
| 791 | }, | 782 | }, |
| 792 | { | 783 | { |
| 784 | /* Acer TravelMate 220 */ | ||
| 793 | .callback = dmi_matched, | 785 | .callback = dmi_matched, |
| 794 | .ident = "Acer TravelMate 220", | ||
| 795 | .matches = { | 786 | .matches = { |
| 796 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 787 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 797 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), | 788 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 220"), |
| @@ -799,8 +790,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 799 | .driver_data = keymap_acer_travelmate_220 | 790 | .driver_data = keymap_acer_travelmate_220 |
| 800 | }, | 791 | }, |
| 801 | { | 792 | { |
| 793 | /* Acer TravelMate 260 */ | ||
| 802 | .callback = dmi_matched, | 794 | .callback = dmi_matched, |
| 803 | .ident = "Acer TravelMate 260", | ||
| 804 | .matches = { | 795 | .matches = { |
| 805 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 796 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 806 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), | 797 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 260"), |
| @@ -808,8 +799,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 808 | .driver_data = keymap_acer_travelmate_220 | 799 | .driver_data = keymap_acer_travelmate_220 |
| 809 | }, | 800 | }, |
| 810 | { | 801 | { |
| 802 | /* Acer TravelMate 230 */ | ||
| 811 | .callback = dmi_matched, | 803 | .callback = dmi_matched, |
| 812 | .ident = "Acer TravelMate 230", | ||
| 813 | .matches = { | 804 | .matches = { |
| 814 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 805 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 815 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), | 806 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 230"), |
| @@ -818,8 +809,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 818 | .driver_data = keymap_acer_travelmate_230 | 809 | .driver_data = keymap_acer_travelmate_230 |
| 819 | }, | 810 | }, |
| 820 | { | 811 | { |
| 812 | /* Acer TravelMate 280 */ | ||
| 821 | .callback = dmi_matched, | 813 | .callback = dmi_matched, |
| 822 | .ident = "Acer TravelMate 280", | ||
| 823 | .matches = { | 814 | .matches = { |
| 824 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 815 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 825 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), | 816 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 280"), |
| @@ -827,8 +818,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 827 | .driver_data = keymap_acer_travelmate_230 | 818 | .driver_data = keymap_acer_travelmate_230 |
| 828 | }, | 819 | }, |
| 829 | { | 820 | { |
| 821 | /* Acer TravelMate 240 */ | ||
| 830 | .callback = dmi_matched, | 822 | .callback = dmi_matched, |
| 831 | .ident = "Acer TravelMate 240", | ||
| 832 | .matches = { | 823 | .matches = { |
| 833 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 824 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 834 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), | 825 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 240"), |
| @@ -836,8 +827,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 836 | .driver_data = keymap_acer_travelmate_240 | 827 | .driver_data = keymap_acer_travelmate_240 |
| 837 | }, | 828 | }, |
| 838 | { | 829 | { |
| 830 | /* Acer TravelMate 250 */ | ||
| 839 | .callback = dmi_matched, | 831 | .callback = dmi_matched, |
| 840 | .ident = "Acer TravelMate 250", | ||
| 841 | .matches = { | 832 | .matches = { |
| 842 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 833 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 843 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), | 834 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 250"), |
| @@ -845,8 +836,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 845 | .driver_data = keymap_acer_travelmate_240 | 836 | .driver_data = keymap_acer_travelmate_240 |
| 846 | }, | 837 | }, |
| 847 | { | 838 | { |
| 839 | /* Acer TravelMate 2424NWXCi */ | ||
| 848 | .callback = dmi_matched, | 840 | .callback = dmi_matched, |
| 849 | .ident = "Acer TravelMate 2424NWXCi", | ||
| 850 | .matches = { | 841 | .matches = { |
| 851 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 842 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 852 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), | 843 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2420"), |
| @@ -854,8 +845,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 854 | .driver_data = keymap_acer_travelmate_240 | 845 | .driver_data = keymap_acer_travelmate_240 |
| 855 | }, | 846 | }, |
| 856 | { | 847 | { |
| 848 | /* Acer TravelMate 350 */ | ||
| 857 | .callback = dmi_matched, | 849 | .callback = dmi_matched, |
| 858 | .ident = "Acer TravelMate 350", | ||
| 859 | .matches = { | 850 | .matches = { |
| 860 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 851 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 861 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), | 852 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 350"), |
| @@ -863,8 +854,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 863 | .driver_data = keymap_acer_travelmate_350 | 854 | .driver_data = keymap_acer_travelmate_350 |
| 864 | }, | 855 | }, |
| 865 | { | 856 | { |
| 857 | /* Acer TravelMate 360 */ | ||
| 866 | .callback = dmi_matched, | 858 | .callback = dmi_matched, |
| 867 | .ident = "Acer TravelMate 360", | ||
| 868 | .matches = { | 859 | .matches = { |
| 869 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 860 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 870 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), | 861 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), |
| @@ -872,8 +863,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 872 | .driver_data = keymap_acer_travelmate_360 | 863 | .driver_data = keymap_acer_travelmate_360 |
| 873 | }, | 864 | }, |
| 874 | { | 865 | { |
| 866 | /* Acer TravelMate 610 */ | ||
| 875 | .callback = dmi_matched, | 867 | .callback = dmi_matched, |
| 876 | .ident = "Acer TravelMate 610", | ||
| 877 | .matches = { | 868 | .matches = { |
| 878 | DMI_MATCH(DMI_SYS_VENDOR, "ACER"), | 869 | DMI_MATCH(DMI_SYS_VENDOR, "ACER"), |
| 879 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), | 870 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 610"), |
| @@ -881,8 +872,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 881 | .driver_data = keymap_acer_travelmate_610 | 872 | .driver_data = keymap_acer_travelmate_610 |
| 882 | }, | 873 | }, |
| 883 | { | 874 | { |
| 875 | /* Acer TravelMate 620 */ | ||
| 884 | .callback = dmi_matched, | 876 | .callback = dmi_matched, |
| 885 | .ident = "Acer TravelMate 620", | ||
| 886 | .matches = { | 877 | .matches = { |
| 887 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 878 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 888 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), | 879 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 620"), |
| @@ -890,8 +881,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 890 | .driver_data = keymap_acer_travelmate_630 | 881 | .driver_data = keymap_acer_travelmate_630 |
| 891 | }, | 882 | }, |
| 892 | { | 883 | { |
| 884 | /* Acer TravelMate 630 */ | ||
| 893 | .callback = dmi_matched, | 885 | .callback = dmi_matched, |
| 894 | .ident = "Acer TravelMate 630", | ||
| 895 | .matches = { | 886 | .matches = { |
| 896 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 887 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 897 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), | 888 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 630"), |
| @@ -899,8 +890,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 899 | .driver_data = keymap_acer_travelmate_630 | 890 | .driver_data = keymap_acer_travelmate_630 |
| 900 | }, | 891 | }, |
| 901 | { | 892 | { |
| 893 | /* AOpen 1559AS */ | ||
| 902 | .callback = dmi_matched, | 894 | .callback = dmi_matched, |
| 903 | .ident = "AOpen 1559AS", | ||
| 904 | .matches = { | 895 | .matches = { |
| 905 | DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), | 896 | DMI_MATCH(DMI_PRODUCT_NAME, "E2U"), |
| 906 | DMI_MATCH(DMI_BOARD_NAME, "E2U"), | 897 | DMI_MATCH(DMI_BOARD_NAME, "E2U"), |
| @@ -908,8 +899,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 908 | .driver_data = keymap_aopen_1559as | 899 | .driver_data = keymap_aopen_1559as |
| 909 | }, | 900 | }, |
| 910 | { | 901 | { |
| 902 | /* Medion MD 9783 */ | ||
| 911 | .callback = dmi_matched, | 903 | .callback = dmi_matched, |
| 912 | .ident = "Medion MD 9783", | ||
| 913 | .matches = { | 904 | .matches = { |
| 914 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), | 905 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), |
| 915 | DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), | 906 | DMI_MATCH(DMI_PRODUCT_NAME, "MD 9783"), |
| @@ -917,8 +908,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 917 | .driver_data = keymap_wistron_ms2111 | 908 | .driver_data = keymap_wistron_ms2111 |
| 918 | }, | 909 | }, |
| 919 | { | 910 | { |
| 911 | /* Medion MD 40100 */ | ||
| 920 | .callback = dmi_matched, | 912 | .callback = dmi_matched, |
| 921 | .ident = "Medion MD 40100", | ||
| 922 | .matches = { | 913 | .matches = { |
| 923 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), | 914 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), |
| 924 | DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), | 915 | DMI_MATCH(DMI_PRODUCT_NAME, "WID2000"), |
| @@ -926,8 +917,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 926 | .driver_data = keymap_wistron_md40100 | 917 | .driver_data = keymap_wistron_md40100 |
| 927 | }, | 918 | }, |
| 928 | { | 919 | { |
| 920 | /* Medion MD 2900 */ | ||
| 929 | .callback = dmi_matched, | 921 | .callback = dmi_matched, |
| 930 | .ident = "Medion MD 2900", | ||
| 931 | .matches = { | 922 | .matches = { |
| 932 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), | 923 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONNB"), |
| 933 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), | 924 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2000"), |
| @@ -935,8 +926,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 935 | .driver_data = keymap_wistron_md2900 | 926 | .driver_data = keymap_wistron_md2900 |
| 936 | }, | 927 | }, |
| 937 | { | 928 | { |
| 929 | /* Medion MD 42200 */ | ||
| 938 | .callback = dmi_matched, | 930 | .callback = dmi_matched, |
| 939 | .ident = "Medion MD 42200", | ||
| 940 | .matches = { | 931 | .matches = { |
| 941 | DMI_MATCH(DMI_SYS_VENDOR, "Medion"), | 932 | DMI_MATCH(DMI_SYS_VENDOR, "Medion"), |
| 942 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), | 933 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2030"), |
| @@ -944,8 +935,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 944 | .driver_data = keymap_fs_amilo_pro_v2000 | 935 | .driver_data = keymap_fs_amilo_pro_v2000 |
| 945 | }, | 936 | }, |
| 946 | { | 937 | { |
| 938 | /* Medion MD 96500 */ | ||
| 947 | .callback = dmi_matched, | 939 | .callback = dmi_matched, |
| 948 | .ident = "Medion MD 96500", | ||
| 949 | .matches = { | 940 | .matches = { |
| 950 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), | 941 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), |
| 951 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), | 942 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2040"), |
| @@ -953,8 +944,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 953 | .driver_data = keymap_wistron_md96500 | 944 | .driver_data = keymap_wistron_md96500 |
| 954 | }, | 945 | }, |
| 955 | { | 946 | { |
| 947 | /* Medion MD 95400 */ | ||
| 956 | .callback = dmi_matched, | 948 | .callback = dmi_matched, |
| 957 | .ident = "Medion MD 95400", | ||
| 958 | .matches = { | 949 | .matches = { |
| 959 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), | 950 | DMI_MATCH(DMI_SYS_VENDOR, "MEDIONPC"), |
| 960 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), | 951 | DMI_MATCH(DMI_PRODUCT_NAME, "WIM 2050"), |
| @@ -962,8 +953,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 962 | .driver_data = keymap_wistron_md96500 | 953 | .driver_data = keymap_wistron_md96500 |
| 963 | }, | 954 | }, |
| 964 | { | 955 | { |
| 956 | /* Fujitsu Siemens Amilo D7820 */ | ||
| 965 | .callback = dmi_matched, | 957 | .callback = dmi_matched, |
| 966 | .ident = "Fujitsu Siemens Amilo D7820", | ||
| 967 | .matches = { | 958 | .matches = { |
| 968 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ | 959 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), /* not sure */ |
| 969 | DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), | 960 | DMI_MATCH(DMI_PRODUCT_NAME, "Amilo D"), |
| @@ -971,8 +962,8 @@ static struct dmi_system_id dmi_ids[] __initdata = { | |||
| 971 | .driver_data = keymap_fs_amilo_d88x0 | 962 | .driver_data = keymap_fs_amilo_d88x0 |
| 972 | }, | 963 | }, |
| 973 | { | 964 | { |
| 965 | /* Fujitsu Siemens Amilo D88x0 */ | ||
| 974 | .callback = dmi_matched, | 966 | .callback = dmi_matched, |
| 975 | .ident = "Fujitsu Siemens Amilo D88x0", | ||
| 976 | .matches = { | 967 | .matches = { |
| 977 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 968 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 978 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), | 969 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO D"), |
| @@ -1037,21 +1028,6 @@ static unsigned long jiffies_last_press; | |||
| 1037 | static bool wifi_enabled; | 1028 | static bool wifi_enabled; |
| 1038 | static bool bluetooth_enabled; | 1029 | static bool bluetooth_enabled; |
| 1039 | 1030 | ||
| 1040 | static void report_key(struct input_dev *dev, unsigned int keycode) | ||
| 1041 | { | ||
| 1042 | input_report_key(dev, keycode, 1); | ||
| 1043 | input_sync(dev); | ||
| 1044 | input_report_key(dev, keycode, 0); | ||
| 1045 | input_sync(dev); | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static void report_switch(struct input_dev *dev, unsigned int code, int value) | ||
| 1049 | { | ||
| 1050 | input_report_switch(dev, code, value); | ||
| 1051 | input_sync(dev); | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | |||
| 1055 | /* led management */ | 1031 | /* led management */ |
| 1056 | static void wistron_mail_led_set(struct led_classdev *led_cdev, | 1032 | static void wistron_mail_led_set(struct led_classdev *led_cdev, |
| 1057 | enum led_brightness value) | 1033 | enum led_brightness value) |
| @@ -1128,43 +1104,13 @@ static inline void wistron_led_resume(void) | |||
| 1128 | led_classdev_resume(&wistron_wifi_led); | 1104 | led_classdev_resume(&wistron_wifi_led); |
| 1129 | } | 1105 | } |
| 1130 | 1106 | ||
| 1131 | static struct key_entry *wistron_get_entry_by_scancode(int code) | ||
| 1132 | { | ||
| 1133 | struct key_entry *key; | ||
| 1134 | |||
| 1135 | for (key = keymap; key->type != KE_END; key++) | ||
| 1136 | if (code == key->code) | ||
| 1137 | return key; | ||
| 1138 | |||
| 1139 | return NULL; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static struct key_entry *wistron_get_entry_by_keycode(int keycode) | ||
| 1143 | { | ||
| 1144 | struct key_entry *key; | ||
| 1145 | |||
| 1146 | for (key = keymap; key->type != KE_END; key++) | ||
| 1147 | if (key->type == KE_KEY && keycode == key->keycode) | ||
| 1148 | return key; | ||
| 1149 | |||
| 1150 | return NULL; | ||
| 1151 | } | ||
| 1152 | |||
| 1153 | static void handle_key(u8 code) | 1107 | static void handle_key(u8 code) |
| 1154 | { | 1108 | { |
| 1155 | const struct key_entry *key = wistron_get_entry_by_scancode(code); | 1109 | const struct key_entry *key = |
| 1110 | sparse_keymap_entry_from_scancode(wistron_idev->input, code); | ||
| 1156 | 1111 | ||
| 1157 | if (key) { | 1112 | if (key) { |
| 1158 | switch (key->type) { | 1113 | switch (key->type) { |
| 1159 | case KE_KEY: | ||
| 1160 | report_key(wistron_idev->input, key->keycode); | ||
| 1161 | break; | ||
| 1162 | |||
| 1163 | case KE_SW: | ||
| 1164 | report_switch(wistron_idev->input, | ||
| 1165 | key->sw.code, key->sw.value); | ||
| 1166 | break; | ||
| 1167 | |||
| 1168 | case KE_WIFI: | 1114 | case KE_WIFI: |
| 1169 | if (have_wifi) { | 1115 | if (have_wifi) { |
| 1170 | wifi_enabled = !wifi_enabled; | 1116 | wifi_enabled = !wifi_enabled; |
| @@ -1180,7 +1126,9 @@ static void handle_key(u8 code) | |||
| 1180 | break; | 1126 | break; |
| 1181 | 1127 | ||
| 1182 | default: | 1128 | default: |
| 1183 | BUG(); | 1129 | sparse_keymap_report_entry(wistron_idev->input, |
| 1130 | key, 1, true); | ||
| 1131 | break; | ||
| 1184 | } | 1132 | } |
| 1185 | jiffies_last_press = jiffies; | 1133 | jiffies_last_press = jiffies; |
| 1186 | } else | 1134 | } else |
| @@ -1220,42 +1168,39 @@ static void wistron_poll(struct input_polled_dev *dev) | |||
| 1220 | dev->poll_interval = POLL_INTERVAL_DEFAULT; | 1168 | dev->poll_interval = POLL_INTERVAL_DEFAULT; |
| 1221 | } | 1169 | } |
| 1222 | 1170 | ||
| 1223 | static int wistron_getkeycode(struct input_dev *dev, int scancode, int *keycode) | 1171 | static int __devinit wistron_setup_keymap(struct input_dev *dev, |
| 1172 | struct key_entry *entry) | ||
| 1224 | { | 1173 | { |
| 1225 | const struct key_entry *key = wistron_get_entry_by_scancode(scancode); | 1174 | switch (entry->type) { |
| 1226 | |||
| 1227 | if (key && key->type == KE_KEY) { | ||
| 1228 | *keycode = key->keycode; | ||
| 1229 | return 0; | ||
| 1230 | } | ||
| 1231 | 1175 | ||
| 1232 | return -EINVAL; | 1176 | /* if wifi or bluetooth are not available, create normal keys */ |
| 1233 | } | 1177 | case KE_WIFI: |
| 1178 | if (!have_wifi) { | ||
| 1179 | entry->type = KE_KEY; | ||
| 1180 | entry->keycode = KEY_WLAN; | ||
| 1181 | } | ||
| 1182 | break; | ||
| 1234 | 1183 | ||
| 1235 | static int wistron_setkeycode(struct input_dev *dev, int scancode, int keycode) | 1184 | case KE_BLUETOOTH: |
| 1236 | { | 1185 | if (!have_bluetooth) { |
| 1237 | struct key_entry *key; | 1186 | entry->type = KE_KEY; |
| 1238 | int old_keycode; | 1187 | entry->keycode = KEY_BLUETOOTH; |
| 1239 | 1188 | } | |
| 1240 | if (keycode < 0 || keycode > KEY_MAX) | 1189 | break; |
| 1241 | return -EINVAL; | 1190 | |
| 1242 | 1191 | case KE_END: | |
| 1243 | key = wistron_get_entry_by_scancode(scancode); | 1192 | if (entry->code & FE_UNTESTED) |
| 1244 | if (key && key->type == KE_KEY) { | 1193 | printk(KERN_WARNING "Untested laptop multimedia keys, " |
| 1245 | old_keycode = key->keycode; | 1194 | "please report success or failure to " |
| 1246 | key->keycode = keycode; | 1195 | "eric.piel@tremplin-utc.net\n"); |
| 1247 | set_bit(keycode, dev->keybit); | 1196 | break; |
| 1248 | if (!wistron_get_entry_by_keycode(old_keycode)) | ||
| 1249 | clear_bit(old_keycode, dev->keybit); | ||
| 1250 | return 0; | ||
| 1251 | } | 1197 | } |
| 1252 | 1198 | ||
| 1253 | return -EINVAL; | 1199 | return 0; |
| 1254 | } | 1200 | } |
| 1255 | 1201 | ||
| 1256 | static int __devinit setup_input_dev(void) | 1202 | static int __devinit setup_input_dev(void) |
| 1257 | { | 1203 | { |
| 1258 | struct key_entry *key; | ||
| 1259 | struct input_dev *input_dev; | 1204 | struct input_dev *input_dev; |
| 1260 | int error; | 1205 | int error; |
| 1261 | 1206 | ||
| @@ -1263,7 +1208,7 @@ static int __devinit setup_input_dev(void) | |||
| 1263 | if (!wistron_idev) | 1208 | if (!wistron_idev) |
| 1264 | return -ENOMEM; | 1209 | return -ENOMEM; |
| 1265 | 1210 | ||
| 1266 | wistron_idev->flush = wistron_flush; | 1211 | wistron_idev->open = wistron_flush; |
| 1267 | wistron_idev->poll = wistron_poll; | 1212 | wistron_idev->poll = wistron_poll; |
| 1268 | wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; | 1213 | wistron_idev->poll_interval = POLL_INTERVAL_DEFAULT; |
| 1269 | 1214 | ||
| @@ -1273,56 +1218,21 @@ static int __devinit setup_input_dev(void) | |||
| 1273 | input_dev->id.bustype = BUS_HOST; | 1218 | input_dev->id.bustype = BUS_HOST; |
| 1274 | input_dev->dev.parent = &wistron_device->dev; | 1219 | input_dev->dev.parent = &wistron_device->dev; |
| 1275 | 1220 | ||
| 1276 | input_dev->getkeycode = wistron_getkeycode; | 1221 | error = sparse_keymap_setup(input_dev, keymap, wistron_setup_keymap); |
| 1277 | input_dev->setkeycode = wistron_setkeycode; | 1222 | if (error) |
| 1278 | 1223 | goto err_free_dev; | |
| 1279 | for (key = keymap; key->type != KE_END; key++) { | ||
| 1280 | switch (key->type) { | ||
| 1281 | case KE_KEY: | ||
| 1282 | set_bit(EV_KEY, input_dev->evbit); | ||
| 1283 | set_bit(key->keycode, input_dev->keybit); | ||
| 1284 | break; | ||
| 1285 | |||
| 1286 | case KE_SW: | ||
| 1287 | set_bit(EV_SW, input_dev->evbit); | ||
| 1288 | set_bit(key->sw.code, input_dev->swbit); | ||
| 1289 | break; | ||
| 1290 | |||
| 1291 | /* if wifi or bluetooth are not available, create normal keys */ | ||
| 1292 | case KE_WIFI: | ||
| 1293 | if (!have_wifi) { | ||
| 1294 | key->type = KE_KEY; | ||
| 1295 | key->keycode = KEY_WLAN; | ||
| 1296 | key--; | ||
| 1297 | } | ||
| 1298 | break; | ||
| 1299 | |||
| 1300 | case KE_BLUETOOTH: | ||
| 1301 | if (!have_bluetooth) { | ||
| 1302 | key->type = KE_KEY; | ||
| 1303 | key->keycode = KEY_BLUETOOTH; | ||
| 1304 | key--; | ||
| 1305 | } | ||
| 1306 | break; | ||
| 1307 | |||
| 1308 | default: | ||
| 1309 | break; | ||
| 1310 | } | ||
| 1311 | } | ||
| 1312 | |||
| 1313 | /* reads information flags on KE_END */ | ||
| 1314 | if (key->code & FE_UNTESTED) | ||
| 1315 | printk(KERN_WARNING "Untested laptop multimedia keys, " | ||
| 1316 | "please report success or failure to eric.piel" | ||
| 1317 | "@tremplin-utc.net\n"); | ||
| 1318 | 1224 | ||
| 1319 | error = input_register_polled_device(wistron_idev); | 1225 | error = input_register_polled_device(wistron_idev); |
| 1320 | if (error) { | 1226 | if (error) |
| 1321 | input_free_polled_device(wistron_idev); | 1227 | goto err_free_keymap; |
| 1322 | return error; | ||
| 1323 | } | ||
| 1324 | 1228 | ||
| 1325 | return 0; | 1229 | return 0; |
| 1230 | |||
| 1231 | err_free_keymap: | ||
| 1232 | sparse_keymap_free(input_dev); | ||
| 1233 | err_free_dev: | ||
| 1234 | input_free_polled_device(wistron_idev); | ||
| 1235 | return error; | ||
| 1326 | } | 1236 | } |
| 1327 | 1237 | ||
| 1328 | /* Driver core */ | 1238 | /* Driver core */ |
| @@ -1371,6 +1281,7 @@ static int __devexit wistron_remove(struct platform_device *dev) | |||
| 1371 | { | 1281 | { |
| 1372 | wistron_led_remove(); | 1282 | wistron_led_remove(); |
| 1373 | input_unregister_polled_device(wistron_idev); | 1283 | input_unregister_polled_device(wistron_idev); |
| 1284 | sparse_keymap_free(wistron_idev->input); | ||
| 1374 | input_free_polled_device(wistron_idev); | 1285 | input_free_polled_device(wistron_idev); |
| 1375 | bios_detach(); | 1286 | bios_detach(); |
| 1376 | 1287 | ||
| @@ -1418,7 +1329,7 @@ static struct platform_driver wistron_driver = { | |||
| 1418 | .driver = { | 1329 | .driver = { |
| 1419 | .name = "wistron-bios", | 1330 | .name = "wistron-bios", |
| 1420 | .owner = THIS_MODULE, | 1331 | .owner = THIS_MODULE, |
| 1421 | #if CONFIG_PM | 1332 | #ifdef CONFIG_PM |
| 1422 | .pm = &wistron_pm_ops, | 1333 | .pm = &wistron_pm_ops, |
| 1423 | #endif | 1334 | #endif |
| 1424 | }, | 1335 | }, |
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index ba4f5dd7c60e..c3d7ba5f5b47 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| 23 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
| 24 | #include <linux/input.h> | 25 | #include <linux/input.h> |
| @@ -97,8 +98,9 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) | |||
| 97 | wm831x_on->dev->phys = "wm831x_on/input0"; | 98 | wm831x_on->dev->phys = "wm831x_on/input0"; |
| 98 | wm831x_on->dev->dev.parent = &pdev->dev; | 99 | wm831x_on->dev->dev.parent = &pdev->dev; |
| 99 | 100 | ||
| 100 | ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq, | 101 | ret = request_threaded_irq(irq, NULL, wm831x_on_irq, |
| 101 | IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on); | 102 | IRQF_TRIGGER_RISING, "wm831x_on", |
| 103 | wm831x_on); | ||
| 102 | if (ret < 0) { | 104 | if (ret < 0) { |
| 103 | dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); | 105 | dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); |
| 104 | goto err_input_dev; | 106 | goto err_input_dev; |
| @@ -114,7 +116,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) | |||
| 114 | return 0; | 116 | return 0; |
| 115 | 117 | ||
| 116 | err_irq: | 118 | err_irq: |
| 117 | wm831x_free_irq(wm831x, irq, NULL); | 119 | free_irq(irq, wm831x_on); |
| 118 | err_input_dev: | 120 | err_input_dev: |
| 119 | input_free_device(wm831x_on->dev); | 121 | input_free_device(wm831x_on->dev); |
| 120 | err: | 122 | err: |
| @@ -127,7 +129,7 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev) | |||
| 127 | struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); | 129 | struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); |
| 128 | int irq = platform_get_irq(pdev, 0); | 130 | int irq = platform_get_irq(pdev, 0); |
| 129 | 131 | ||
| 130 | wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on); | 132 | free_irq(irq, wm831x_on); |
| 131 | cancel_delayed_work_sync(&wm831x_on->work); | 133 | cancel_delayed_work_sync(&wm831x_on->work); |
| 132 | input_unregister_device(wm831x_on->dev); | 134 | input_unregister_device(wm831x_on->dev); |
| 133 | kfree(wm831x_on); | 135 | kfree(wm831x_on); |
diff --git a/drivers/input/misc/yealink.h b/drivers/input/misc/yealink.h index 48af0be9cbdf..1e0f52397010 100644 --- a/drivers/input/misc/yealink.h +++ b/drivers/input/misc/yealink.h | |||
| @@ -127,7 +127,7 @@ struct yld_ctl_packet { | |||
| 127 | * yld_status struct. | 127 | * yld_status struct. |
| 128 | */ | 128 | */ |
| 129 | 129 | ||
| 130 | /* LCD, each segment must be driven seperately. | 130 | /* LCD, each segment must be driven separately. |
| 131 | * | 131 | * |
| 132 | * Layout: | 132 | * Layout: |
| 133 | * | 133 | * |
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig index 3feeb3af8abd..c714ca2407f8 100644 --- a/drivers/input/mouse/Kconfig +++ b/drivers/input/mouse/Kconfig | |||
| @@ -70,7 +70,7 @@ config MOUSE_PS2_SYNAPTICS | |||
| 70 | config MOUSE_PS2_LIFEBOOK | 70 | config MOUSE_PS2_LIFEBOOK |
| 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED | 71 | bool "Fujitsu Lifebook PS/2 mouse protocol extension" if EMBEDDED |
| 72 | default y | 72 | default y |
| 73 | depends on MOUSE_PS2 && X86 | 73 | depends on MOUSE_PS2 && X86 && DMI |
| 74 | help | 74 | help |
| 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 | 75 | Say Y here if you have a Fujitsu B-series Lifebook PS/2 |
| 76 | TouchScreen connected to your system. | 76 | TouchScreen connected to your system. |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f36110689aae..99d58764ef03 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> | 5 | * Copyright (c) 2003-2005 Peter Osterlund <petero2@telia.com> |
| 6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> | 6 | * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru> |
| 7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | 7 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> |
| 8 | * Copyright (c) 2009 Sebastian Kapfer <sebastian_kapfer@gmx.net> | ||
| 8 | * | 9 | * |
| 9 | * ALPS detection, tap switching and status querying info is taken from | 10 | * ALPS detection, tap switching and status querying info is taken from |
| 10 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). | 11 | * tpconfig utility (by C. Scott Ananian and Bruce Kall). |
| @@ -14,6 +15,7 @@ | |||
| 14 | * the Free Software Foundation. | 15 | * the Free Software Foundation. |
| 15 | */ | 16 | */ |
| 16 | 17 | ||
| 18 | #include <linux/slab.h> | ||
| 17 | #include <linux/input.h> | 19 | #include <linux/input.h> |
| 18 | #include <linux/serio.h> | 20 | #include <linux/serio.h> |
| 19 | #include <linux/libps2.h> | 21 | #include <linux/libps2.h> |
| @@ -28,13 +30,16 @@ | |||
| 28 | #define dbg(format, arg...) do {} while (0) | 30 | #define dbg(format, arg...) do {} while (0) |
| 29 | #endif | 31 | #endif |
| 30 | 32 | ||
| 31 | #define ALPS_DUALPOINT 0x01 | 33 | #define ALPS_OLDPROTO 0x01 /* old style input */ |
| 32 | #define ALPS_WHEEL 0x02 | 34 | #define ALPS_DUALPOINT 0x02 /* touchpad has trackstick */ |
| 33 | #define ALPS_FW_BK_1 0x04 | 35 | #define ALPS_PASS 0x04 /* device has a pass-through port */ |
| 34 | #define ALPS_4BTN 0x08 | 36 | |
| 35 | #define ALPS_OLDPROTO 0x10 | 37 | #define ALPS_WHEEL 0x08 /* hardware wheel present */ |
| 36 | #define ALPS_PASS 0x20 | 38 | #define ALPS_FW_BK_1 0x10 /* front & back buttons present */ |
| 37 | #define ALPS_FW_BK_2 0x40 | 39 | #define ALPS_FW_BK_2 0x20 /* front & back buttons present */ |
| 40 | #define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */ | ||
| 41 | #define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with | ||
| 42 | 6-byte ALPS packet */ | ||
| 38 | 43 | ||
| 39 | static const struct alps_model_info alps_model_data[] = { | 44 | static const struct alps_model_info alps_model_data[] = { |
| 40 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ | 45 | { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */ |
| @@ -55,8 +60,12 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 55 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 60 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
| 56 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 61 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
| 57 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 62 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
| 58 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude E6500 */ | 63 | /* Dell Latitude E5500, E6400, E6500, Precision M4400 */ |
| 59 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FW_BK_1 }, /* Dell Vostro 1400 */ | 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, |
| 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | ||
| 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | ||
| 67 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, | ||
| 68 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | ||
| 60 | }; | 69 | }; |
| 61 | 70 | ||
| 62 | /* | 71 | /* |
| @@ -66,42 +75,86 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 66 | */ | 75 | */ |
| 67 | 76 | ||
| 68 | /* | 77 | /* |
| 69 | * ALPS abolute Mode - new format | 78 | * PS/2 packet format |
| 79 | * | ||
| 80 | * byte 0: 0 0 YSGN XSGN 1 M R L | ||
| 81 | * byte 1: X7 X6 X5 X4 X3 X2 X1 X0 | ||
| 82 | * byte 2: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
| 83 | * | ||
| 84 | * Note that the device never signals overflow condition. | ||
| 85 | * | ||
| 86 | * ALPS absolute Mode - new format | ||
| 70 | * | 87 | * |
| 71 | * byte 0: 1 ? ? ? 1 ? ? ? | 88 | * byte 0: 1 ? ? ? 1 ? ? ? |
| 72 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 89 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
| 73 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 90 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
| 74 | * byte 3: 0 y9 y8 y7 1 M R L | 91 | * byte 3: 0 y9 y8 y7 1 M R L |
| 75 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 92 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
| 76 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 93 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
| 77 | * | 94 | * |
| 95 | * Dualpoint device -- interleaved packet format | ||
| 96 | * | ||
| 97 | * byte 0: 1 1 0 0 1 1 1 1 | ||
| 98 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | ||
| 99 | * byte 2: 0 x10 x9 x8 x7 0 fin ges | ||
| 100 | * byte 3: 0 0 YSGN XSGN 1 1 1 1 | ||
| 101 | * byte 4: X7 X6 X5 X4 X3 X2 X1 X0 | ||
| 102 | * byte 5: Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 | ||
| 103 | * byte 6: 0 y9 y8 y7 1 m r l | ||
| 104 | * byte 7: 0 y6 y5 y4 y3 y2 y1 y0 | ||
| 105 | * byte 8: 0 z6 z5 z4 z3 z2 z1 z0 | ||
| 106 | * | ||
| 107 | * CAPITALS = stick, miniscules = touchpad | ||
| 108 | * | ||
| 78 | * ?'s can have different meanings on different models, | 109 | * ?'s can have different meanings on different models, |
| 79 | * such as wheel rotation, extra buttons, stick buttons | 110 | * such as wheel rotation, extra buttons, stick buttons |
| 80 | * on a dualpoint, etc. | 111 | * on a dualpoint, etc. |
| 81 | */ | 112 | */ |
| 82 | 113 | ||
| 114 | static bool alps_is_valid_first_byte(const struct alps_model_info *model, | ||
| 115 | unsigned char data) | ||
| 116 | { | ||
| 117 | return (data & model->mask0) == model->byte0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static void alps_report_buttons(struct psmouse *psmouse, | ||
| 121 | struct input_dev *dev1, struct input_dev *dev2, | ||
| 122 | int left, int right, int middle) | ||
| 123 | { | ||
| 124 | struct input_dev *dev; | ||
| 125 | |||
| 126 | /* | ||
| 127 | * If shared button has already been reported on the | ||
| 128 | * other device (dev2) then this event should be also | ||
| 129 | * sent through that device. | ||
| 130 | */ | ||
| 131 | dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; | ||
| 132 | input_report_key(dev, BTN_LEFT, left); | ||
| 133 | |||
| 134 | dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; | ||
| 135 | input_report_key(dev, BTN_RIGHT, right); | ||
| 136 | |||
| 137 | dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; | ||
| 138 | input_report_key(dev, BTN_MIDDLE, middle); | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Sync the _other_ device now, we'll do the first | ||
| 142 | * device later once we report the rest of the events. | ||
| 143 | */ | ||
| 144 | input_sync(dev2); | ||
| 145 | } | ||
| 146 | |||
| 83 | static void alps_process_packet(struct psmouse *psmouse) | 147 | static void alps_process_packet(struct psmouse *psmouse) |
| 84 | { | 148 | { |
| 85 | struct alps_data *priv = psmouse->private; | 149 | struct alps_data *priv = psmouse->private; |
| 150 | const struct alps_model_info *model = priv->i; | ||
| 86 | unsigned char *packet = psmouse->packet; | 151 | unsigned char *packet = psmouse->packet; |
| 87 | struct input_dev *dev = psmouse->dev; | 152 | struct input_dev *dev = psmouse->dev; |
| 88 | struct input_dev *dev2 = priv->dev2; | 153 | struct input_dev *dev2 = priv->dev2; |
| 89 | int x, y, z, ges, fin, left, right, middle; | 154 | int x, y, z, ges, fin, left, right, middle; |
| 90 | int back = 0, forward = 0; | 155 | int back = 0, forward = 0; |
| 91 | 156 | ||
| 92 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | 157 | if (model->flags & ALPS_OLDPROTO) { |
| 93 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | ||
| 94 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | ||
| 95 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | ||
| 96 | input_report_rel(dev2, REL_X, | ||
| 97 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
| 98 | input_report_rel(dev2, REL_Y, | ||
| 99 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
| 100 | input_sync(dev2); | ||
| 101 | return; | ||
| 102 | } | ||
| 103 | |||
| 104 | if (priv->i->flags & ALPS_OLDPROTO) { | ||
| 105 | left = packet[2] & 0x10; | 158 | left = packet[2] & 0x10; |
| 106 | right = packet[2] & 0x08; | 159 | right = packet[2] & 0x08; |
| 107 | middle = 0; | 160 | middle = 0; |
| @@ -117,12 +170,12 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 117 | z = packet[5]; | 170 | z = packet[5]; |
| 118 | } | 171 | } |
| 119 | 172 | ||
| 120 | if (priv->i->flags & ALPS_FW_BK_1) { | 173 | if (model->flags & ALPS_FW_BK_1) { |
| 121 | back = packet[0] & 0x10; | 174 | back = packet[0] & 0x10; |
| 122 | forward = packet[2] & 4; | 175 | forward = packet[2] & 4; |
| 123 | } | 176 | } |
| 124 | 177 | ||
| 125 | if (priv->i->flags & ALPS_FW_BK_2) { | 178 | if (model->flags & ALPS_FW_BK_2) { |
| 126 | back = packet[3] & 4; | 179 | back = packet[3] & 4; |
| 127 | forward = packet[2] & 4; | 180 | forward = packet[2] & 4; |
| 128 | if ((middle = forward && back)) | 181 | if ((middle = forward && back)) |
| @@ -132,25 +185,21 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 132 | ges = packet[2] & 1; | 185 | ges = packet[2] & 1; |
| 133 | fin = packet[2] & 2; | 186 | fin = packet[2] & 2; |
| 134 | 187 | ||
| 135 | if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) { | 188 | if ((model->flags & ALPS_DUALPOINT) && z == 127) { |
| 136 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); | 189 | input_report_rel(dev2, REL_X, (x > 383 ? (x - 768) : x)); |
| 137 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); | 190 | input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y)); |
| 138 | 191 | ||
| 139 | input_report_key(dev2, BTN_LEFT, left); | 192 | alps_report_buttons(psmouse, dev2, dev, left, right, middle); |
| 140 | input_report_key(dev2, BTN_RIGHT, right); | ||
| 141 | input_report_key(dev2, BTN_MIDDLE, middle); | ||
| 142 | 193 | ||
| 143 | input_sync(dev); | ||
| 144 | input_sync(dev2); | 194 | input_sync(dev2); |
| 145 | return; | 195 | return; |
| 146 | } | 196 | } |
| 147 | 197 | ||
| 148 | input_report_key(dev, BTN_LEFT, left); | 198 | alps_report_buttons(psmouse, dev, dev2, left, right, middle); |
| 149 | input_report_key(dev, BTN_RIGHT, right); | ||
| 150 | input_report_key(dev, BTN_MIDDLE, middle); | ||
| 151 | 199 | ||
| 152 | /* Convert hardware tap to a reasonable Z value */ | 200 | /* Convert hardware tap to a reasonable Z value */ |
| 153 | if (ges && !fin) z = 40; | 201 | if (ges && !fin) |
| 202 | z = 40; | ||
| 154 | 203 | ||
| 155 | /* | 204 | /* |
| 156 | * A "tap and drag" operation is reported by the hardware as a transition | 205 | * A "tap and drag" operation is reported by the hardware as a transition |
| @@ -166,8 +215,10 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 166 | } | 215 | } |
| 167 | priv->prev_fin = fin; | 216 | priv->prev_fin = fin; |
| 168 | 217 | ||
| 169 | if (z > 30) input_report_key(dev, BTN_TOUCH, 1); | 218 | if (z > 30) |
| 170 | if (z < 25) input_report_key(dev, BTN_TOUCH, 0); | 219 | input_report_key(dev, BTN_TOUCH, 1); |
| 220 | if (z < 25) | ||
| 221 | input_report_key(dev, BTN_TOUCH, 0); | ||
| 171 | 222 | ||
| 172 | if (z > 0) { | 223 | if (z > 0) { |
| 173 | input_report_abs(dev, ABS_X, x); | 224 | input_report_abs(dev, ABS_X, x); |
| @@ -177,36 +228,186 @@ static void alps_process_packet(struct psmouse *psmouse) | |||
| 177 | input_report_abs(dev, ABS_PRESSURE, z); | 228 | input_report_abs(dev, ABS_PRESSURE, z); |
| 178 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 229 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
| 179 | 230 | ||
| 180 | if (priv->i->flags & ALPS_WHEEL) | 231 | if (model->flags & ALPS_WHEEL) |
| 181 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); | 232 | input_report_rel(dev, REL_WHEEL, ((packet[2] << 1) & 0x08) - ((packet[0] >> 4) & 0x07)); |
| 182 | 233 | ||
| 183 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 234 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
| 184 | input_report_key(dev, BTN_FORWARD, forward); | 235 | input_report_key(dev, BTN_FORWARD, forward); |
| 185 | input_report_key(dev, BTN_BACK, back); | 236 | input_report_key(dev, BTN_BACK, back); |
| 186 | } | 237 | } |
| 187 | 238 | ||
| 239 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
| 240 | input_report_key(dev, BTN_0, packet[2] & 4); | ||
| 241 | input_report_key(dev, BTN_1, packet[0] & 0x10); | ||
| 242 | input_report_key(dev, BTN_2, packet[3] & 4); | ||
| 243 | input_report_key(dev, BTN_3, packet[0] & 0x20); | ||
| 244 | } | ||
| 245 | |||
| 188 | input_sync(dev); | 246 | input_sync(dev); |
| 189 | } | 247 | } |
| 190 | 248 | ||
| 249 | static void alps_report_bare_ps2_packet(struct psmouse *psmouse, | ||
| 250 | unsigned char packet[], | ||
| 251 | bool report_buttons) | ||
| 252 | { | ||
| 253 | struct alps_data *priv = psmouse->private; | ||
| 254 | struct input_dev *dev2 = priv->dev2; | ||
| 255 | |||
| 256 | if (report_buttons) | ||
| 257 | alps_report_buttons(psmouse, dev2, psmouse->dev, | ||
| 258 | packet[0] & 1, packet[0] & 2, packet[0] & 4); | ||
| 259 | |||
| 260 | input_report_rel(dev2, REL_X, | ||
| 261 | packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0); | ||
| 262 | input_report_rel(dev2, REL_Y, | ||
| 263 | packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0); | ||
| 264 | |||
| 265 | input_sync(dev2); | ||
| 266 | } | ||
| 267 | |||
| 268 | static psmouse_ret_t alps_handle_interleaved_ps2(struct psmouse *psmouse) | ||
| 269 | { | ||
| 270 | struct alps_data *priv = psmouse->private; | ||
| 271 | |||
| 272 | if (psmouse->pktcnt < 6) | ||
| 273 | return PSMOUSE_GOOD_DATA; | ||
| 274 | |||
| 275 | if (psmouse->pktcnt == 6) { | ||
| 276 | /* | ||
| 277 | * Start a timer to flush the packet if it ends up last | ||
| 278 | * 6-byte packet in the stream. Timer needs to fire | ||
| 279 | * psmouse core times out itself. 20 ms should be enough | ||
| 280 | * to decide if we are getting more data or not. | ||
| 281 | */ | ||
| 282 | mod_timer(&priv->timer, jiffies + msecs_to_jiffies(20)); | ||
| 283 | return PSMOUSE_GOOD_DATA; | ||
| 284 | } | ||
| 285 | |||
| 286 | del_timer(&priv->timer); | ||
| 287 | |||
| 288 | if (psmouse->packet[6] & 0x80) { | ||
| 289 | |||
| 290 | /* | ||
| 291 | * Highest bit is set - that means we either had | ||
| 292 | * complete ALPS packet and this is start of the | ||
| 293 | * next packet or we got garbage. | ||
| 294 | */ | ||
| 295 | |||
| 296 | if (((psmouse->packet[3] | | ||
| 297 | psmouse->packet[4] | | ||
| 298 | psmouse->packet[5]) & 0x80) || | ||
| 299 | (!alps_is_valid_first_byte(priv->i, psmouse->packet[6]))) { | ||
| 300 | dbg("refusing packet %x %x %x %x " | ||
| 301 | "(suspected interleaved ps/2)\n", | ||
| 302 | psmouse->packet[3], psmouse->packet[4], | ||
| 303 | psmouse->packet[5], psmouse->packet[6]); | ||
| 304 | return PSMOUSE_BAD_DATA; | ||
| 305 | } | ||
| 306 | |||
| 307 | alps_process_packet(psmouse); | ||
| 308 | |||
| 309 | /* Continue with the next packet */ | ||
| 310 | psmouse->packet[0] = psmouse->packet[6]; | ||
| 311 | psmouse->pktcnt = 1; | ||
| 312 | |||
| 313 | } else { | ||
| 314 | |||
| 315 | /* | ||
| 316 | * High bit is 0 - that means that we indeed got a PS/2 | ||
| 317 | * packet in the middle of ALPS packet. | ||
| 318 | * | ||
| 319 | * There is also possibility that we got 6-byte ALPS | ||
| 320 | * packet followed by 3-byte packet from trackpoint. We | ||
| 321 | * can not distinguish between these 2 scenarios but | ||
| 322 | * becase the latter is unlikely to happen in course of | ||
| 323 | * normal operation (user would need to press all | ||
| 324 | * buttons on the pad and start moving trackpoint | ||
| 325 | * without touching the pad surface) we assume former. | ||
| 326 | * Even if we are wrong the wost thing that would happen | ||
| 327 | * the cursor would jump but we should not get protocol | ||
| 328 | * desynchronization. | ||
| 329 | */ | ||
| 330 | |||
| 331 | alps_report_bare_ps2_packet(psmouse, &psmouse->packet[3], | ||
| 332 | false); | ||
| 333 | |||
| 334 | /* | ||
| 335 | * Continue with the standard ALPS protocol handling, | ||
| 336 | * but make sure we won't process it as an interleaved | ||
| 337 | * packet again, which may happen if all buttons are | ||
| 338 | * pressed. To avoid this let's reset the 4th bit which | ||
| 339 | * is normally 1. | ||
| 340 | */ | ||
| 341 | psmouse->packet[3] = psmouse->packet[6] & 0xf7; | ||
| 342 | psmouse->pktcnt = 4; | ||
| 343 | } | ||
| 344 | |||
| 345 | return PSMOUSE_GOOD_DATA; | ||
| 346 | } | ||
| 347 | |||
| 348 | static void alps_flush_packet(unsigned long data) | ||
| 349 | { | ||
| 350 | struct psmouse *psmouse = (struct psmouse *)data; | ||
| 351 | |||
| 352 | serio_pause_rx(psmouse->ps2dev.serio); | ||
| 353 | |||
| 354 | if (psmouse->pktcnt == 6) { | ||
| 355 | |||
| 356 | /* | ||
| 357 | * We did not any more data in reasonable amount of time. | ||
| 358 | * Validate the last 3 bytes and process as a standard | ||
| 359 | * ALPS packet. | ||
| 360 | */ | ||
| 361 | if ((psmouse->packet[3] | | ||
| 362 | psmouse->packet[4] | | ||
| 363 | psmouse->packet[5]) & 0x80) { | ||
| 364 | dbg("refusing packet %x %x %x " | ||
| 365 | "(suspected interleaved ps/2)\n", | ||
| 366 | psmouse->packet[3], psmouse->packet[4], | ||
| 367 | psmouse->packet[5]); | ||
| 368 | } else { | ||
| 369 | alps_process_packet(psmouse); | ||
| 370 | } | ||
| 371 | psmouse->pktcnt = 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | serio_continue_rx(psmouse->ps2dev.serio); | ||
| 375 | } | ||
| 376 | |||
| 191 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | 377 | static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) |
| 192 | { | 378 | { |
| 193 | struct alps_data *priv = psmouse->private; | 379 | struct alps_data *priv = psmouse->private; |
| 380 | const struct alps_model_info *model = priv->i; | ||
| 194 | 381 | ||
| 195 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ | 382 | if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */ |
| 196 | if (psmouse->pktcnt == 3) { | 383 | if (psmouse->pktcnt == 3) { |
| 197 | alps_process_packet(psmouse); | 384 | alps_report_bare_ps2_packet(psmouse, psmouse->packet, |
| 385 | true); | ||
| 198 | return PSMOUSE_FULL_PACKET; | 386 | return PSMOUSE_FULL_PACKET; |
| 199 | } | 387 | } |
| 200 | return PSMOUSE_GOOD_DATA; | 388 | return PSMOUSE_GOOD_DATA; |
| 201 | } | 389 | } |
| 202 | 390 | ||
| 203 | if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0) | 391 | /* Check for PS/2 packet stuffed in the middle of ALPS packet. */ |
| 392 | |||
| 393 | if ((model->flags & ALPS_PS2_INTERLEAVED) && | ||
| 394 | psmouse->pktcnt >= 4 && (psmouse->packet[3] & 0x0f) == 0x0f) { | ||
| 395 | return alps_handle_interleaved_ps2(psmouse); | ||
| 396 | } | ||
| 397 | |||
| 398 | if (!alps_is_valid_first_byte(model, psmouse->packet[0])) { | ||
| 399 | dbg("refusing packet[0] = %x (mask0 = %x, byte0 = %x)\n", | ||
| 400 | psmouse->packet[0], model->mask0, model->byte0); | ||
| 204 | return PSMOUSE_BAD_DATA; | 401 | return PSMOUSE_BAD_DATA; |
| 402 | } | ||
| 205 | 403 | ||
| 206 | /* Bytes 2 - 6 should have 0 in the highest bit */ | 404 | /* Bytes 2 - 6 should have 0 in the highest bit */ |
| 207 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && | 405 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 && |
| 208 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) | 406 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
| 407 | dbg("refusing packet[%i] = %x\n", | ||
| 408 | psmouse->pktcnt - 1, psmouse->packet[psmouse->pktcnt - 1]); | ||
| 209 | return PSMOUSE_BAD_DATA; | 409 | return PSMOUSE_BAD_DATA; |
| 410 | } | ||
| 210 | 411 | ||
| 211 | if (psmouse->pktcnt == 6) { | 412 | if (psmouse->pktcnt == 6) { |
| 212 | alps_process_packet(psmouse); | 413 | alps_process_packet(psmouse); |
| @@ -393,15 +594,12 @@ static int alps_poll(struct psmouse *psmouse) | |||
| 393 | return 0; | 594 | return 0; |
| 394 | } | 595 | } |
| 395 | 596 | ||
| 396 | static int alps_hw_init(struct psmouse *psmouse, int *version) | 597 | static int alps_hw_init(struct psmouse *psmouse) |
| 397 | { | 598 | { |
| 398 | struct alps_data *priv = psmouse->private; | 599 | struct alps_data *priv = psmouse->private; |
| 600 | const struct alps_model_info *model = priv->i; | ||
| 399 | 601 | ||
| 400 | priv->i = alps_get_model(psmouse, version); | 602 | if ((model->flags & ALPS_PASS) && |
| 401 | if (!priv->i) | ||
| 402 | return -1; | ||
| 403 | |||
| 404 | if ((priv->i->flags & ALPS_PASS) && | ||
| 405 | alps_passthrough_mode(psmouse, true)) { | 603 | alps_passthrough_mode(psmouse, true)) { |
| 406 | return -1; | 604 | return -1; |
| 407 | } | 605 | } |
| @@ -416,7 +614,7 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
| 416 | return -1; | 614 | return -1; |
| 417 | } | 615 | } |
| 418 | 616 | ||
| 419 | if ((priv->i->flags & ALPS_PASS) && | 617 | if ((model->flags & ALPS_PASS) && |
| 420 | alps_passthrough_mode(psmouse, false)) { | 618 | alps_passthrough_mode(psmouse, false)) { |
| 421 | return -1; | 619 | return -1; |
| 422 | } | 620 | } |
| @@ -432,12 +630,15 @@ static int alps_hw_init(struct psmouse *psmouse, int *version) | |||
| 432 | 630 | ||
| 433 | static int alps_reconnect(struct psmouse *psmouse) | 631 | static int alps_reconnect(struct psmouse *psmouse) |
| 434 | { | 632 | { |
| 633 | const struct alps_model_info *model; | ||
| 634 | |||
| 435 | psmouse_reset(psmouse); | 635 | psmouse_reset(psmouse); |
| 436 | 636 | ||
| 437 | if (alps_hw_init(psmouse, NULL)) | 637 | model = alps_get_model(psmouse, NULL); |
| 638 | if (!model) | ||
| 438 | return -1; | 639 | return -1; |
| 439 | 640 | ||
| 440 | return 0; | 641 | return alps_hw_init(psmouse); |
| 441 | } | 642 | } |
| 442 | 643 | ||
| 443 | static void alps_disconnect(struct psmouse *psmouse) | 644 | static void alps_disconnect(struct psmouse *psmouse) |
| @@ -445,6 +646,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
| 445 | struct alps_data *priv = psmouse->private; | 646 | struct alps_data *priv = psmouse->private; |
| 446 | 647 | ||
| 447 | psmouse_reset(psmouse); | 648 | psmouse_reset(psmouse); |
| 649 | del_timer_sync(&priv->timer); | ||
| 448 | input_unregister_device(priv->dev2); | 650 | input_unregister_device(priv->dev2); |
| 449 | kfree(priv); | 651 | kfree(priv); |
| 450 | } | 652 | } |
| @@ -452,6 +654,7 @@ static void alps_disconnect(struct psmouse *psmouse) | |||
| 452 | int alps_init(struct psmouse *psmouse) | 654 | int alps_init(struct psmouse *psmouse) |
| 453 | { | 655 | { |
| 454 | struct alps_data *priv; | 656 | struct alps_data *priv; |
| 657 | const struct alps_model_info *model; | ||
| 455 | struct input_dev *dev1 = psmouse->dev, *dev2; | 658 | struct input_dev *dev1 = psmouse->dev, *dev2; |
| 456 | int version; | 659 | int version; |
| 457 | 660 | ||
| @@ -461,35 +664,63 @@ int alps_init(struct psmouse *psmouse) | |||
| 461 | goto init_fail; | 664 | goto init_fail; |
| 462 | 665 | ||
| 463 | priv->dev2 = dev2; | 666 | priv->dev2 = dev2; |
| 667 | setup_timer(&priv->timer, alps_flush_packet, (unsigned long)psmouse); | ||
| 668 | |||
| 464 | psmouse->private = priv; | 669 | psmouse->private = priv; |
| 465 | 670 | ||
| 466 | if (alps_hw_init(psmouse, &version)) | 671 | model = alps_get_model(psmouse, &version); |
| 672 | if (!model) | ||
| 673 | goto init_fail; | ||
| 674 | |||
| 675 | priv->i = model; | ||
| 676 | |||
| 677 | if (alps_hw_init(psmouse)) | ||
| 467 | goto init_fail; | 678 | goto init_fail; |
| 468 | 679 | ||
| 680 | /* | ||
| 681 | * Undo part of setup done for us by psmouse core since touchpad | ||
| 682 | * is not a relative device. | ||
| 683 | */ | ||
| 684 | __clear_bit(EV_REL, dev1->evbit); | ||
| 685 | __clear_bit(REL_X, dev1->relbit); | ||
| 686 | __clear_bit(REL_Y, dev1->relbit); | ||
| 687 | |||
| 688 | /* | ||
| 689 | * Now set up our capabilities. | ||
| 690 | */ | ||
| 469 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); | 691 | dev1->evbit[BIT_WORD(EV_KEY)] |= BIT_MASK(EV_KEY); |
| 470 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); | 692 | dev1->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH); |
| 471 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); | 693 | dev1->keybit[BIT_WORD(BTN_TOOL_FINGER)] |= BIT_MASK(BTN_TOOL_FINGER); |
| 472 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 694 | dev1->keybit[BIT_WORD(BTN_LEFT)] |= |
| 473 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 695 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
| 474 | 696 | ||
| 475 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); | 697 | dev1->evbit[BIT_WORD(EV_ABS)] |= BIT_MASK(EV_ABS); |
| 476 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); | 698 | input_set_abs_params(dev1, ABS_X, 0, 1023, 0, 0); |
| 477 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); | 699 | input_set_abs_params(dev1, ABS_Y, 0, 767, 0, 0); |
| 478 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); | 700 | input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0); |
| 479 | 701 | ||
| 480 | if (priv->i->flags & ALPS_WHEEL) { | 702 | if (model->flags & ALPS_WHEEL) { |
| 481 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); | 703 | dev1->evbit[BIT_WORD(EV_REL)] |= BIT_MASK(EV_REL); |
| 482 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); | 704 | dev1->relbit[BIT_WORD(REL_WHEEL)] |= BIT_MASK(REL_WHEEL); |
| 483 | } | 705 | } |
| 484 | 706 | ||
| 485 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { | 707 | if (model->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
| 486 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); | 708 | dev1->keybit[BIT_WORD(BTN_FORWARD)] |= BIT_MASK(BTN_FORWARD); |
| 487 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); | 709 | dev1->keybit[BIT_WORD(BTN_BACK)] |= BIT_MASK(BTN_BACK); |
| 488 | } | 710 | } |
| 489 | 711 | ||
| 712 | if (model->flags & ALPS_FOUR_BUTTONS) { | ||
| 713 | dev1->keybit[BIT_WORD(BTN_0)] |= BIT_MASK(BTN_0); | ||
| 714 | dev1->keybit[BIT_WORD(BTN_1)] |= BIT_MASK(BTN_1); | ||
| 715 | dev1->keybit[BIT_WORD(BTN_2)] |= BIT_MASK(BTN_2); | ||
| 716 | dev1->keybit[BIT_WORD(BTN_3)] |= BIT_MASK(BTN_3); | ||
| 717 | } else { | ||
| 718 | dev1->keybit[BIT_WORD(BTN_MIDDLE)] |= BIT_MASK(BTN_MIDDLE); | ||
| 719 | } | ||
| 720 | |||
| 490 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); | 721 | snprintf(priv->phys, sizeof(priv->phys), "%s/input1", psmouse->ps2dev.serio->phys); |
| 491 | dev2->phys = priv->phys; | 722 | dev2->phys = priv->phys; |
| 492 | dev2->name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; | 723 | dev2->name = (model->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse"; |
| 493 | dev2->id.bustype = BUS_I8042; | 724 | dev2->id.bustype = BUS_I8042; |
| 494 | dev2->id.vendor = 0x0002; | 725 | dev2->id.vendor = 0x0002; |
| 495 | dev2->id.product = PSMOUSE_ALPS; | 726 | dev2->id.product = PSMOUSE_ALPS; |
| @@ -497,9 +728,9 @@ int alps_init(struct psmouse *psmouse) | |||
| 497 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; | 728 | dev2->dev.parent = &psmouse->ps2dev.serio->dev; |
| 498 | 729 | ||
| 499 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 730 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
| 500 | dev2->relbit[BIT_WORD(REL_X)] |= BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 731 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
| 501 | dev2->keybit[BIT_WORD(BTN_LEFT)] |= BIT_MASK(BTN_LEFT) | | 732 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
| 502 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 733 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
| 503 | 734 | ||
| 504 | if (input_register_device(priv->dev2)) | 735 | if (input_register_device(priv->dev2)) |
| 505 | goto init_fail; | 736 | goto init_fail; |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index bc87936fee1a..904ed8b3c8be 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
| @@ -23,6 +23,7 @@ struct alps_data { | |||
| 23 | char phys[32]; /* Phys */ | 23 | char phys[32]; /* Phys */ |
| 24 | const struct alps_model_info *i;/* Info */ | 24 | const struct alps_model_info *i;/* Info */ |
| 25 | int prev_fin; /* Finger bit from previous packet */ | 25 | int prev_fin; /* Finger bit from previous packet */ |
| 26 | struct timer_list timer; | ||
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 28 | #ifdef CONFIG_MOUSE_PS2_ALPS | 29 | #ifdef CONFIG_MOUSE_PS2_ALPS |
diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 908b5b44052f..53ec7ddd1826 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c | |||
| @@ -205,8 +205,8 @@ struct atp { | |||
| 205 | bool overflow_warned; | 205 | bool overflow_warned; |
| 206 | int x_old; /* last reported x/y, */ | 206 | int x_old; /* last reported x/y, */ |
| 207 | int y_old; /* used for smoothing */ | 207 | int y_old; /* used for smoothing */ |
| 208 | signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; | 208 | u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; |
| 209 | signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; | 209 | u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; |
| 210 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; | 210 | int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; |
| 211 | int idlecount; /* number of empty packets */ | 211 | int idlecount; /* number of empty packets */ |
| 212 | struct work_struct work; | 212 | struct work_struct work; |
| @@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) | |||
| 531 | 531 | ||
| 532 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { | 532 | for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { |
| 533 | /* accumulate the change */ | 533 | /* accumulate the change */ |
| 534 | signed char change = dev->xy_old[i] - dev->xy_cur[i]; | 534 | int change = dev->xy_old[i] - dev->xy_cur[i]; |
| 535 | dev->xy_acc[i] -= change; | 535 | dev->xy_acc[i] -= change; |
| 536 | 536 | ||
| 537 | /* prevent down drifting */ | 537 | /* prevent down drifting */ |
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 0d1d33468b43..4f8fe0886b2a 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c | |||
| @@ -139,6 +139,7 @@ struct tp_finger { | |||
| 139 | /* trackpad finger data size, empirically at least ten fingers */ | 139 | /* trackpad finger data size, empirically at least ten fingers */ |
| 140 | #define SIZEOF_FINGER sizeof(struct tp_finger) | 140 | #define SIZEOF_FINGER sizeof(struct tp_finger) |
| 141 | #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) | 141 | #define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER) |
| 142 | #define MAX_FINGER_ORIENTATION 16384 | ||
| 142 | 143 | ||
| 143 | /* device-specific parameters */ | 144 | /* device-specific parameters */ |
| 144 | struct bcm5974_param { | 145 | struct bcm5974_param { |
| @@ -284,6 +285,26 @@ static void setup_events_to_report(struct input_dev *input_dev, | |||
| 284 | input_set_abs_params(input_dev, ABS_Y, | 285 | input_set_abs_params(input_dev, ABS_Y, |
| 285 | 0, cfg->y.dim, cfg->y.fuzz, 0); | 286 | 0, cfg->y.dim, cfg->y.fuzz, 0); |
| 286 | 287 | ||
| 288 | /* finger touch area */ | ||
| 289 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, | ||
| 290 | cfg->w.devmin, cfg->w.devmax, 0, 0); | ||
| 291 | input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, | ||
| 292 | cfg->w.devmin, cfg->w.devmax, 0, 0); | ||
| 293 | /* finger approach area */ | ||
| 294 | input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, | ||
| 295 | cfg->w.devmin, cfg->w.devmax, 0, 0); | ||
| 296 | input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, | ||
| 297 | cfg->w.devmin, cfg->w.devmax, 0, 0); | ||
| 298 | /* finger orientation */ | ||
| 299 | input_set_abs_params(input_dev, ABS_MT_ORIENTATION, | ||
| 300 | -MAX_FINGER_ORIENTATION, | ||
| 301 | MAX_FINGER_ORIENTATION, 0, 0); | ||
| 302 | /* finger position */ | ||
| 303 | input_set_abs_params(input_dev, ABS_MT_POSITION_X, | ||
| 304 | cfg->x.devmin, cfg->x.devmax, 0, 0); | ||
| 305 | input_set_abs_params(input_dev, ABS_MT_POSITION_Y, | ||
| 306 | cfg->y.devmin, cfg->y.devmax, 0, 0); | ||
| 307 | |||
| 287 | __set_bit(EV_KEY, input_dev->evbit); | 308 | __set_bit(EV_KEY, input_dev->evbit); |
| 288 | __set_bit(BTN_TOUCH, input_dev->keybit); | 309 | __set_bit(BTN_TOUCH, input_dev->keybit); |
| 289 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | 310 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); |
| @@ -310,13 +331,29 @@ static int report_bt_state(struct bcm5974 *dev, int size) | |||
| 310 | return 0; | 331 | return 0; |
| 311 | } | 332 | } |
| 312 | 333 | ||
| 334 | static void report_finger_data(struct input_dev *input, | ||
| 335 | const struct bcm5974_config *cfg, | ||
| 336 | const struct tp_finger *f) | ||
| 337 | { | ||
| 338 | input_report_abs(input, ABS_MT_TOUCH_MAJOR, raw2int(f->force_major)); | ||
| 339 | input_report_abs(input, ABS_MT_TOUCH_MINOR, raw2int(f->force_minor)); | ||
| 340 | input_report_abs(input, ABS_MT_WIDTH_MAJOR, raw2int(f->size_major)); | ||
| 341 | input_report_abs(input, ABS_MT_WIDTH_MINOR, raw2int(f->size_minor)); | ||
| 342 | input_report_abs(input, ABS_MT_ORIENTATION, | ||
| 343 | MAX_FINGER_ORIENTATION - raw2int(f->orientation)); | ||
| 344 | input_report_abs(input, ABS_MT_POSITION_X, raw2int(f->abs_x)); | ||
| 345 | input_report_abs(input, ABS_MT_POSITION_Y, | ||
| 346 | cfg->y.devmin + cfg->y.devmax - raw2int(f->abs_y)); | ||
| 347 | input_mt_sync(input); | ||
| 348 | } | ||
| 349 | |||
| 313 | /* report trackpad data as logical trackpad state */ | 350 | /* report trackpad data as logical trackpad state */ |
| 314 | static int report_tp_state(struct bcm5974 *dev, int size) | 351 | static int report_tp_state(struct bcm5974 *dev, int size) |
| 315 | { | 352 | { |
| 316 | const struct bcm5974_config *c = &dev->cfg; | 353 | const struct bcm5974_config *c = &dev->cfg; |
| 317 | const struct tp_finger *f; | 354 | const struct tp_finger *f; |
| 318 | struct input_dev *input = dev->input; | 355 | struct input_dev *input = dev->input; |
| 319 | int raw_p, raw_w, raw_x, raw_y, raw_n; | 356 | int raw_p, raw_w, raw_x, raw_y, raw_n, i; |
| 320 | int ptest, origin, ibt = 0, nmin = 0, nmax = 0; | 357 | int ptest, origin, ibt = 0, nmin = 0, nmax = 0; |
| 321 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; | 358 | int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0; |
| 322 | 359 | ||
| @@ -329,6 +366,11 @@ static int report_tp_state(struct bcm5974 *dev, int size) | |||
| 329 | 366 | ||
| 330 | /* always track the first finger; when detached, start over */ | 367 | /* always track the first finger; when detached, start over */ |
| 331 | if (raw_n) { | 368 | if (raw_n) { |
| 369 | |||
| 370 | /* report raw trackpad data */ | ||
| 371 | for (i = 0; i < raw_n; i++) | ||
| 372 | report_finger_data(input, c, &f[i]); | ||
| 373 | |||
| 332 | raw_p = raw2int(f->force_major); | 374 | raw_p = raw2int(f->force_major); |
| 333 | raw_w = raw2int(f->size_major); | 375 | raw_w = raw2int(f->size_major); |
| 334 | raw_x = raw2int(f->abs_x); | 376 | raw_x = raw2int(f->abs_x); |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index fda35e615abf..a138b5da79f9 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
| 14 | #include <linux/slab.h> | ||
| 14 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 15 | #include <linux/input.h> | 16 | #include <linux/input.h> |
| 16 | #include <linux/serio.h> | 17 | #include <linux/serio.h> |
| @@ -420,6 +421,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
| 420 | 421 | ||
| 421 | __set_bit(EV_KEY, dev->evbit); | 422 | __set_bit(EV_KEY, dev->evbit); |
| 422 | __set_bit(EV_ABS, dev->evbit); | 423 | __set_bit(EV_ABS, dev->evbit); |
| 424 | __clear_bit(EV_REL, dev->evbit); | ||
| 423 | 425 | ||
| 424 | __set_bit(BTN_LEFT, dev->keybit); | 426 | __set_bit(BTN_LEFT, dev->keybit); |
| 425 | __set_bit(BTN_RIGHT, dev->keybit); | 427 | __set_bit(BTN_RIGHT, dev->keybit); |
diff --git a/drivers/input/mouse/hgpk.c b/drivers/input/mouse/hgpk.c index de1e553028b7..08d66d820d2b 100644 --- a/drivers/input/mouse/hgpk.c +++ b/drivers/input/mouse/hgpk.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | #define DEBUG | 32 | #define DEBUG |
| 33 | #include <linux/slab.h> | ||
| 33 | #include <linux/input.h> | 34 | #include <linux/input.h> |
| 34 | #include <linux/serio.h> | 35 | #include <linux/serio.h> |
| 35 | #include <linux/libps2.h> | 36 | #include <linux/libps2.h> |
| @@ -68,10 +69,6 @@ module_param(post_interrupt_delay, int, 0644); | |||
| 68 | MODULE_PARM_DESC(post_interrupt_delay, | 69 | MODULE_PARM_DESC(post_interrupt_delay, |
| 69 | "delay (ms) before recal after recal interrupt detected"); | 70 | "delay (ms) before recal after recal interrupt detected"); |
| 70 | 71 | ||
| 71 | static int autorecal = 1; | ||
| 72 | module_param(autorecal, int, 0644); | ||
| 73 | MODULE_PARM_DESC(autorecal, "enable recalibration in the driver"); | ||
| 74 | |||
| 75 | /* | 72 | /* |
| 76 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" | 73 | * When the touchpad gets ultra-sensitive, one can keep their finger 1/2" |
| 77 | * above the pad and still have it send packets. This causes a jump cursor | 74 | * above the pad and still have it send packets. This causes a jump cursor |
| @@ -427,22 +424,8 @@ static void hgpk_recalib_work(struct work_struct *work) | |||
| 427 | 424 | ||
| 428 | static int hgpk_register(struct psmouse *psmouse) | 425 | static int hgpk_register(struct psmouse *psmouse) |
| 429 | { | 426 | { |
| 430 | struct input_dev *dev = psmouse->dev; | ||
| 431 | int err; | 427 | int err; |
| 432 | 428 | ||
| 433 | /* unset the things that psmouse-base sets which we don't have */ | ||
| 434 | __clear_bit(BTN_MIDDLE, dev->keybit); | ||
| 435 | |||
| 436 | /* set the things we do have */ | ||
| 437 | __set_bit(EV_KEY, dev->evbit); | ||
| 438 | __set_bit(EV_REL, dev->evbit); | ||
| 439 | |||
| 440 | __set_bit(REL_X, dev->relbit); | ||
| 441 | __set_bit(REL_Y, dev->relbit); | ||
| 442 | |||
| 443 | __set_bit(BTN_LEFT, dev->keybit); | ||
| 444 | __set_bit(BTN_RIGHT, dev->keybit); | ||
| 445 | |||
| 446 | /* register handlers */ | 429 | /* register handlers */ |
| 447 | psmouse->protocol_handler = hgpk_process_byte; | 430 | psmouse->protocol_handler = hgpk_process_byte; |
| 448 | psmouse->poll = hgpk_poll; | 431 | psmouse->poll = hgpk_poll; |
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c index 82811558ec33..c31ad11df6bb 100644 --- a/drivers/input/mouse/lifebook.c +++ b/drivers/input/mouse/lifebook.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/serio.h> | 16 | #include <linux/serio.h> |
| 17 | #include <linux/libps2.h> | 17 | #include <linux/libps2.h> |
| 18 | #include <linux/dmi.h> | 18 | #include <linux/dmi.h> |
| 19 | #include <linux/slab.h> | ||
| 19 | 20 | ||
| 20 | #include "psmouse.h" | 21 | #include "psmouse.h" |
| 21 | #include "lifebook.h" | 22 | #include "lifebook.h" |
| @@ -25,11 +26,13 @@ struct lifebook_data { | |||
| 25 | char phys[32]; | 26 | char phys[32]; |
| 26 | }; | 27 | }; |
| 27 | 28 | ||
| 29 | static bool lifebook_present; | ||
| 30 | |||
| 28 | static const char *desired_serio_phys; | 31 | static const char *desired_serio_phys; |
| 29 | 32 | ||
| 30 | static int lifebook_set_serio_phys(const struct dmi_system_id *d) | 33 | static int lifebook_limit_serio3(const struct dmi_system_id *d) |
| 31 | { | 34 | { |
| 32 | desired_serio_phys = d->driver_data; | 35 | desired_serio_phys = "isa0060/serio3"; |
| 33 | return 0; | 36 | return 0; |
| 34 | } | 37 | } |
| 35 | 38 | ||
| @@ -41,53 +44,58 @@ static int lifebook_set_6byte_proto(const struct dmi_system_id *d) | |||
| 41 | return 0; | 44 | return 0; |
| 42 | } | 45 | } |
| 43 | 46 | ||
| 44 | static const struct dmi_system_id lifebook_dmi_table[] = { | 47 | static const struct dmi_system_id __initconst lifebook_dmi_table[] = { |
| 45 | { | 48 | { |
| 46 | .ident = "FLORA-ie 55mi", | 49 | /* FLORA-ie 55mi */ |
| 47 | .matches = { | 50 | .matches = { |
| 48 | DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), | 51 | DMI_MATCH(DMI_PRODUCT_NAME, "FLORA-ie 55mi"), |
| 49 | }, | 52 | }, |
| 50 | }, | 53 | }, |
| 51 | { | 54 | { |
| 52 | .ident = "LifeBook B", | 55 | /* LifeBook B */ |
| 56 | .matches = { | ||
| 57 | DMI_MATCH(DMI_PRODUCT_NAME, "Lifebook B Series"), | ||
| 58 | }, | ||
| 59 | }, | ||
| 60 | { | ||
| 61 | /* LifeBook B */ | ||
| 53 | .matches = { | 62 | .matches = { |
| 54 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), | 63 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B Series"), |
| 55 | }, | 64 | }, |
| 56 | }, | 65 | }, |
| 57 | { | 66 | { |
| 58 | .ident = "Lifebook B", | 67 | /* Lifebook B */ |
| 59 | .matches = { | 68 | .matches = { |
| 60 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), | 69 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), |
| 61 | }, | 70 | }, |
| 62 | }, | 71 | }, |
| 63 | { | 72 | { |
| 64 | .ident = "Lifebook B-2130", | 73 | /* Lifebook B-2130 */ |
| 65 | .matches = { | 74 | .matches = { |
| 66 | DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), | 75 | DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"), |
| 67 | }, | 76 | }, |
| 68 | }, | 77 | }, |
| 69 | { | 78 | { |
| 70 | .ident = "Lifebook B213x/B2150", | 79 | /* Lifebook B213x/B2150 */ |
| 71 | .matches = { | 80 | .matches = { |
| 72 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), | 81 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B2131/B2133/B2150"), |
| 73 | }, | 82 | }, |
| 74 | }, | 83 | }, |
| 75 | { | 84 | { |
| 76 | .ident = "Zephyr", | 85 | /* Zephyr */ |
| 77 | .matches = { | 86 | .matches = { |
| 78 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), | 87 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPHYR"), |
| 79 | }, | 88 | }, |
| 80 | }, | 89 | }, |
| 81 | { | 90 | { |
| 82 | .ident = "CF-18", | 91 | /* Panasonic CF-18 */ |
| 83 | .matches = { | 92 | .matches = { |
| 84 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), | 93 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-18"), |
| 85 | }, | 94 | }, |
| 86 | .callback = lifebook_set_serio_phys, | 95 | .callback = lifebook_limit_serio3, |
| 87 | .driver_data = "isa0060/serio3", | ||
| 88 | }, | 96 | }, |
| 89 | { | 97 | { |
| 90 | .ident = "Panasonic CF-28", | 98 | /* Panasonic CF-28 */ |
| 91 | .matches = { | 99 | .matches = { |
| 92 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), | 100 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), |
| 93 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), | 101 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-28"), |
| @@ -95,7 +103,7 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
| 95 | .callback = lifebook_set_6byte_proto, | 103 | .callback = lifebook_set_6byte_proto, |
| 96 | }, | 104 | }, |
| 97 | { | 105 | { |
| 98 | .ident = "Panasonic CF-29", | 106 | /* Panasonic CF-29 */ |
| 99 | .matches = { | 107 | .matches = { |
| 100 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), | 108 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), |
| 101 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), | 109 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), |
| @@ -103,14 +111,14 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
| 103 | .callback = lifebook_set_6byte_proto, | 111 | .callback = lifebook_set_6byte_proto, |
| 104 | }, | 112 | }, |
| 105 | { | 113 | { |
| 106 | .ident = "CF-72", | 114 | /* Panasonic CF-72 */ |
| 107 | .matches = { | 115 | .matches = { |
| 108 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), | 116 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-72"), |
| 109 | }, | 117 | }, |
| 110 | .callback = lifebook_set_6byte_proto, | 118 | .callback = lifebook_set_6byte_proto, |
| 111 | }, | 119 | }, |
| 112 | { | 120 | { |
| 113 | .ident = "Lifebook B142", | 121 | /* Lifebook B142 */ |
| 114 | .matches = { | 122 | .matches = { |
| 115 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), | 123 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), |
| 116 | }, | 124 | }, |
| @@ -118,6 +126,11 @@ static const struct dmi_system_id lifebook_dmi_table[] = { | |||
| 118 | { } | 126 | { } |
| 119 | }; | 127 | }; |
| 120 | 128 | ||
| 129 | void __init lifebook_module_init(void) | ||
| 130 | { | ||
| 131 | lifebook_present = dmi_check_system(lifebook_dmi_table); | ||
| 132 | } | ||
| 133 | |||
| 121 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) | 134 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) |
| 122 | { | 135 | { |
| 123 | struct lifebook_data *priv = psmouse->private; | 136 | struct lifebook_data *priv = psmouse->private; |
| @@ -198,10 +211,10 @@ static int lifebook_absolute_mode(struct psmouse *psmouse) | |||
| 198 | return -1; | 211 | return -1; |
| 199 | 212 | ||
| 200 | /* | 213 | /* |
| 201 | Enable absolute output -- ps2_command fails always but if | 214 | * Enable absolute output -- ps2_command fails always but if |
| 202 | you leave this call out the touchsreen will never send | 215 | * you leave this call out the touchsreen will never send |
| 203 | absolute coordinates | 216 | * absolute coordinates |
| 204 | */ | 217 | */ |
| 205 | param = lifebook_use_6byte_proto ? 0x08 : 0x07; | 218 | param = lifebook_use_6byte_proto ? 0x08 : 0x07; |
| 206 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); | 219 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); |
| 207 | 220 | ||
| @@ -243,7 +256,7 @@ static void lifebook_disconnect(struct psmouse *psmouse) | |||
| 243 | 256 | ||
| 244 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) | 257 | int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
| 245 | { | 258 | { |
| 246 | if (!dmi_check_system(lifebook_dmi_table)) | 259 | if (!lifebook_present) |
| 247 | return -1; | 260 | return -1; |
| 248 | 261 | ||
| 249 | if (desired_serio_phys && | 262 | if (desired_serio_phys && |
| @@ -283,8 +296,8 @@ static int lifebook_create_relative_device(struct psmouse *psmouse) | |||
| 283 | 296 | ||
| 284 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 297 | dev2->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
| 285 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 298 | dev2->relbit[BIT_WORD(REL_X)] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
| 286 | dev2->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | | 299 | dev2->keybit[BIT_WORD(BTN_LEFT)] = |
| 287 | BIT_MASK(BTN_RIGHT); | 300 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
| 288 | 301 | ||
| 289 | error = input_register_device(priv->dev2); | 302 | error = input_register_device(priv->dev2); |
| 290 | if (error) | 303 | if (error) |
| @@ -309,6 +322,7 @@ int lifebook_init(struct psmouse *psmouse) | |||
| 309 | 322 | ||
| 310 | dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); | 323 | dev1->evbit[0] = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY); |
| 311 | dev1->relbit[0] = 0; | 324 | dev1->relbit[0] = 0; |
| 325 | dev1->keybit[BIT_WORD(BTN_MOUSE)] = 0; | ||
| 312 | dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | 326 | dev1->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); |
| 313 | input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0); | 327 | input_set_abs_params(dev1, ABS_X, 0, max_coord, 0, 0); |
| 314 | input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0); | 328 | input_set_abs_params(dev1, ABS_Y, 0, max_coord, 0, 0); |
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h index 407cb226bc0a..4c4326c6f504 100644 --- a/drivers/input/mouse/lifebook.h +++ b/drivers/input/mouse/lifebook.h | |||
| @@ -12,9 +12,13 @@ | |||
| 12 | #define _LIFEBOOK_H | 12 | #define _LIFEBOOK_H |
| 13 | 13 | ||
| 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK | 14 | #ifdef CONFIG_MOUSE_PS2_LIFEBOOK |
| 15 | void lifebook_module_init(void); | ||
| 15 | int lifebook_detect(struct psmouse *psmouse, bool set_properties); | 16 | int lifebook_detect(struct psmouse *psmouse, bool set_properties); |
| 16 | int lifebook_init(struct psmouse *psmouse); | 17 | int lifebook_init(struct psmouse *psmouse); |
| 17 | #else | 18 | #else |
| 19 | inline void lifebook_module_init(void) | ||
| 20 | { | ||
| 21 | } | ||
| 18 | inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) | 22 | inline int lifebook_detect(struct psmouse *psmouse, bool set_properties) |
| 19 | { | 23 | { |
| 20 | return -ENOSYS; | 24 | return -ENOSYS; |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index ab5dc5f5fd83..543c240a85f2 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
| @@ -404,8 +404,8 @@ int ps2pp_init(struct psmouse *psmouse, bool set_properties) | |||
| 404 | } | 404 | } |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | if (buttons < 3) | 407 | if (buttons >= 3) |
| 408 | __clear_bit(BTN_MIDDLE, psmouse->dev->keybit); | 408 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
| 409 | 409 | ||
| 410 | if (model_info) | 410 | if (model_info) |
| 411 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); | 411 | ps2pp_set_model_properties(psmouse, model_info, use_ps2pp); |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 07c53798301a..d8c0c8d6992c 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -425,6 +425,7 @@ static int genius_detect(struct psmouse *psmouse, bool set_properties) | |||
| 425 | return -1; | 425 | return -1; |
| 426 | 426 | ||
| 427 | if (set_properties) { | 427 | if (set_properties) { |
| 428 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 428 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); | 429 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 429 | __set_bit(BTN_SIDE, psmouse->dev->keybit); | 430 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 430 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | 431 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
| @@ -460,8 +461,10 @@ static int intellimouse_detect(struct psmouse *psmouse, bool set_properties) | |||
| 460 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | 461 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); |
| 461 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | 462 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
| 462 | 463 | ||
| 463 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 464 | if (!psmouse->vendor) |
| 464 | if (!psmouse->name) psmouse->name = "Wheel Mouse"; | 465 | psmouse->vendor = "Generic"; |
| 466 | if (!psmouse->name) | ||
| 467 | psmouse->name = "Wheel Mouse"; | ||
| 465 | psmouse->pktsize = 4; | 468 | psmouse->pktsize = 4; |
| 466 | } | 469 | } |
| 467 | 470 | ||
| @@ -504,8 +507,10 @@ static int im_explorer_detect(struct psmouse *psmouse, bool set_properties) | |||
| 504 | __set_bit(BTN_SIDE, psmouse->dev->keybit); | 507 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 505 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); | 508 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 506 | 509 | ||
| 507 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 510 | if (!psmouse->vendor) |
| 508 | if (!psmouse->name) psmouse->name = "Explorer Mouse"; | 511 | psmouse->vendor = "Generic"; |
| 512 | if (!psmouse->name) | ||
| 513 | psmouse->name = "Explorer Mouse"; | ||
| 509 | psmouse->pktsize = 4; | 514 | psmouse->pktsize = 4; |
| 510 | } | 515 | } |
| 511 | 516 | ||
| @@ -536,6 +541,7 @@ static int thinking_detect(struct psmouse *psmouse, bool set_properties) | |||
| 536 | return -1; | 541 | return -1; |
| 537 | 542 | ||
| 538 | if (set_properties) { | 543 | if (set_properties) { |
| 544 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 539 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); | 545 | __set_bit(BTN_EXTRA, psmouse->dev->keybit); |
| 540 | 546 | ||
| 541 | psmouse->vendor = "Kensington"; | 547 | psmouse->vendor = "Kensington"; |
| @@ -551,8 +557,16 @@ static int thinking_detect(struct psmouse *psmouse, bool set_properties) | |||
| 551 | static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) | 557 | static int ps2bare_detect(struct psmouse *psmouse, bool set_properties) |
| 552 | { | 558 | { |
| 553 | if (set_properties) { | 559 | if (set_properties) { |
| 554 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 560 | if (!psmouse->vendor) |
| 555 | if (!psmouse->name) psmouse->name = "Mouse"; | 561 | psmouse->vendor = "Generic"; |
| 562 | if (!psmouse->name) | ||
| 563 | psmouse->name = "Mouse"; | ||
| 564 | |||
| 565 | /* | ||
| 566 | * We have no way of figuring true number of buttons so let's | ||
| 567 | * assume that the device has 3. | ||
| 568 | */ | ||
| 569 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 556 | } | 570 | } |
| 557 | 571 | ||
| 558 | return 0; | 572 | return 0; |
| @@ -567,6 +581,8 @@ static int cortron_detect(struct psmouse *psmouse, bool set_properties) | |||
| 567 | if (set_properties) { | 581 | if (set_properties) { |
| 568 | psmouse->vendor = "Cortron"; | 582 | psmouse->vendor = "Cortron"; |
| 569 | psmouse->name = "PS/2 Trackball"; | 583 | psmouse->name = "PS/2 Trackball"; |
| 584 | |||
| 585 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 570 | __set_bit(BTN_SIDE, psmouse->dev->keybit); | 586 | __set_bit(BTN_SIDE, psmouse->dev->keybit); |
| 571 | } | 587 | } |
| 572 | 588 | ||
| @@ -611,8 +627,15 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 611 | synaptics_hardware = true; | 627 | synaptics_hardware = true; |
| 612 | 628 | ||
| 613 | if (max_proto > PSMOUSE_IMEX) { | 629 | if (max_proto > PSMOUSE_IMEX) { |
| 614 | if (!set_properties || synaptics_init(psmouse) == 0) | 630 | /* |
| 631 | * Try activating protocol, but check if support is enabled first, since | ||
| 632 | * we try detecting Synaptics even when protocol is disabled. | ||
| 633 | */ | ||
| 634 | if (synaptics_supported() && | ||
| 635 | (!set_properties || synaptics_init(psmouse) == 0)) { | ||
| 615 | return PSMOUSE_SYNAPTICS; | 636 | return PSMOUSE_SYNAPTICS; |
| 637 | } | ||
| 638 | |||
| 616 | /* | 639 | /* |
| 617 | * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). | 640 | * Some Synaptics touchpads can emulate extended protocols (like IMPS/2). |
| 618 | * Unfortunately Logitech/Genius probes confuse some firmware versions so | 641 | * Unfortunately Logitech/Genius probes confuse some firmware versions so |
| @@ -667,19 +690,6 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 667 | max_proto = PSMOUSE_IMEX; | 690 | max_proto = PSMOUSE_IMEX; |
| 668 | } | 691 | } |
| 669 | 692 | ||
| 670 | /* | ||
| 671 | * Try Finger Sensing Pad | ||
| 672 | */ | ||
| 673 | if (max_proto > PSMOUSE_IMEX) { | ||
| 674 | if (fsp_detect(psmouse, set_properties) == 0) { | ||
| 675 | if (!set_properties || fsp_init(psmouse) == 0) | ||
| 676 | return PSMOUSE_FSP; | ||
| 677 | /* | ||
| 678 | * Init failed, try basic relative protocols | ||
| 679 | */ | ||
| 680 | max_proto = PSMOUSE_IMEX; | ||
| 681 | } | ||
| 682 | } | ||
| 683 | 693 | ||
| 684 | if (max_proto > PSMOUSE_IMEX) { | 694 | if (max_proto > PSMOUSE_IMEX) { |
| 685 | if (genius_detect(psmouse, set_properties) == 0) | 695 | if (genius_detect(psmouse, set_properties) == 0) |
| @@ -696,6 +706,21 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 696 | } | 706 | } |
| 697 | 707 | ||
| 698 | /* | 708 | /* |
| 709 | * Try Finger Sensing Pad. We do it here because its probe upsets | ||
| 710 | * Trackpoint devices (causing TP_READ_ID command to time out). | ||
| 711 | */ | ||
| 712 | if (max_proto > PSMOUSE_IMEX) { | ||
| 713 | if (fsp_detect(psmouse, set_properties) == 0) { | ||
| 714 | if (!set_properties || fsp_init(psmouse) == 0) | ||
| 715 | return PSMOUSE_FSP; | ||
| 716 | /* | ||
| 717 | * Init failed, try basic relative protocols | ||
| 718 | */ | ||
| 719 | max_proto = PSMOUSE_IMEX; | ||
| 720 | } | ||
| 721 | } | ||
| 722 | |||
| 723 | /* | ||
| 699 | * Reset to defaults in case the device got confused by extended | 724 | * Reset to defaults in case the device got confused by extended |
| 700 | * protocol probes. Note that we follow up with full reset because | 725 | * protocol probes. Note that we follow up with full reset because |
| 701 | * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. | 726 | * some mice put themselves to sleep when they see PSMOUSE_RESET_DIS. |
| @@ -1116,12 +1141,22 @@ static void psmouse_cleanup(struct serio *serio) | |||
| 1116 | psmouse_deactivate(parent); | 1141 | psmouse_deactivate(parent); |
| 1117 | } | 1142 | } |
| 1118 | 1143 | ||
| 1119 | psmouse_deactivate(psmouse); | 1144 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
| 1145 | |||
| 1146 | /* | ||
| 1147 | * Disable stream mode so cleanup routine can proceed undisturbed. | ||
| 1148 | */ | ||
| 1149 | if (ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE)) | ||
| 1150 | printk(KERN_WARNING "psmouse.c: Failed to disable mouse on %s\n", | ||
| 1151 | psmouse->ps2dev.serio->phys); | ||
| 1120 | 1152 | ||
| 1121 | if (psmouse->cleanup) | 1153 | if (psmouse->cleanup) |
| 1122 | psmouse->cleanup(psmouse); | 1154 | psmouse->cleanup(psmouse); |
| 1123 | 1155 | ||
| 1124 | psmouse_reset(psmouse); | 1156 | /* |
| 1157 | * Reset the mouse to defaults (bare PS/2 protocol). | ||
| 1158 | */ | ||
| 1159 | ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_RESET_DIS); | ||
| 1125 | 1160 | ||
| 1126 | /* | 1161 | /* |
| 1127 | * Some boxes, such as HP nx7400, get terribly confused if mouse | 1162 | * Some boxes, such as HP nx7400, get terribly confused if mouse |
| @@ -1184,15 +1219,16 @@ static void psmouse_disconnect(struct serio *serio) | |||
| 1184 | mutex_unlock(&psmouse_mutex); | 1219 | mutex_unlock(&psmouse_mutex); |
| 1185 | } | 1220 | } |
| 1186 | 1221 | ||
| 1187 | static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse_protocol *proto) | 1222 | static int psmouse_switch_protocol(struct psmouse *psmouse, |
| 1223 | const struct psmouse_protocol *proto) | ||
| 1188 | { | 1224 | { |
| 1189 | struct input_dev *input_dev = psmouse->dev; | 1225 | struct input_dev *input_dev = psmouse->dev; |
| 1190 | 1226 | ||
| 1191 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; | 1227 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
| 1192 | 1228 | ||
| 1193 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 1229 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
| 1194 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) | | 1230 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] = |
| 1195 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 1231 | BIT_MASK(BTN_LEFT) | BIT_MASK(BTN_RIGHT); |
| 1196 | input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 1232 | input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
| 1197 | 1233 | ||
| 1198 | psmouse->set_rate = psmouse_set_rate; | 1234 | psmouse->set_rate = psmouse_set_rate; |
| @@ -1209,8 +1245,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, const struct psmouse | |||
| 1209 | return -1; | 1245 | return -1; |
| 1210 | 1246 | ||
| 1211 | psmouse->type = proto->type; | 1247 | psmouse->type = proto->type; |
| 1212 | } | 1248 | } else |
| 1213 | else | ||
| 1214 | psmouse->type = psmouse_extensions(psmouse, | 1249 | psmouse->type = psmouse_extensions(psmouse, |
| 1215 | psmouse_max_proto, true); | 1250 | psmouse_max_proto, true); |
| 1216 | 1251 | ||
| @@ -1431,24 +1466,10 @@ ssize_t psmouse_attr_show_helper(struct device *dev, struct device_attribute *de | |||
| 1431 | struct serio *serio = to_serio_port(dev); | 1466 | struct serio *serio = to_serio_port(dev); |
| 1432 | struct psmouse_attribute *attr = to_psmouse_attr(devattr); | 1467 | struct psmouse_attribute *attr = to_psmouse_attr(devattr); |
| 1433 | struct psmouse *psmouse; | 1468 | struct psmouse *psmouse; |
| 1434 | int retval; | ||
| 1435 | |||
| 1436 | retval = serio_pin_driver(serio); | ||
| 1437 | if (retval) | ||
| 1438 | return retval; | ||
| 1439 | |||
| 1440 | if (serio->drv != &psmouse_drv) { | ||
| 1441 | retval = -ENODEV; | ||
| 1442 | goto out; | ||
| 1443 | } | ||
| 1444 | 1469 | ||
| 1445 | psmouse = serio_get_drvdata(serio); | 1470 | psmouse = serio_get_drvdata(serio); |
| 1446 | 1471 | ||
| 1447 | retval = attr->show(psmouse, attr->data, buf); | 1472 | return attr->show(psmouse, attr->data, buf); |
| 1448 | |||
| 1449 | out: | ||
| 1450 | serio_unpin_driver(serio); | ||
| 1451 | return retval; | ||
| 1452 | } | 1473 | } |
| 1453 | 1474 | ||
| 1454 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, | 1475 | ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *devattr, |
| @@ -1459,18 +1480,9 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev | |||
| 1459 | struct psmouse *psmouse, *parent = NULL; | 1480 | struct psmouse *psmouse, *parent = NULL; |
| 1460 | int retval; | 1481 | int retval; |
| 1461 | 1482 | ||
| 1462 | retval = serio_pin_driver(serio); | ||
| 1463 | if (retval) | ||
| 1464 | return retval; | ||
| 1465 | |||
| 1466 | if (serio->drv != &psmouse_drv) { | ||
| 1467 | retval = -ENODEV; | ||
| 1468 | goto out_unpin; | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | retval = mutex_lock_interruptible(&psmouse_mutex); | 1483 | retval = mutex_lock_interruptible(&psmouse_mutex); |
| 1472 | if (retval) | 1484 | if (retval) |
| 1473 | goto out_unpin; | 1485 | goto out; |
| 1474 | 1486 | ||
| 1475 | psmouse = serio_get_drvdata(serio); | 1487 | psmouse = serio_get_drvdata(serio); |
| 1476 | 1488 | ||
| @@ -1500,8 +1512,7 @@ ssize_t psmouse_attr_set_helper(struct device *dev, struct device_attribute *dev | |||
| 1500 | 1512 | ||
| 1501 | out_unlock: | 1513 | out_unlock: |
| 1502 | mutex_unlock(&psmouse_mutex); | 1514 | mutex_unlock(&psmouse_mutex); |
| 1503 | out_unpin: | 1515 | out: |
| 1504 | serio_unpin_driver(serio); | ||
| 1505 | return retval; | 1516 | return retval; |
| 1506 | } | 1517 | } |
| 1507 | 1518 | ||
| @@ -1563,9 +1574,7 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co | |||
| 1563 | } | 1574 | } |
| 1564 | 1575 | ||
| 1565 | mutex_unlock(&psmouse_mutex); | 1576 | mutex_unlock(&psmouse_mutex); |
| 1566 | serio_unpin_driver(serio); | ||
| 1567 | serio_unregister_child_port(serio); | 1577 | serio_unregister_child_port(serio); |
| 1568 | serio_pin_driver_uninterruptible(serio); | ||
| 1569 | mutex_lock(&psmouse_mutex); | 1578 | mutex_lock(&psmouse_mutex); |
| 1570 | 1579 | ||
| 1571 | if (serio->drv != &psmouse_drv) { | 1580 | if (serio->drv != &psmouse_drv) { |
| @@ -1680,6 +1689,9 @@ static int __init psmouse_init(void) | |||
| 1680 | { | 1689 | { |
| 1681 | int err; | 1690 | int err; |
| 1682 | 1691 | ||
| 1692 | lifebook_module_init(); | ||
| 1693 | synaptics_module_init(); | ||
| 1694 | |||
| 1683 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | 1695 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); |
| 1684 | if (!kpsmoused_wq) { | 1696 | if (!kpsmoused_wq) { |
| 1685 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | 1697 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); |
diff --git a/drivers/input/mouse/pxa930_trkball.c b/drivers/input/mouse/pxa930_trkball.c index 1e827ad0afbe..943cfec15665 100644 --- a/drivers/input/mouse/pxa930_trkball.c +++ b/drivers/input/mouse/pxa930_trkball.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
| 21 | #include <linux/slab.h> | ||
| 21 | 22 | ||
| 22 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
| 23 | #include <mach/pxa930_trkball.h> | 24 | #include <mach/pxa930_trkball.h> |
diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index f84cbd97c884..1242775fee19 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * Finger Sensing Pad PS/2 mouse driver. | 2 | * Finger Sensing Pad PS/2 mouse driver. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. | 4 | * Copyright (C) 2005-2007 Asia Vital Components Co., Ltd. |
| 5 | * Copyright (C) 2005-2009 Tai-hwa Liang, Sentelic Corporation. | 5 | * Copyright (C) 2005-2010 Tai-hwa Liang, Sentelic Corporation. |
| 6 | * | 6 | * |
| 7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
| 8 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/libps2.h> | 26 | #include <linux/libps2.h> |
| 27 | #include <linux/serio.h> | 27 | #include <linux/serio.h> |
| 28 | #include <linux/jiffies.h> | 28 | #include <linux/jiffies.h> |
| 29 | #include <linux/slab.h> | ||
| 29 | 30 | ||
| 30 | #include "psmouse.h" | 31 | #include "psmouse.h" |
| 31 | #include "sentelic.h" | 32 | #include "sentelic.h" |
| @@ -658,9 +659,9 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) | |||
| 658 | if (packet[3] & BIT(1)) | 659 | if (packet[3] & BIT(1)) |
| 659 | button_status |= 0x0f; /* wheel up */ | 660 | button_status |= 0x0f; /* wheel up */ |
| 660 | if (packet[3] & BIT(2)) | 661 | if (packet[3] & BIT(2)) |
| 661 | button_status |= BIT(5);/* horizontal left */ | 662 | button_status |= BIT(4);/* horizontal left */ |
| 662 | if (packet[3] & BIT(3)) | 663 | if (packet[3] & BIT(3)) |
| 663 | button_status |= BIT(4);/* horizontal right */ | 664 | button_status |= BIT(5);/* horizontal right */ |
| 664 | /* push back to packet queue */ | 665 | /* push back to packet queue */ |
| 665 | if (button_status != 0) | 666 | if (button_status != 0) |
| 666 | packet[3] = button_status; | 667 | packet[3] = button_status; |
| @@ -836,6 +837,7 @@ int fsp_init(struct psmouse *psmouse) | |||
| 836 | priv->flags |= FSPDRV_FLAG_EN_OPC; | 837 | priv->flags |= FSPDRV_FLAG_EN_OPC; |
| 837 | 838 | ||
| 838 | /* Set up various supported input event bits */ | 839 | /* Set up various supported input event bits */ |
| 840 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 839 | __set_bit(BTN_BACK, psmouse->dev->keybit); | 841 | __set_bit(BTN_BACK, psmouse->dev->keybit); |
| 840 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); | 842 | __set_bit(BTN_FORWARD, psmouse->dev->keybit); |
| 841 | __set_bit(REL_WHEEL, psmouse->dev->relbit); | 843 | __set_bit(REL_WHEEL, psmouse->dev->relbit); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index f4a61252bcc9..026df6010161 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -24,9 +24,11 @@ | |||
| 24 | */ | 24 | */ |
| 25 | 25 | ||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/dmi.h> | ||
| 27 | #include <linux/input.h> | 28 | #include <linux/input.h> |
| 28 | #include <linux/serio.h> | 29 | #include <linux/serio.h> |
| 29 | #include <linux/libps2.h> | 30 | #include <linux/libps2.h> |
| 31 | #include <linux/slab.h> | ||
| 30 | #include "psmouse.h" | 32 | #include "psmouse.h" |
| 31 | #include "synaptics.h" | 33 | #include "synaptics.h" |
| 32 | 34 | ||
| @@ -629,25 +631,26 @@ static int synaptics_reconnect(struct psmouse *psmouse) | |||
| 629 | return 0; | 631 | return 0; |
| 630 | } | 632 | } |
| 631 | 633 | ||
| 632 | #if defined(__i386__) | 634 | static bool impaired_toshiba_kbc; |
| 633 | #include <linux/dmi.h> | 635 | |
| 634 | static const struct dmi_system_id toshiba_dmi_table[] = { | 636 | static const struct dmi_system_id __initconst toshiba_dmi_table[] = { |
| 637 | #if defined(CONFIG_DMI) && defined(CONFIG_X86) | ||
| 635 | { | 638 | { |
| 636 | .ident = "Toshiba Satellite", | 639 | /* Toshiba Satellite */ |
| 637 | .matches = { | 640 | .matches = { |
| 638 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 641 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 639 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), | 642 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite"), |
| 640 | }, | 643 | }, |
| 641 | }, | 644 | }, |
| 642 | { | 645 | { |
| 643 | .ident = "Toshiba Dynabook", | 646 | /* Toshiba Dynabook */ |
| 644 | .matches = { | 647 | .matches = { |
| 645 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 648 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 646 | DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"), | 649 | DMI_MATCH(DMI_PRODUCT_NAME, "dynabook"), |
| 647 | }, | 650 | }, |
| 648 | }, | 651 | }, |
| 649 | { | 652 | { |
| 650 | .ident = "Toshiba Portege M300", | 653 | /* Toshiba Portege M300 */ |
| 651 | .matches = { | 654 | .matches = { |
| 652 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 655 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 653 | DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), | 656 | DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), |
| @@ -655,7 +658,7 @@ static const struct dmi_system_id toshiba_dmi_table[] = { | |||
| 655 | 658 | ||
| 656 | }, | 659 | }, |
| 657 | { | 660 | { |
| 658 | .ident = "Toshiba Portege M300", | 661 | /* Toshiba Portege M300 */ |
| 659 | .matches = { | 662 | .matches = { |
| 660 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 663 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 661 | DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), | 664 | DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"), |
| @@ -664,8 +667,13 @@ static const struct dmi_system_id toshiba_dmi_table[] = { | |||
| 664 | 667 | ||
| 665 | }, | 668 | }, |
| 666 | { } | 669 | { } |
| 667 | }; | ||
| 668 | #endif | 670 | #endif |
| 671 | }; | ||
| 672 | |||
| 673 | void __init synaptics_module_init(void) | ||
| 674 | { | ||
| 675 | impaired_toshiba_kbc = dmi_check_system(toshiba_dmi_table); | ||
| 676 | } | ||
| 669 | 677 | ||
| 670 | int synaptics_init(struct psmouse *psmouse) | 678 | int synaptics_init(struct psmouse *psmouse) |
| 671 | { | 679 | { |
| @@ -718,18 +726,16 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 718 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 726 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
| 719 | synaptics_pt_create(psmouse); | 727 | synaptics_pt_create(psmouse); |
| 720 | 728 | ||
| 721 | #if defined(__i386__) | ||
| 722 | /* | 729 | /* |
| 723 | * Toshiba's KBC seems to have trouble handling data from | 730 | * Toshiba's KBC seems to have trouble handling data from |
| 724 | * Synaptics as full rate, switch to lower rate which is roughly | 731 | * Synaptics as full rate, switch to lower rate which is roughly |
| 725 | * thye same as rate of standard PS/2 mouse. | 732 | * thye same as rate of standard PS/2 mouse. |
| 726 | */ | 733 | */ |
| 727 | if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) { | 734 | if (psmouse->rate >= 80 && impaired_toshiba_kbc) { |
| 728 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", | 735 | printk(KERN_INFO "synaptics: Toshiba %s detected, limiting rate to 40pps.\n", |
| 729 | dmi_get_system_info(DMI_PRODUCT_NAME)); | 736 | dmi_get_system_info(DMI_PRODUCT_NAME)); |
| 730 | psmouse->rate = 40; | 737 | psmouse->rate = 40; |
| 731 | } | 738 | } |
| 732 | #endif | ||
| 733 | 739 | ||
| 734 | return 0; | 740 | return 0; |
| 735 | 741 | ||
| @@ -738,12 +744,26 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 738 | return -1; | 744 | return -1; |
| 739 | } | 745 | } |
| 740 | 746 | ||
| 747 | bool synaptics_supported(void) | ||
| 748 | { | ||
| 749 | return true; | ||
| 750 | } | ||
| 751 | |||
| 741 | #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ | 752 | #else /* CONFIG_MOUSE_PS2_SYNAPTICS */ |
| 742 | 753 | ||
| 754 | void __init synaptics_module_init(void) | ||
| 755 | { | ||
| 756 | } | ||
| 757 | |||
| 743 | int synaptics_init(struct psmouse *psmouse) | 758 | int synaptics_init(struct psmouse *psmouse) |
| 744 | { | 759 | { |
| 745 | return -ENOSYS; | 760 | return -ENOSYS; |
| 746 | } | 761 | } |
| 747 | 762 | ||
| 763 | bool synaptics_supported(void) | ||
| 764 | { | ||
| 765 | return false; | ||
| 766 | } | ||
| 767 | |||
| 748 | #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ | 768 | #endif /* CONFIG_MOUSE_PS2_SYNAPTICS */ |
| 749 | 769 | ||
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index 871f6fe377f9..f0f40a331dc8 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
| @@ -105,8 +105,10 @@ struct synaptics_data { | |||
| 105 | int scroll; | 105 | int scroll; |
| 106 | }; | 106 | }; |
| 107 | 107 | ||
| 108 | void synaptics_module_init(void); | ||
| 108 | int synaptics_detect(struct psmouse *psmouse, bool set_properties); | 109 | int synaptics_detect(struct psmouse *psmouse, bool set_properties); |
| 109 | int synaptics_init(struct psmouse *psmouse); | 110 | int synaptics_init(struct psmouse *psmouse); |
| 110 | void synaptics_reset(struct psmouse *psmouse); | 111 | void synaptics_reset(struct psmouse *psmouse); |
| 112 | bool synaptics_supported(void); | ||
| 111 | 113 | ||
| 112 | #endif /* _SYNAPTICS_H */ | 114 | #endif /* _SYNAPTICS_H */ |
diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 7283c78044af..8291e7399ffa 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/workqueue.h> | 19 | #include <linux/workqueue.h> |
| 20 | #include <linux/slab.h> | ||
| 20 | 21 | ||
| 21 | #define DRIVER_NAME "synaptics_i2c" | 22 | #define DRIVER_NAME "synaptics_i2c" |
| 22 | /* maximum product id is 15 characters */ | 23 | /* maximum product id is 15 characters */ |
| @@ -420,8 +421,8 @@ static void synaptics_i2c_check_params(struct synaptics_i2c *touch) | |||
| 420 | } | 421 | } |
| 421 | 422 | ||
| 422 | /* Control the Device polling rate / Work Handler sleep time */ | 423 | /* Control the Device polling rate / Work Handler sleep time */ |
| 423 | unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, | 424 | static unsigned long synaptics_i2c_adjust_delay(struct synaptics_i2c *touch, |
| 424 | bool have_data) | 425 | bool have_data) |
| 425 | { | 426 | { |
| 426 | unsigned long delay, nodata_count_thres; | 427 | unsigned long delay, nodata_count_thres; |
| 427 | 428 | ||
| @@ -520,7 +521,7 @@ static void synaptics_i2c_set_input_params(struct synaptics_i2c *touch) | |||
| 520 | __set_bit(BTN_LEFT, input->keybit); | 521 | __set_bit(BTN_LEFT, input->keybit); |
| 521 | } | 522 | } |
| 522 | 523 | ||
| 523 | struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) | 524 | static struct synaptics_i2c *synaptics_i2c_touch_create(struct i2c_client *client) |
| 524 | { | 525 | { |
| 525 | struct synaptics_i2c *touch; | 526 | struct synaptics_i2c *touch; |
| 526 | 527 | ||
diff --git a/drivers/input/mouse/touchkit_ps2.c b/drivers/input/mouse/touchkit_ps2.c index 0308a0faa94d..88121c59c3cc 100644 --- a/drivers/input/mouse/touchkit_ps2.c +++ b/drivers/input/mouse/touchkit_ps2.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | */ | 26 | */ |
| 27 | 27 | ||
| 28 | #include <linux/kernel.h> | 28 | #include <linux/kernel.h> |
| 29 | #include <linux/slab.h> | ||
| 30 | 29 | ||
| 31 | #include <linux/input.h> | 30 | #include <linux/input.h> |
| 32 | #include <linux/serio.h> | 31 | #include <linux/serio.h> |
| @@ -86,7 +85,8 @@ int touchkit_ps2_detect(struct psmouse *psmouse, bool set_properties) | |||
| 86 | 85 | ||
| 87 | if (set_properties) { | 86 | if (set_properties) { |
| 88 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 87 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 89 | __set_bit(BTN_TOUCH, dev->keybit); | 88 | dev->keybit[BIT_WORD(BTN_MOUSE)] = 0; |
| 89 | dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); | 90 | input_set_abs_params(dev, ABS_X, 0, TOUCHKIT_MAX_XC, 0, 0); |
| 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); | 91 | input_set_abs_params(dev, ABS_Y, 0, TOUCHKIT_MAX_YC, 0, 0); |
| 92 | 92 | ||
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c index e354362f2971..0643e49ca603 100644 --- a/drivers/input/mouse/trackpoint.c +++ b/drivers/input/mouse/trackpoint.c | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * Trademarks are the property of their respective owners. | 8 | * Trademarks are the property of their respective owners. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #include <linux/slab.h> | ||
| 11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
| 12 | #include <linux/serio.h> | 13 | #include <linux/serio.h> |
| 13 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| @@ -284,7 +285,6 @@ static int trackpoint_reconnect(struct psmouse *psmouse) | |||
| 284 | 285 | ||
| 285 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | 286 | int trackpoint_detect(struct psmouse *psmouse, bool set_properties) |
| 286 | { | 287 | { |
| 287 | struct trackpoint_data *priv; | ||
| 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 288 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 289 | unsigned char firmware_id; | 289 | unsigned char firmware_id; |
| 290 | unsigned char button_info; | 290 | unsigned char button_info; |
| @@ -301,8 +301,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
| 301 | button_info = 0; | 301 | button_info = 0; |
| 302 | } | 302 | } |
| 303 | 303 | ||
| 304 | psmouse->private = priv = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); | 304 | psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL); |
| 305 | if (!priv) | 305 | if (!psmouse->private) |
| 306 | return -1; | 306 | return -1; |
| 307 | 307 | ||
| 308 | psmouse->vendor = "IBM"; | 308 | psmouse->vendor = "IBM"; |
| @@ -311,7 +311,10 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
| 311 | psmouse->reconnect = trackpoint_reconnect; | 311 | psmouse->reconnect = trackpoint_reconnect; |
| 312 | psmouse->disconnect = trackpoint_disconnect; | 312 | psmouse->disconnect = trackpoint_disconnect; |
| 313 | 313 | ||
| 314 | trackpoint_defaults(priv); | 314 | if ((button_info & 0x0f) >= 3) |
| 315 | __set_bit(BTN_MIDDLE, psmouse->dev->keybit); | ||
| 316 | |||
| 317 | trackpoint_defaults(psmouse->private); | ||
| 315 | trackpoint_sync(psmouse); | 318 | trackpoint_sync(psmouse); |
| 316 | 319 | ||
| 317 | error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); | 320 | error = sysfs_create_group(&ps2dev->serio->dev.kobj, &trackpoint_attr_group); |
| @@ -319,7 +322,8 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties) | |||
| 319 | printk(KERN_ERR | 322 | printk(KERN_ERR |
| 320 | "trackpoint.c: failed to create sysfs attributes, error: %d\n", | 323 | "trackpoint.c: failed to create sysfs attributes, error: %d\n", |
| 321 | error); | 324 | error); |
| 322 | kfree(priv); | 325 | kfree(psmouse->private); |
| 326 | psmouse->private = NULL; | ||
| 323 | return -1; | 327 | return -1; |
| 324 | } | 328 | } |
| 325 | 329 | ||
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index 70111443678e..bf2c0c80d6cc 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
| @@ -86,27 +86,28 @@ | |||
| 86 | 86 | ||
| 87 | #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet" | 87 | #define DRIVER_DESC "Driver for DEC VSXXX-AA and -GA mice and VSXXX-AB tablet" |
| 88 | 88 | ||
| 89 | MODULE_AUTHOR ("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); | 89 | MODULE_AUTHOR("Jan-Benedict Glaw <jbglaw@lug-owl.de>"); |
| 90 | MODULE_DESCRIPTION (DRIVER_DESC); | 90 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 91 | MODULE_LICENSE ("GPL"); | 91 | MODULE_LICENSE("GPL"); |
| 92 | 92 | ||
| 93 | #undef VSXXXAA_DEBUG | 93 | #undef VSXXXAA_DEBUG |
| 94 | #ifdef VSXXXAA_DEBUG | 94 | #ifdef VSXXXAA_DEBUG |
| 95 | #define DBG(x...) printk (x) | 95 | #define DBG(x...) printk(x) |
| 96 | #else | 96 | #else |
| 97 | #define DBG(x...) do {} while (0) | 97 | #define DBG(x...) do {} while (0) |
| 98 | #endif | 98 | #endif |
| 99 | 99 | ||
| 100 | #define VSXXXAA_INTRO_MASK 0x80 | 100 | #define VSXXXAA_INTRO_MASK 0x80 |
| 101 | #define VSXXXAA_INTRO_HEAD 0x80 | 101 | #define VSXXXAA_INTRO_HEAD 0x80 |
| 102 | #define IS_HDR_BYTE(x) (((x) & VSXXXAA_INTRO_MASK) \ | 102 | #define IS_HDR_BYTE(x) \ |
| 103 | == VSXXXAA_INTRO_HEAD) | 103 | (((x) & VSXXXAA_INTRO_MASK) == VSXXXAA_INTRO_HEAD) |
| 104 | 104 | ||
| 105 | #define VSXXXAA_PACKET_MASK 0xe0 | 105 | #define VSXXXAA_PACKET_MASK 0xe0 |
| 106 | #define VSXXXAA_PACKET_REL 0x80 | 106 | #define VSXXXAA_PACKET_REL 0x80 |
| 107 | #define VSXXXAA_PACKET_ABS 0xc0 | 107 | #define VSXXXAA_PACKET_ABS 0xc0 |
| 108 | #define VSXXXAA_PACKET_POR 0xa0 | 108 | #define VSXXXAA_PACKET_POR 0xa0 |
| 109 | #define MATCH_PACKET_TYPE(data, type) (((data) & VSXXXAA_PACKET_MASK) == (type)) | 109 | #define MATCH_PACKET_TYPE(data, type) \ |
| 110 | (((data) & VSXXXAA_PACKET_MASK) == (type)) | ||
| 110 | 111 | ||
| 111 | 112 | ||
| 112 | 113 | ||
| @@ -123,52 +124,50 @@ struct vsxxxaa { | |||
| 123 | char phys[32]; | 124 | char phys[32]; |
| 124 | }; | 125 | }; |
| 125 | 126 | ||
| 126 | static void | 127 | static void vsxxxaa_drop_bytes(struct vsxxxaa *mouse, int num) |
| 127 | vsxxxaa_drop_bytes (struct vsxxxaa *mouse, int num) | ||
| 128 | { | 128 | { |
| 129 | if (num >= mouse->count) | 129 | if (num >= mouse->count) { |
| 130 | mouse->count = 0; | 130 | mouse->count = 0; |
| 131 | else { | 131 | } else { |
| 132 | memmove (mouse->buf, mouse->buf + num - 1, BUFLEN - num); | 132 | memmove(mouse->buf, mouse->buf + num - 1, BUFLEN - num); |
| 133 | mouse->count -= num; | 133 | mouse->count -= num; |
| 134 | } | 134 | } |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | static void | 137 | static void vsxxxaa_queue_byte(struct vsxxxaa *mouse, unsigned char byte) |
| 138 | vsxxxaa_queue_byte (struct vsxxxaa *mouse, unsigned char byte) | ||
| 139 | { | 138 | { |
| 140 | if (mouse->count == BUFLEN) { | 139 | if (mouse->count == BUFLEN) { |
| 141 | printk (KERN_ERR "%s on %s: Dropping a byte of full buffer.\n", | 140 | printk(KERN_ERR "%s on %s: Dropping a byte of full buffer.\n", |
| 142 | mouse->name, mouse->phys); | 141 | mouse->name, mouse->phys); |
| 143 | vsxxxaa_drop_bytes (mouse, 1); | 142 | vsxxxaa_drop_bytes(mouse, 1); |
| 144 | } | 143 | } |
| 145 | DBG (KERN_INFO "Queueing byte 0x%02x\n", byte); | 144 | |
| 145 | DBG(KERN_INFO "Queueing byte 0x%02x\n", byte); | ||
| 146 | 146 | ||
| 147 | mouse->buf[mouse->count++] = byte; | 147 | mouse->buf[mouse->count++] = byte; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | static void | 150 | static void vsxxxaa_detection_done(struct vsxxxaa *mouse) |
| 151 | vsxxxaa_detection_done (struct vsxxxaa *mouse) | ||
| 152 | { | 151 | { |
| 153 | switch (mouse->type) { | 152 | switch (mouse->type) { |
| 154 | case 0x02: | 153 | case 0x02: |
| 155 | strlcpy (mouse->name, "DEC VSXXX-AA/-GA mouse", | 154 | strlcpy(mouse->name, "DEC VSXXX-AA/-GA mouse", |
| 156 | sizeof (mouse->name)); | 155 | sizeof(mouse->name)); |
| 157 | break; | 156 | break; |
| 158 | 157 | ||
| 159 | case 0x04: | 158 | case 0x04: |
| 160 | strlcpy (mouse->name, "DEC VSXXX-AB digitizer", | 159 | strlcpy(mouse->name, "DEC VSXXX-AB digitizer", |
| 161 | sizeof (mouse->name)); | 160 | sizeof(mouse->name)); |
| 162 | break; | 161 | break; |
| 163 | 162 | ||
| 164 | default: | 163 | default: |
| 165 | snprintf (mouse->name, sizeof (mouse->name), | 164 | snprintf(mouse->name, sizeof(mouse->name), |
| 166 | "unknown DEC pointer device (type = 0x%02x)", | 165 | "unknown DEC pointer device (type = 0x%02x)", |
| 167 | mouse->type); | 166 | mouse->type); |
| 168 | break; | 167 | break; |
| 169 | } | 168 | } |
| 170 | 169 | ||
| 171 | printk (KERN_INFO | 170 | printk(KERN_INFO |
| 172 | "Found %s version 0x%02x from country 0x%02x on port %s\n", | 171 | "Found %s version 0x%02x from country 0x%02x on port %s\n", |
| 173 | mouse->name, mouse->version, mouse->country, mouse->phys); | 172 | mouse->name, mouse->version, mouse->country, mouse->phys); |
| 174 | } | 173 | } |
| @@ -176,42 +175,38 @@ vsxxxaa_detection_done (struct vsxxxaa *mouse) | |||
| 176 | /* | 175 | /* |
| 177 | * Returns number of bytes to be dropped, 0 if packet is okay. | 176 | * Returns number of bytes to be dropped, 0 if packet is okay. |
| 178 | */ | 177 | */ |
| 179 | static int | 178 | static int vsxxxaa_check_packet(struct vsxxxaa *mouse, int packet_len) |
| 180 | vsxxxaa_check_packet (struct vsxxxaa *mouse, int packet_len) | ||
| 181 | { | 179 | { |
| 182 | int i; | 180 | int i; |
| 183 | 181 | ||
| 184 | /* First byte must be a header byte */ | 182 | /* First byte must be a header byte */ |
| 185 | if (!IS_HDR_BYTE (mouse->buf[0])) { | 183 | if (!IS_HDR_BYTE(mouse->buf[0])) { |
| 186 | DBG ("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]); | 184 | DBG("vsck: len=%d, 1st=0x%02x\n", packet_len, mouse->buf[0]); |
| 187 | return 1; | 185 | return 1; |
| 188 | } | 186 | } |
| 189 | 187 | ||
| 190 | /* Check all following bytes */ | 188 | /* Check all following bytes */ |
| 191 | if (packet_len > 1) { | 189 | for (i = 1; i < packet_len; i++) { |
| 192 | for (i = 1; i < packet_len; i++) { | 190 | if (IS_HDR_BYTE(mouse->buf[i])) { |
| 193 | if (IS_HDR_BYTE (mouse->buf[i])) { | 191 | printk(KERN_ERR |
| 194 | printk (KERN_ERR "Need to drop %d bytes " | 192 | "Need to drop %d bytes of a broken packet.\n", |
| 195 | "of a broken packet.\n", | 193 | i - 1); |
| 196 | i - 1); | 194 | DBG(KERN_INFO "check: len=%d, b[%d]=0x%02x\n", |
| 197 | DBG (KERN_INFO "check: len=%d, b[%d]=0x%02x\n", | 195 | packet_len, i, mouse->buf[i]); |
| 198 | packet_len, i, mouse->buf[i]); | 196 | return i - 1; |
| 199 | return i - 1; | ||
| 200 | } | ||
| 201 | } | 197 | } |
| 202 | } | 198 | } |
| 203 | 199 | ||
| 204 | return 0; | 200 | return 0; |
| 205 | } | 201 | } |
| 206 | 202 | ||
| 207 | static __inline__ int | 203 | static inline int vsxxxaa_smells_like_packet(struct vsxxxaa *mouse, |
| 208 | vsxxxaa_smells_like_packet (struct vsxxxaa *mouse, unsigned char type, size_t len) | 204 | unsigned char type, size_t len) |
| 209 | { | 205 | { |
| 210 | return (mouse->count >= len) && MATCH_PACKET_TYPE (mouse->buf[0], type); | 206 | return mouse->count >= len && MATCH_PACKET_TYPE(mouse->buf[0], type); |
| 211 | } | 207 | } |
| 212 | 208 | ||
| 213 | static void | 209 | static void vsxxxaa_handle_REL_packet(struct vsxxxaa *mouse) |
| 214 | vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse) | ||
| 215 | { | 210 | { |
| 216 | struct input_dev *dev = mouse->dev; | 211 | struct input_dev *dev = mouse->dev; |
| 217 | unsigned char *buf = mouse->buf; | 212 | unsigned char *buf = mouse->buf; |
| @@ -232,43 +227,42 @@ vsxxxaa_handle_REL_packet (struct vsxxxaa *mouse) | |||
| 232 | * 0, bit 4 of byte 0 is direction. | 227 | * 0, bit 4 of byte 0 is direction. |
| 233 | */ | 228 | */ |
| 234 | dx = buf[1] & 0x7f; | 229 | dx = buf[1] & 0x7f; |
| 235 | dx *= ((buf[0] >> 4) & 0x01)? 1: -1; | 230 | dx *= ((buf[0] >> 4) & 0x01) ? 1 : -1; |
| 236 | 231 | ||
| 237 | /* | 232 | /* |
| 238 | * Low 7 bit of byte 2 are abs(dy), bit 7 is | 233 | * Low 7 bit of byte 2 are abs(dy), bit 7 is |
| 239 | * 0, bit 3 of byte 0 is direction. | 234 | * 0, bit 3 of byte 0 is direction. |
| 240 | */ | 235 | */ |
| 241 | dy = buf[2] & 0x7f; | 236 | dy = buf[2] & 0x7f; |
| 242 | dy *= ((buf[0] >> 3) & 0x01)? -1: 1; | 237 | dy *= ((buf[0] >> 3) & 0x01) ? -1 : 1; |
| 243 | 238 | ||
| 244 | /* | 239 | /* |
| 245 | * Get button state. It's the low three bits | 240 | * Get button state. It's the low three bits |
| 246 | * (for three buttons) of byte 0. | 241 | * (for three buttons) of byte 0. |
| 247 | */ | 242 | */ |
| 248 | left = (buf[0] & 0x04)? 1: 0; | 243 | left = buf[0] & 0x04; |
| 249 | middle = (buf[0] & 0x02)? 1: 0; | 244 | middle = buf[0] & 0x02; |
| 250 | right = (buf[0] & 0x01)? 1: 0; | 245 | right = buf[0] & 0x01; |
| 251 | 246 | ||
| 252 | vsxxxaa_drop_bytes (mouse, 3); | 247 | vsxxxaa_drop_bytes(mouse, 3); |
| 253 | 248 | ||
| 254 | DBG (KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n", | 249 | DBG(KERN_INFO "%s on %s: dx=%d, dy=%d, buttons=%s%s%s\n", |
| 255 | mouse->name, mouse->phys, dx, dy, | 250 | mouse->name, mouse->phys, dx, dy, |
| 256 | left? "L": "l", middle? "M": "m", right? "R": "r"); | 251 | left ? "L" : "l", middle ? "M" : "m", right ? "R" : "r"); |
| 257 | 252 | ||
| 258 | /* | 253 | /* |
| 259 | * Report what we've found so far... | 254 | * Report what we've found so far... |
| 260 | */ | 255 | */ |
| 261 | input_report_key (dev, BTN_LEFT, left); | 256 | input_report_key(dev, BTN_LEFT, left); |
| 262 | input_report_key (dev, BTN_MIDDLE, middle); | 257 | input_report_key(dev, BTN_MIDDLE, middle); |
| 263 | input_report_key (dev, BTN_RIGHT, right); | 258 | input_report_key(dev, BTN_RIGHT, right); |
| 264 | input_report_key (dev, BTN_TOUCH, 0); | 259 | input_report_key(dev, BTN_TOUCH, 0); |
| 265 | input_report_rel (dev, REL_X, dx); | 260 | input_report_rel(dev, REL_X, dx); |
| 266 | input_report_rel (dev, REL_Y, dy); | 261 | input_report_rel(dev, REL_Y, dy); |
| 267 | input_sync (dev); | 262 | input_sync(dev); |
| 268 | } | 263 | } |
| 269 | 264 | ||
| 270 | static void | 265 | static void vsxxxaa_handle_ABS_packet(struct vsxxxaa *mouse) |
| 271 | vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse) | ||
| 272 | { | 266 | { |
| 273 | struct input_dev *dev = mouse->dev; | 267 | struct input_dev *dev = mouse->dev; |
| 274 | unsigned char *buf = mouse->buf; | 268 | unsigned char *buf = mouse->buf; |
| @@ -296,32 +290,31 @@ vsxxxaa_handle_ABS_packet (struct vsxxxaa *mouse) | |||
| 296 | /* | 290 | /* |
| 297 | * Get button state. It's bits <4..1> of byte 0. | 291 | * Get button state. It's bits <4..1> of byte 0. |
| 298 | */ | 292 | */ |
| 299 | left = (buf[0] & 0x02)? 1: 0; | 293 | left = buf[0] & 0x02; |
| 300 | middle = (buf[0] & 0x04)? 1: 0; | 294 | middle = buf[0] & 0x04; |
| 301 | right = (buf[0] & 0x08)? 1: 0; | 295 | right = buf[0] & 0x08; |
| 302 | touch = (buf[0] & 0x10)? 1: 0; | 296 | touch = buf[0] & 0x10; |
| 303 | 297 | ||
| 304 | vsxxxaa_drop_bytes (mouse, 5); | 298 | vsxxxaa_drop_bytes(mouse, 5); |
| 305 | 299 | ||
| 306 | DBG (KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n", | 300 | DBG(KERN_INFO "%s on %s: x=%d, y=%d, buttons=%s%s%s%s\n", |
| 307 | mouse->name, mouse->phys, x, y, | 301 | mouse->name, mouse->phys, x, y, |
| 308 | left? "L": "l", middle? "M": "m", | 302 | left ? "L" : "l", middle ? "M" : "m", |
| 309 | right? "R": "r", touch? "T": "t"); | 303 | right ? "R" : "r", touch ? "T" : "t"); |
| 310 | 304 | ||
| 311 | /* | 305 | /* |
| 312 | * Report what we've found so far... | 306 | * Report what we've found so far... |
| 313 | */ | 307 | */ |
| 314 | input_report_key (dev, BTN_LEFT, left); | 308 | input_report_key(dev, BTN_LEFT, left); |
| 315 | input_report_key (dev, BTN_MIDDLE, middle); | 309 | input_report_key(dev, BTN_MIDDLE, middle); |
| 316 | input_report_key (dev, BTN_RIGHT, right); | 310 | input_report_key(dev, BTN_RIGHT, right); |
| 317 | input_report_key (dev, BTN_TOUCH, touch); | 311 | input_report_key(dev, BTN_TOUCH, touch); |
| 318 | input_report_abs (dev, ABS_X, x); | 312 | input_report_abs(dev, ABS_X, x); |
| 319 | input_report_abs (dev, ABS_Y, y); | 313 | input_report_abs(dev, ABS_Y, y); |
| 320 | input_sync (dev); | 314 | input_sync(dev); |
| 321 | } | 315 | } |
| 322 | 316 | ||
| 323 | static void | 317 | static void vsxxxaa_handle_POR_packet(struct vsxxxaa *mouse) |
| 324 | vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | ||
| 325 | { | 318 | { |
| 326 | struct input_dev *dev = mouse->dev; | 319 | struct input_dev *dev = mouse->dev; |
| 327 | unsigned char *buf = mouse->buf; | 320 | unsigned char *buf = mouse->buf; |
| @@ -356,24 +349,24 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
| 356 | * (for three buttons) of byte 0. Maybe even the bit <3> | 349 | * (for three buttons) of byte 0. Maybe even the bit <3> |
| 357 | * has some meaning if a tablet is attached. | 350 | * has some meaning if a tablet is attached. |
| 358 | */ | 351 | */ |
| 359 | left = (buf[0] & 0x04)? 1: 0; | 352 | left = buf[0] & 0x04; |
| 360 | middle = (buf[0] & 0x02)? 1: 0; | 353 | middle = buf[0] & 0x02; |
| 361 | right = (buf[0] & 0x01)? 1: 0; | 354 | right = buf[0] & 0x01; |
| 362 | 355 | ||
| 363 | vsxxxaa_drop_bytes (mouse, 4); | 356 | vsxxxaa_drop_bytes(mouse, 4); |
| 364 | vsxxxaa_detection_done (mouse); | 357 | vsxxxaa_detection_done(mouse); |
| 365 | 358 | ||
| 366 | if (error <= 0x1f) { | 359 | if (error <= 0x1f) { |
| 367 | /* No (serious) error. Report buttons */ | 360 | /* No (serious) error. Report buttons */ |
| 368 | input_report_key (dev, BTN_LEFT, left); | 361 | input_report_key(dev, BTN_LEFT, left); |
| 369 | input_report_key (dev, BTN_MIDDLE, middle); | 362 | input_report_key(dev, BTN_MIDDLE, middle); |
| 370 | input_report_key (dev, BTN_RIGHT, right); | 363 | input_report_key(dev, BTN_RIGHT, right); |
| 371 | input_report_key (dev, BTN_TOUCH, 0); | 364 | input_report_key(dev, BTN_TOUCH, 0); |
| 372 | input_sync (dev); | 365 | input_sync(dev); |
| 373 | 366 | ||
| 374 | if (error != 0) | 367 | if (error != 0) |
| 375 | printk (KERN_INFO "Your %s on %s reports error=0x%02x\n", | 368 | printk(KERN_INFO "Your %s on %s reports error=0x%02x\n", |
| 376 | mouse->name, mouse->phys, error); | 369 | mouse->name, mouse->phys, error); |
| 377 | 370 | ||
| 378 | } | 371 | } |
| 379 | 372 | ||
| @@ -381,18 +374,18 @@ vsxxxaa_handle_POR_packet (struct vsxxxaa *mouse) | |||
| 381 | * If the mouse was hot-plugged, we need to force differential mode | 374 | * If the mouse was hot-plugged, we need to force differential mode |
| 382 | * now... However, give it a second to recover from it's reset. | 375 | * now... However, give it a second to recover from it's reset. |
| 383 | */ | 376 | */ |
| 384 | printk (KERN_NOTICE "%s on %s: Forceing standard packet format, " | 377 | printk(KERN_NOTICE |
| 385 | "incremental streaming mode and 72 samples/sec\n", | 378 | "%s on %s: Forcing standard packet format, " |
| 386 | mouse->name, mouse->phys); | 379 | "incremental streaming mode and 72 samples/sec\n", |
| 387 | serio_write (mouse->serio, 'S'); /* Standard format */ | 380 | mouse->name, mouse->phys); |
| 388 | mdelay (50); | 381 | serio_write(mouse->serio, 'S'); /* Standard format */ |
| 389 | serio_write (mouse->serio, 'R'); /* Incremental */ | 382 | mdelay(50); |
| 390 | mdelay (50); | 383 | serio_write(mouse->serio, 'R'); /* Incremental */ |
| 391 | serio_write (mouse->serio, 'L'); /* 72 samples/sec */ | 384 | mdelay(50); |
| 385 | serio_write(mouse->serio, 'L'); /* 72 samples/sec */ | ||
| 392 | } | 386 | } |
| 393 | 387 | ||
| 394 | static void | 388 | static void vsxxxaa_parse_buffer(struct vsxxxaa *mouse) |
| 395 | vsxxxaa_parse_buffer (struct vsxxxaa *mouse) | ||
| 396 | { | 389 | { |
| 397 | unsigned char *buf = mouse->buf; | 390 | unsigned char *buf = mouse->buf; |
| 398 | int stray_bytes; | 391 | int stray_bytes; |
| @@ -409,122 +402,107 @@ vsxxxaa_parse_buffer (struct vsxxxaa *mouse) | |||
| 409 | * activity on the mouse. | 402 | * activity on the mouse. |
| 410 | */ | 403 | */ |
| 411 | while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) { | 404 | while (mouse->count > 0 && !IS_HDR_BYTE(buf[0])) { |
| 412 | printk (KERN_ERR "%s on %s: Dropping a byte to regain " | 405 | printk(KERN_ERR "%s on %s: Dropping a byte to regain " |
| 413 | "sync with mouse data stream...\n", | 406 | "sync with mouse data stream...\n", |
| 414 | mouse->name, mouse->phys); | 407 | mouse->name, mouse->phys); |
| 415 | vsxxxaa_drop_bytes (mouse, 1); | 408 | vsxxxaa_drop_bytes(mouse, 1); |
| 416 | } | 409 | } |
| 417 | 410 | ||
| 418 | /* | 411 | /* |
| 419 | * Check for packets we know about. | 412 | * Check for packets we know about. |
| 420 | */ | 413 | */ |
| 421 | 414 | ||
| 422 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_REL, 3)) { | 415 | if (vsxxxaa_smells_like_packet(mouse, VSXXXAA_PACKET_REL, 3)) { |
| 423 | /* Check for broken packet */ | 416 | /* Check for broken packet */ |
| 424 | stray_bytes = vsxxxaa_check_packet (mouse, 3); | 417 | stray_bytes = vsxxxaa_check_packet(mouse, 3); |
| 425 | if (stray_bytes > 0) { | 418 | if (!stray_bytes) |
| 426 | printk (KERN_ERR "Dropping %d bytes now...\n", | 419 | vsxxxaa_handle_REL_packet(mouse); |
| 427 | stray_bytes); | ||
| 428 | vsxxxaa_drop_bytes (mouse, stray_bytes); | ||
| 429 | continue; | ||
| 430 | } | ||
| 431 | |||
| 432 | vsxxxaa_handle_REL_packet (mouse); | ||
| 433 | continue; /* More to parse? */ | ||
| 434 | } | ||
| 435 | 420 | ||
| 436 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_ABS, 5)) { | 421 | } else if (vsxxxaa_smells_like_packet(mouse, |
| 422 | VSXXXAA_PACKET_ABS, 5)) { | ||
| 437 | /* Check for broken packet */ | 423 | /* Check for broken packet */ |
| 438 | stray_bytes = vsxxxaa_check_packet (mouse, 5); | 424 | stray_bytes = vsxxxaa_check_packet(mouse, 5); |
| 439 | if (stray_bytes > 0) { | 425 | if (!stray_bytes) |
| 440 | printk (KERN_ERR "Dropping %d bytes now...\n", | 426 | vsxxxaa_handle_ABS_packet(mouse); |
| 441 | stray_bytes); | ||
| 442 | vsxxxaa_drop_bytes (mouse, stray_bytes); | ||
| 443 | continue; | ||
| 444 | } | ||
| 445 | |||
| 446 | vsxxxaa_handle_ABS_packet (mouse); | ||
| 447 | continue; /* More to parse? */ | ||
| 448 | } | ||
| 449 | 427 | ||
| 450 | if (vsxxxaa_smells_like_packet (mouse, VSXXXAA_PACKET_POR, 4)) { | 428 | } else if (vsxxxaa_smells_like_packet(mouse, |
| 429 | VSXXXAA_PACKET_POR, 4)) { | ||
| 451 | /* Check for broken packet */ | 430 | /* Check for broken packet */ |
| 452 | stray_bytes = vsxxxaa_check_packet (mouse, 4); | 431 | stray_bytes = vsxxxaa_check_packet(mouse, 4); |
| 453 | if (stray_bytes > 0) { | 432 | if (!stray_bytes) |
| 454 | printk (KERN_ERR "Dropping %d bytes now...\n", | 433 | vsxxxaa_handle_POR_packet(mouse); |
| 455 | stray_bytes); | 434 | |
| 456 | vsxxxaa_drop_bytes (mouse, stray_bytes); | 435 | } else { |
| 457 | continue; | 436 | break; /* No REL, ABS or POR packet found */ |
| 458 | } | 437 | } |
| 459 | 438 | ||
| 460 | vsxxxaa_handle_POR_packet (mouse); | 439 | if (stray_bytes > 0) { |
| 461 | continue; /* More to parse? */ | 440 | printk(KERN_ERR "Dropping %d bytes now...\n", |
| 441 | stray_bytes); | ||
| 442 | vsxxxaa_drop_bytes(mouse, stray_bytes); | ||
| 462 | } | 443 | } |
| 463 | 444 | ||
| 464 | break; /* No REL, ABS or POR packet found */ | ||
| 465 | } while (1); | 445 | } while (1); |
| 466 | } | 446 | } |
| 467 | 447 | ||
| 468 | static irqreturn_t | 448 | static irqreturn_t vsxxxaa_interrupt(struct serio *serio, |
| 469 | vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags) | 449 | unsigned char data, unsigned int flags) |
| 470 | { | 450 | { |
| 471 | struct vsxxxaa *mouse = serio_get_drvdata (serio); | 451 | struct vsxxxaa *mouse = serio_get_drvdata(serio); |
| 472 | 452 | ||
| 473 | vsxxxaa_queue_byte (mouse, data); | 453 | vsxxxaa_queue_byte(mouse, data); |
| 474 | vsxxxaa_parse_buffer (mouse); | 454 | vsxxxaa_parse_buffer(mouse); |
| 475 | 455 | ||
| 476 | return IRQ_HANDLED; | 456 | return IRQ_HANDLED; |
| 477 | } | 457 | } |
| 478 | 458 | ||
| 479 | static void | 459 | static void vsxxxaa_disconnect(struct serio *serio) |
| 480 | vsxxxaa_disconnect (struct serio *serio) | ||
| 481 | { | 460 | { |
| 482 | struct vsxxxaa *mouse = serio_get_drvdata (serio); | 461 | struct vsxxxaa *mouse = serio_get_drvdata(serio); |
| 483 | 462 | ||
| 484 | serio_close (serio); | 463 | serio_close(serio); |
| 485 | serio_set_drvdata (serio, NULL); | 464 | serio_set_drvdata(serio, NULL); |
| 486 | input_unregister_device (mouse->dev); | 465 | input_unregister_device(mouse->dev); |
| 487 | kfree (mouse); | 466 | kfree(mouse); |
| 488 | } | 467 | } |
| 489 | 468 | ||
| 490 | static int | 469 | static int vsxxxaa_connect(struct serio *serio, struct serio_driver *drv) |
| 491 | vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | ||
| 492 | { | 470 | { |
| 493 | struct vsxxxaa *mouse; | 471 | struct vsxxxaa *mouse; |
| 494 | struct input_dev *input_dev; | 472 | struct input_dev *input_dev; |
| 495 | int err = -ENOMEM; | 473 | int err = -ENOMEM; |
| 496 | 474 | ||
| 497 | mouse = kzalloc (sizeof (struct vsxxxaa), GFP_KERNEL); | 475 | mouse = kzalloc(sizeof(struct vsxxxaa), GFP_KERNEL); |
| 498 | input_dev = input_allocate_device (); | 476 | input_dev = input_allocate_device(); |
| 499 | if (!mouse || !input_dev) | 477 | if (!mouse || !input_dev) |
| 500 | goto fail1; | 478 | goto fail1; |
| 501 | 479 | ||
| 502 | mouse->dev = input_dev; | 480 | mouse->dev = input_dev; |
| 503 | mouse->serio = serio; | 481 | mouse->serio = serio; |
| 504 | strlcat (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer", | 482 | strlcat(mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer", |
| 505 | sizeof (mouse->name)); | 483 | sizeof(mouse->name)); |
| 506 | snprintf (mouse->phys, sizeof (mouse->phys), "%s/input0", serio->phys); | 484 | snprintf(mouse->phys, sizeof(mouse->phys), "%s/input0", serio->phys); |
| 507 | 485 | ||
| 508 | input_dev->name = mouse->name; | 486 | input_dev->name = mouse->name; |
| 509 | input_dev->phys = mouse->phys; | 487 | input_dev->phys = mouse->phys; |
| 510 | input_dev->id.bustype = BUS_RS232; | 488 | input_dev->id.bustype = BUS_RS232; |
| 511 | input_dev->dev.parent = &serio->dev; | 489 | input_dev->dev.parent = &serio->dev; |
| 512 | 490 | ||
| 513 | set_bit (EV_KEY, input_dev->evbit); /* We have buttons */ | 491 | __set_bit(EV_KEY, input_dev->evbit); /* We have buttons */ |
| 514 | set_bit (EV_REL, input_dev->evbit); | 492 | __set_bit(EV_REL, input_dev->evbit); |
| 515 | set_bit (EV_ABS, input_dev->evbit); | 493 | __set_bit(EV_ABS, input_dev->evbit); |
| 516 | set_bit (BTN_LEFT, input_dev->keybit); /* We have 3 buttons */ | 494 | __set_bit(BTN_LEFT, input_dev->keybit); /* We have 3 buttons */ |
| 517 | set_bit (BTN_MIDDLE, input_dev->keybit); | 495 | __set_bit(BTN_MIDDLE, input_dev->keybit); |
| 518 | set_bit (BTN_RIGHT, input_dev->keybit); | 496 | __set_bit(BTN_RIGHT, input_dev->keybit); |
| 519 | set_bit (BTN_TOUCH, input_dev->keybit); /* ...and Tablet */ | 497 | __set_bit(BTN_TOUCH, input_dev->keybit); /* ...and Tablet */ |
| 520 | set_bit (REL_X, input_dev->relbit); | 498 | __set_bit(REL_X, input_dev->relbit); |
| 521 | set_bit (REL_Y, input_dev->relbit); | 499 | __set_bit(REL_Y, input_dev->relbit); |
| 522 | input_set_abs_params (input_dev, ABS_X, 0, 1023, 0, 0); | 500 | input_set_abs_params(input_dev, ABS_X, 0, 1023, 0, 0); |
| 523 | input_set_abs_params (input_dev, ABS_Y, 0, 1023, 0, 0); | 501 | input_set_abs_params(input_dev, ABS_Y, 0, 1023, 0, 0); |
| 524 | 502 | ||
| 525 | serio_set_drvdata (serio, mouse); | 503 | serio_set_drvdata(serio, mouse); |
| 526 | 504 | ||
| 527 | err = serio_open (serio, drv); | 505 | err = serio_open(serio, drv); |
| 528 | if (err) | 506 | if (err) |
| 529 | goto fail2; | 507 | goto fail2; |
| 530 | 508 | ||
| @@ -532,18 +510,18 @@ vsxxxaa_connect (struct serio *serio, struct serio_driver *drv) | |||
| 532 | * Request selftest. Standard packet format and differential | 510 | * Request selftest. Standard packet format and differential |
| 533 | * mode will be requested after the device ID'ed successfully. | 511 | * mode will be requested after the device ID'ed successfully. |
| 534 | */ | 512 | */ |
| 535 | serio_write (serio, 'T'); /* Test */ | 513 | serio_write(serio, 'T'); /* Test */ |
| 536 | 514 | ||
| 537 | err = input_register_device (input_dev); | 515 | err = input_register_device(input_dev); |
| 538 | if (err) | 516 | if (err) |
| 539 | goto fail3; | 517 | goto fail3; |
| 540 | 518 | ||
| 541 | return 0; | 519 | return 0; |
| 542 | 520 | ||
| 543 | fail3: serio_close (serio); | 521 | fail3: serio_close(serio); |
| 544 | fail2: serio_set_drvdata (serio, NULL); | 522 | fail2: serio_set_drvdata(serio, NULL); |
| 545 | fail1: input_free_device (input_dev); | 523 | fail1: input_free_device(input_dev); |
| 546 | kfree (mouse); | 524 | kfree(mouse); |
| 547 | return err; | 525 | return err; |
| 548 | } | 526 | } |
| 549 | 527 | ||
| @@ -570,18 +548,16 @@ static struct serio_driver vsxxxaa_drv = { | |||
| 570 | .disconnect = vsxxxaa_disconnect, | 548 | .disconnect = vsxxxaa_disconnect, |
| 571 | }; | 549 | }; |
| 572 | 550 | ||
| 573 | static int __init | 551 | static int __init vsxxxaa_init(void) |
| 574 | vsxxxaa_init (void) | ||
| 575 | { | 552 | { |
| 576 | return serio_register_driver(&vsxxxaa_drv); | 553 | return serio_register_driver(&vsxxxaa_drv); |
| 577 | } | 554 | } |
| 578 | 555 | ||
| 579 | static void __exit | 556 | static void __exit vsxxxaa_exit(void) |
| 580 | vsxxxaa_exit (void) | ||
| 581 | { | 557 | { |
| 582 | serio_unregister_driver(&vsxxxaa_drv); | 558 | serio_unregister_driver(&vsxxxaa_drv); |
| 583 | } | 559 | } |
| 584 | 560 | ||
| 585 | module_init (vsxxxaa_init); | 561 | module_init(vsxxxaa_init); |
| 586 | module_exit (vsxxxaa_exit); | 562 | module_exit(vsxxxaa_exit); |
| 587 | 563 | ||
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a13d80f7da17..f34b22bce4ff 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/smp_lock.h> | ||
| 19 | #include <linux/poll.h> | 18 | #include <linux/poll.h> |
| 20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
| 21 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| @@ -542,10 +541,8 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 542 | if (i >= MOUSEDEV_MINORS) | 541 | if (i >= MOUSEDEV_MINORS) |
| 543 | return -ENODEV; | 542 | return -ENODEV; |
| 544 | 543 | ||
| 545 | lock_kernel(); | ||
| 546 | error = mutex_lock_interruptible(&mousedev_table_mutex); | 544 | error = mutex_lock_interruptible(&mousedev_table_mutex); |
| 547 | if (error) { | 545 | if (error) { |
| 548 | unlock_kernel(); | ||
| 549 | return error; | 546 | return error; |
| 550 | } | 547 | } |
| 551 | mousedev = mousedev_table[i]; | 548 | mousedev = mousedev_table[i]; |
| @@ -554,7 +551,6 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 554 | mutex_unlock(&mousedev_table_mutex); | 551 | mutex_unlock(&mousedev_table_mutex); |
| 555 | 552 | ||
| 556 | if (!mousedev) { | 553 | if (!mousedev) { |
| 557 | unlock_kernel(); | ||
| 558 | return -ENODEV; | 554 | return -ENODEV; |
| 559 | } | 555 | } |
| 560 | 556 | ||
| @@ -575,7 +571,6 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 575 | goto err_free_client; | 571 | goto err_free_client; |
| 576 | 572 | ||
| 577 | file->private_data = client; | 573 | file->private_data = client; |
| 578 | unlock_kernel(); | ||
| 579 | return 0; | 574 | return 0; |
| 580 | 575 | ||
| 581 | err_free_client: | 576 | err_free_client: |
| @@ -583,7 +578,6 @@ static int mousedev_open(struct inode *inode, struct file *file) | |||
| 583 | kfree(client); | 578 | kfree(client); |
| 584 | err_put_mousedev: | 579 | err_put_mousedev: |
| 585 | put_device(&mousedev->dev); | 580 | put_device(&mousedev->dev); |
| 586 | unlock_kernel(); | ||
| 587 | return error; | 581 | return error; |
| 588 | } | 582 | } |
| 589 | 583 | ||
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index aa533ceffe34..7e319d65ec57 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
| @@ -201,4 +201,12 @@ config SERIO_XILINX_XPS_PS2 | |||
| 201 | To compile this driver as a module, choose M here: the | 201 | To compile this driver as a module, choose M here: the |
| 202 | module will be called xilinx_ps2. | 202 | module will be called xilinx_ps2. |
| 203 | 203 | ||
| 204 | config SERIO_ALTERA_PS2 | ||
| 205 | tristate "Altera UP PS/2 controller" | ||
| 206 | help | ||
| 207 | Say Y here if you have Altera University Program PS/2 ports. | ||
| 208 | |||
| 209 | To compile this driver as a module, choose M here: the | ||
| 210 | module will be called altera_ps2. | ||
| 211 | |||
| 204 | endif | 212 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index 9b6c8135955f..bf945f789d05 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
| @@ -22,3 +22,4 @@ obj-$(CONFIG_SERIO_MACEPS2) += maceps2.o | |||
| 22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o | 22 | obj-$(CONFIG_SERIO_LIBPS2) += libps2.o |
| 23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o | 23 | obj-$(CONFIG_SERIO_RAW) += serio_raw.o |
| 24 | obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o | 24 | obj-$(CONFIG_SERIO_XILINX_XPS_PS2) += xilinx_ps2.o |
| 25 | obj-$(CONFIG_SERIO_ALTERA_PS2) += altera_ps2.o | ||
diff --git a/drivers/input/serio/altera_ps2.c b/drivers/input/serio/altera_ps2.c new file mode 100644 index 000000000000..7998560a1904 --- /dev/null +++ b/drivers/input/serio/altera_ps2.c | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | /* | ||
| 2 | * Altera University Program PS2 controller driver | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw> | ||
| 5 | * | ||
| 6 | * Based on sa1111ps2.c, which is: | ||
| 7 | * Copyright (C) 2002 Russell King | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/serio.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/platform_device.h> | ||
| 20 | #include <linux/io.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | |||
| 23 | #define DRV_NAME "altera_ps2" | ||
| 24 | |||
| 25 | struct ps2if { | ||
| 26 | struct serio *io; | ||
| 27 | struct resource *iomem_res; | ||
| 28 | void __iomem *base; | ||
| 29 | unsigned irq; | ||
| 30 | }; | ||
| 31 | |||
| 32 | /* | ||
| 33 | * Read all bytes waiting in the PS2 port. There should be | ||
| 34 | * at the most one, but we loop for safety. | ||
| 35 | */ | ||
| 36 | static irqreturn_t altera_ps2_rxint(int irq, void *dev_id) | ||
| 37 | { | ||
| 38 | struct ps2if *ps2if = dev_id; | ||
| 39 | unsigned int status; | ||
| 40 | int handled = IRQ_NONE; | ||
| 41 | |||
| 42 | while ((status = readl(ps2if->base)) & 0xffff0000) { | ||
| 43 | serio_interrupt(ps2if->io, status & 0xff, 0); | ||
| 44 | handled = IRQ_HANDLED; | ||
| 45 | } | ||
| 46 | |||
| 47 | return handled; | ||
| 48 | } | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Write a byte to the PS2 port. | ||
| 52 | */ | ||
| 53 | static int altera_ps2_write(struct serio *io, unsigned char val) | ||
| 54 | { | ||
| 55 | struct ps2if *ps2if = io->port_data; | ||
| 56 | |||
| 57 | writel(val, ps2if->base); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static int altera_ps2_open(struct serio *io) | ||
| 62 | { | ||
| 63 | struct ps2if *ps2if = io->port_data; | ||
| 64 | |||
| 65 | /* clear fifo */ | ||
| 66 | while (readl(ps2if->base) & 0xffff0000) | ||
| 67 | /* empty */; | ||
| 68 | |||
| 69 | writel(1, ps2if->base + 4); /* enable rx irq */ | ||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static void altera_ps2_close(struct serio *io) | ||
| 74 | { | ||
| 75 | struct ps2if *ps2if = io->port_data; | ||
| 76 | |||
| 77 | writel(0, ps2if->base); /* disable rx irq */ | ||
| 78 | } | ||
| 79 | |||
| 80 | /* | ||
| 81 | * Add one device to this driver. | ||
| 82 | */ | ||
| 83 | static int __devinit altera_ps2_probe(struct platform_device *pdev) | ||
| 84 | { | ||
| 85 | struct ps2if *ps2if; | ||
| 86 | struct serio *serio; | ||
| 87 | int error, irq; | ||
| 88 | |||
| 89 | ps2if = kzalloc(sizeof(struct ps2if), GFP_KERNEL); | ||
| 90 | serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
| 91 | if (!ps2if || !serio) { | ||
| 92 | error = -ENOMEM; | ||
| 93 | goto err_free_mem; | ||
| 94 | } | ||
| 95 | |||
| 96 | serio->id.type = SERIO_8042; | ||
| 97 | serio->write = altera_ps2_write; | ||
| 98 | serio->open = altera_ps2_open; | ||
| 99 | serio->close = altera_ps2_close; | ||
| 100 | strlcpy(serio->name, dev_name(&pdev->dev), sizeof(serio->name)); | ||
| 101 | strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys)); | ||
| 102 | serio->port_data = ps2if; | ||
| 103 | serio->dev.parent = &pdev->dev; | ||
| 104 | ps2if->io = serio; | ||
| 105 | |||
| 106 | ps2if->iomem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 107 | if (ps2if->iomem_res == NULL) { | ||
| 108 | error = -ENOENT; | ||
| 109 | goto err_free_mem; | ||
| 110 | } | ||
| 111 | |||
| 112 | |||
| 113 | irq = platform_get_irq(pdev, 0); | ||
| 114 | if (irq < 0) { | ||
| 115 | error = -ENXIO; | ||
| 116 | goto err_free_mem; | ||
| 117 | } | ||
| 118 | ps2if->irq = irq; | ||
| 119 | |||
| 120 | if (!request_mem_region(ps2if->iomem_res->start, | ||
| 121 | resource_size(ps2if->iomem_res), pdev->name)) { | ||
| 122 | error = -EBUSY; | ||
| 123 | goto err_free_mem; | ||
| 124 | } | ||
| 125 | |||
| 126 | ps2if->base = ioremap(ps2if->iomem_res->start, | ||
| 127 | resource_size(ps2if->iomem_res)); | ||
| 128 | if (!ps2if->base) { | ||
| 129 | error = -ENOMEM; | ||
| 130 | goto err_free_res; | ||
| 131 | } | ||
| 132 | |||
| 133 | error = request_irq(ps2if->irq, altera_ps2_rxint, 0, pdev->name, ps2if); | ||
| 134 | if (error) { | ||
| 135 | dev_err(&pdev->dev, "could not allocate IRQ %d: %d\n", | ||
| 136 | ps2if->irq, error); | ||
| 137 | goto err_unmap; | ||
| 138 | } | ||
| 139 | |||
| 140 | dev_info(&pdev->dev, "base %p, irq %d\n", ps2if->base, ps2if->irq); | ||
| 141 | |||
| 142 | serio_register_port(ps2if->io); | ||
| 143 | platform_set_drvdata(pdev, ps2if); | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | |||
| 147 | err_unmap: | ||
| 148 | iounmap(ps2if->base); | ||
| 149 | err_free_res: | ||
| 150 | release_mem_region(ps2if->iomem_res->start, | ||
| 151 | resource_size(ps2if->iomem_res)); | ||
| 152 | err_free_mem: | ||
| 153 | kfree(ps2if); | ||
| 154 | kfree(serio); | ||
| 155 | return error; | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 159 | * Remove one device from this driver. | ||
| 160 | */ | ||
| 161 | static int __devexit altera_ps2_remove(struct platform_device *pdev) | ||
| 162 | { | ||
| 163 | struct ps2if *ps2if = platform_get_drvdata(pdev); | ||
| 164 | |||
| 165 | platform_set_drvdata(pdev, NULL); | ||
| 166 | serio_unregister_port(ps2if->io); | ||
| 167 | free_irq(ps2if->irq, ps2if); | ||
| 168 | iounmap(ps2if->base); | ||
| 169 | release_mem_region(ps2if->iomem_res->start, | ||
| 170 | resource_size(ps2if->iomem_res)); | ||
| 171 | kfree(ps2if); | ||
| 172 | |||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Our device driver structure | ||
| 178 | */ | ||
| 179 | static struct platform_driver altera_ps2_driver = { | ||
| 180 | .probe = altera_ps2_probe, | ||
| 181 | .remove = __devexit_p(altera_ps2_remove), | ||
| 182 | .driver = { | ||
| 183 | .name = DRV_NAME, | ||
| 184 | .owner = THIS_MODULE, | ||
| 185 | }, | ||
| 186 | }; | ||
| 187 | |||
| 188 | static int __init altera_ps2_init(void) | ||
| 189 | { | ||
| 190 | return platform_driver_register(&altera_ps2_driver); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void __exit altera_ps2_exit(void) | ||
| 194 | { | ||
| 195 | platform_driver_unregister(&altera_ps2_driver); | ||
| 196 | } | ||
| 197 | |||
| 198 | module_init(altera_ps2_init); | ||
| 199 | module_exit(altera_ps2_exit); | ||
| 200 | |||
| 201 | MODULE_DESCRIPTION("Altera University Program PS2 controller driver"); | ||
| 202 | MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>"); | ||
| 203 | MODULE_LICENSE("GPL"); | ||
| 204 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c index 89b394183a75..92563a681d65 100644 --- a/drivers/input/serio/ambakmi.c +++ b/drivers/input/serio/ambakmi.c | |||
| @@ -107,7 +107,7 @@ static void amba_kmi_close(struct serio *io) | |||
| 107 | clk_disable(kmi->clk); | 107 | clk_disable(kmi->clk); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | 110 | static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id) |
| 111 | { | 111 | { |
| 112 | struct amba_kmi_port *kmi; | 112 | struct amba_kmi_port *kmi; |
| 113 | struct serio *io; | 113 | struct serio *io; |
| @@ -134,7 +134,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
| 134 | io->port_data = kmi; | 134 | io->port_data = kmi; |
| 135 | io->dev.parent = &dev->dev; | 135 | io->dev.parent = &dev->dev; |
| 136 | 136 | ||
| 137 | kmi->io = io; | 137 | kmi->io = io; |
| 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); | 138 | kmi->base = ioremap(dev->res.start, resource_size(&dev->res)); |
| 139 | if (!kmi->base) { | 139 | if (!kmi->base) { |
| 140 | ret = -ENOMEM; | 140 | ret = -ENOMEM; |
| @@ -162,7 +162,7 @@ static int amba_kmi_probe(struct amba_device *dev, struct amba_id *id) | |||
| 162 | return ret; | 162 | return ret; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | static int amba_kmi_remove(struct amba_device *dev) | 165 | static int __devexit amba_kmi_remove(struct amba_device *dev) |
| 166 | { | 166 | { |
| 167 | struct amba_kmi_port *kmi = amba_get_drvdata(dev); | 167 | struct amba_kmi_port *kmi = amba_get_drvdata(dev); |
| 168 | 168 | ||
| @@ -197,10 +197,11 @@ static struct amba_id amba_kmi_idtable[] = { | |||
| 197 | static struct amba_driver ambakmi_driver = { | 197 | static struct amba_driver ambakmi_driver = { |
| 198 | .drv = { | 198 | .drv = { |
| 199 | .name = "kmi-pl050", | 199 | .name = "kmi-pl050", |
| 200 | .owner = THIS_MODULE, | ||
| 200 | }, | 201 | }, |
| 201 | .id_table = amba_kmi_idtable, | 202 | .id_table = amba_kmi_idtable, |
| 202 | .probe = amba_kmi_probe, | 203 | .probe = amba_kmi_probe, |
| 203 | .remove = amba_kmi_remove, | 204 | .remove = __devexit_p(amba_kmi_remove), |
| 204 | .resume = amba_kmi_resume, | 205 | .resume = amba_kmi_resume, |
| 205 | }; | 206 | }; |
| 206 | 207 | ||
diff --git a/drivers/input/serio/at32psif.c b/drivers/input/serio/at32psif.c index a6fb7a3dcc46..6ee8f0ddad51 100644 --- a/drivers/input/serio/at32psif.c +++ b/drivers/input/serio/at32psif.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
| 19 | #include <linux/clk.h> | 19 | #include <linux/clk.h> |
| 20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
| 21 | #include <linux/slab.h> | ||
| 21 | 22 | ||
| 22 | /* PSIF register offsets */ | 23 | /* PSIF register offsets */ |
| 23 | #define PSIF_CR 0x00 | 24 | #define PSIF_CR 0x00 |
| @@ -137,7 +138,7 @@ static int psif_write(struct serio *io, unsigned char val) | |||
| 137 | spin_lock_irqsave(&psif->lock, flags); | 138 | spin_lock_irqsave(&psif->lock, flags); |
| 138 | 139 | ||
| 139 | while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) | 140 | while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) |
| 140 | msleep(10); | 141 | udelay(50); |
| 141 | 142 | ||
| 142 | if (timeout >= 0) { | 143 | if (timeout >= 0) { |
| 143 | psif_writel(psif, THR, val); | 144 | psif_writel(psif, THR, val); |
| @@ -352,6 +353,7 @@ static struct platform_driver psif_driver = { | |||
| 352 | .remove = __exit_p(psif_remove), | 353 | .remove = __exit_p(psif_remove), |
| 353 | .driver = { | 354 | .driver = { |
| 354 | .name = "atmel_psif", | 355 | .name = "atmel_psif", |
| 356 | .owner = THIS_MODULE, | ||
| 355 | }, | 357 | }, |
| 356 | .suspend = psif_suspend, | 358 | .suspend = psif_suspend, |
| 357 | .resume = psif_resume, | 359 | .resume = psif_resume, |
diff --git a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c index d1380fc72cc6..4a3084695c00 100644 --- a/drivers/input/serio/ct82c710.c +++ b/drivers/input/serio/ct82c710.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
| 36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
| 37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
| 38 | #include <linux/slab.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
| 40 | 41 | ||
diff --git a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c index bd0f92d9f40f..3c287dd879d3 100644 --- a/drivers/input/serio/gscps2.c +++ b/drivers/input/serio/gscps2.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> | 6 | * Copyright (c) 2002 Thibaut Varene <varenet@parisc-linux.org> |
| 7 | * | 7 | * |
| 8 | * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c | 8 | * Pieces of code based on linux-2.4's hp_mouse.c & hp_keyb.c |
| 9 | * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> | 9 | * Copyright (c) 1999 Alex deVries <alex@onefishtwo.ca> |
| 10 | * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> | 10 | * Copyright (c) 1999-2000 Philipp Rumpf <prumpf@tux.org> |
| 11 | * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> | 11 | * Copyright (c) 2000 Xavier Debacker <debackex@esiee.fr> |
| 12 | * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> | 12 | * Copyright (c) 2000-2001 Thomas Marteau <marteaut@esiee.fr> |
| @@ -24,6 +24,7 @@ | |||
| 24 | 24 | ||
| 25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/slab.h> | ||
| 27 | #include <linux/serio.h> | 28 | #include <linux/serio.h> |
| 28 | #include <linux/input.h> | 29 | #include <linux/input.h> |
| 29 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
| @@ -326,7 +327,7 @@ static void gscps2_close(struct serio *port) | |||
| 326 | * @return: success/error report | 327 | * @return: success/error report |
| 327 | */ | 328 | */ |
| 328 | 329 | ||
| 329 | static int __init gscps2_probe(struct parisc_device *dev) | 330 | static int __devinit gscps2_probe(struct parisc_device *dev) |
| 330 | { | 331 | { |
| 331 | struct gscps2port *ps2port; | 332 | struct gscps2port *ps2port; |
| 332 | struct serio *serio; | 333 | struct serio *serio; |
| @@ -443,7 +444,7 @@ static struct parisc_driver parisc_ps2_driver = { | |||
| 443 | .name = "gsc_ps2", | 444 | .name = "gsc_ps2", |
| 444 | .id_table = gscps2_device_tbl, | 445 | .id_table = gscps2_device_tbl, |
| 445 | .probe = gscps2_probe, | 446 | .probe = gscps2_probe, |
| 446 | .remove = gscps2_remove, | 447 | .remove = __devexit_p(gscps2_remove), |
| 447 | }; | 448 | }; |
| 448 | 449 | ||
| 449 | static int __init gscps2_init(void) | 450 | static int __init gscps2_init(void) |
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c index 7ba9f2b2c041..c92f4edfee7b 100644 --- a/drivers/input/serio/hil_mlc.c +++ b/drivers/input/serio/hil_mlc.c | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #include <linux/module.h> | 58 | #include <linux/module.h> |
| 59 | #include <linux/init.h> | 59 | #include <linux/init.h> |
| 60 | #include <linux/interrupt.h> | 60 | #include <linux/interrupt.h> |
| 61 | #include <linux/slab.h> | ||
| 61 | #include <linux/timer.h> | 62 | #include <linux/timer.h> |
| 62 | #include <linux/list.h> | 63 | #include <linux/list.h> |
| 63 | 64 | ||
| @@ -993,10 +994,8 @@ int hil_mlc_unregister(hil_mlc *mlc) | |||
| 993 | 994 | ||
| 994 | static int __init hil_mlc_init(void) | 995 | static int __init hil_mlc_init(void) |
| 995 | { | 996 | { |
| 996 | init_timer(&hil_mlcs_kicker); | 997 | setup_timer(&hil_mlcs_kicker, &hil_mlcs_timer, 0); |
| 997 | hil_mlcs_kicker.expires = jiffies + HZ; | 998 | mod_timer(&hil_mlcs_kicker, jiffies + HZ); |
| 998 | hil_mlcs_kicker.function = &hil_mlcs_timer; | ||
| 999 | add_timer(&hil_mlcs_kicker); | ||
| 1000 | 999 | ||
| 1001 | tasklet_enable(&hil_mlcs_tasklet); | 1000 | tasklet_enable(&hil_mlcs_tasklet); |
| 1002 | 1001 | ||
| @@ -1005,7 +1004,7 @@ static int __init hil_mlc_init(void) | |||
| 1005 | 1004 | ||
| 1006 | static void __exit hil_mlc_exit(void) | 1005 | static void __exit hil_mlc_exit(void) |
| 1007 | { | 1006 | { |
| 1008 | del_timer(&hil_mlcs_kicker); | 1007 | del_timer_sync(&hil_mlcs_kicker); |
| 1009 | 1008 | ||
| 1010 | tasklet_disable(&hil_mlcs_tasklet); | 1009 | tasklet_disable(&hil_mlcs_tasklet); |
| 1011 | tasklet_kill(&hil_mlcs_tasklet); | 1010 | tasklet_kill(&hil_mlcs_tasklet); |
diff --git a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c index 1c9410d1822c..bcc2d30ec245 100644 --- a/drivers/input/serio/hp_sdc.c +++ b/drivers/input/serio/hp_sdc.c | |||
| @@ -955,7 +955,7 @@ static int __init hp_sdc_init_hppa(struct parisc_device *d) | |||
| 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); | 955 | INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed); |
| 956 | 956 | ||
| 957 | ret = hp_sdc_init(); | 957 | ret = hp_sdc_init(); |
| 958 | /* after sucessfull initialization give SDC some time to settle | 958 | /* after successfull initialization give SDC some time to settle |
| 959 | * and then load the hp_sdc_mlc upper layer driver */ | 959 | * and then load the hp_sdc_mlc upper layer driver */ |
| 960 | if (!ret) | 960 | if (!ret) |
| 961 | schedule_delayed_work(&moduleloader_work, | 961 | schedule_delayed_work(&moduleloader_work, |
diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index 820e51673b26..7d2b820ef58d 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c | |||
| @@ -125,7 +125,7 @@ static void hp_sdc_mlc_isr (int irq, void *dev_id, | |||
| 125 | break; | 125 | break; |
| 126 | 126 | ||
| 127 | default: | 127 | default: |
| 128 | printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data); | 128 | printk(KERN_WARNING PREFIX "Unknown HIL Error status (%x)!\n", data); |
| 129 | break; | 129 | break; |
| 130 | } | 130 | } |
| 131 | 131 | ||
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2bcf1ace27c0..ead0494721d0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
| @@ -67,10 +67,12 @@ static inline void i8042_write_command(int val) | |||
| 67 | 67 | ||
| 68 | #include <linux/dmi.h> | 68 | #include <linux/dmi.h> |
| 69 | 69 | ||
| 70 | static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | 70 | static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { |
| 71 | { | 71 | { |
| 72 | /* AUX LOOP command does not raise AUX IRQ */ | 72 | /* |
| 73 | .ident = "Arima-Rioworks HDAMB", | 73 | * Arima-Rioworks HDAMB - |
| 74 | * AUX LOOP command does not raise AUX IRQ | ||
| 75 | */ | ||
| 74 | .matches = { | 76 | .matches = { |
| 75 | DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), | 77 | DMI_MATCH(DMI_BOARD_VENDOR, "RIOWORKS"), |
| 76 | DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), | 78 | DMI_MATCH(DMI_BOARD_NAME, "HDAMB"), |
| @@ -78,7 +80,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 78 | }, | 80 | }, |
| 79 | }, | 81 | }, |
| 80 | { | 82 | { |
| 81 | .ident = "ASUS G1S", | 83 | /* ASUS G1S */ |
| 82 | .matches = { | 84 | .matches = { |
| 83 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), | 85 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc."), |
| 84 | DMI_MATCH(DMI_BOARD_NAME, "G1S"), | 86 | DMI_MATCH(DMI_BOARD_NAME, "G1S"), |
| @@ -86,8 +88,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 86 | }, | 88 | }, |
| 87 | }, | 89 | }, |
| 88 | { | 90 | { |
| 89 | /* AUX LOOP command does not raise AUX IRQ */ | 91 | /* ASUS P65UP5 - AUX LOOP command does not raise AUX IRQ */ |
| 90 | .ident = "ASUS P65UP5", | ||
| 91 | .matches = { | 92 | .matches = { |
| 92 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), | 93 | DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), |
| 93 | DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"), | 94 | DMI_MATCH(DMI_BOARD_NAME, "P/I-P65UP5"), |
| @@ -95,7 +96,6 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 95 | }, | 96 | }, |
| 96 | }, | 97 | }, |
| 97 | { | 98 | { |
| 98 | .ident = "Compaq Proliant 8500", | ||
| 99 | .matches = { | 99 | .matches = { |
| 100 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), | 100 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), |
| 101 | DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), | 101 | DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), |
| @@ -103,7 +103,6 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 103 | }, | 103 | }, |
| 104 | }, | 104 | }, |
| 105 | { | 105 | { |
| 106 | .ident = "Compaq Proliant DL760", | ||
| 107 | .matches = { | 106 | .matches = { |
| 108 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), | 107 | DMI_MATCH(DMI_SYS_VENDOR, "Compaq"), |
| 109 | DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), | 108 | DMI_MATCH(DMI_PRODUCT_NAME , "ProLiant"), |
| @@ -111,7 +110,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 111 | }, | 110 | }, |
| 112 | }, | 111 | }, |
| 113 | { | 112 | { |
| 114 | .ident = "OQO Model 01", | 113 | /* OQO Model 01 */ |
| 115 | .matches = { | 114 | .matches = { |
| 116 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), | 115 | DMI_MATCH(DMI_SYS_VENDOR, "OQO"), |
| 117 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), | 116 | DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), |
| @@ -119,8 +118,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 119 | }, | 118 | }, |
| 120 | }, | 119 | }, |
| 121 | { | 120 | { |
| 122 | /* AUX LOOP does not work properly */ | 121 | /* ULI EV4873 - AUX LOOP does not work properly */ |
| 123 | .ident = "ULI EV4873", | ||
| 124 | .matches = { | 122 | .matches = { |
| 125 | DMI_MATCH(DMI_SYS_VENDOR, "ULI"), | 123 | DMI_MATCH(DMI_SYS_VENDOR, "ULI"), |
| 126 | DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"), | 124 | DMI_MATCH(DMI_PRODUCT_NAME, "EV4873"), |
| @@ -128,7 +126,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 128 | }, | 126 | }, |
| 129 | }, | 127 | }, |
| 130 | { | 128 | { |
| 131 | .ident = "Microsoft Virtual Machine", | 129 | /* Microsoft Virtual Machine */ |
| 132 | .matches = { | 130 | .matches = { |
| 133 | DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), | 131 | DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), |
| 134 | DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), | 132 | DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), |
| @@ -136,7 +134,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 136 | }, | 134 | }, |
| 137 | }, | 135 | }, |
| 138 | { | 136 | { |
| 139 | .ident = "Medion MAM 2070", | 137 | /* Medion MAM 2070 */ |
| 140 | .matches = { | 138 | .matches = { |
| 141 | DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), | 139 | DMI_MATCH(DMI_SYS_VENDOR, "Notebook"), |
| 142 | DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), | 140 | DMI_MATCH(DMI_PRODUCT_NAME, "MAM 2070"), |
| @@ -144,7 +142,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 144 | }, | 142 | }, |
| 145 | }, | 143 | }, |
| 146 | { | 144 | { |
| 147 | .ident = "Blue FB5601", | 145 | /* Blue FB5601 */ |
| 148 | .matches = { | 146 | .matches = { |
| 149 | DMI_MATCH(DMI_SYS_VENDOR, "blue"), | 147 | DMI_MATCH(DMI_SYS_VENDOR, "blue"), |
| 150 | DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"), | 148 | DMI_MATCH(DMI_PRODUCT_NAME, "FB5601"), |
| @@ -152,7 +150,7 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 152 | }, | 150 | }, |
| 153 | }, | 151 | }, |
| 154 | { | 152 | { |
| 155 | .ident = "Gigabyte M912", | 153 | /* Gigabyte M912 */ |
| 156 | .matches = { | 154 | .matches = { |
| 157 | DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), | 155 | DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), |
| 158 | DMI_MATCH(DMI_PRODUCT_NAME, "M912"), | 156 | DMI_MATCH(DMI_PRODUCT_NAME, "M912"), |
| @@ -160,7 +158,14 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 160 | }, | 158 | }, |
| 161 | }, | 159 | }, |
| 162 | { | 160 | { |
| 163 | .ident = "HP DV9700", | 161 | /* Gigabyte M1022M netbook */ |
| 162 | .matches = { | ||
| 163 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co.,Ltd."), | ||
| 164 | DMI_MATCH(DMI_BOARD_NAME, "M1022E"), | ||
| 165 | DMI_MATCH(DMI_BOARD_VERSION, "1.02"), | ||
| 166 | }, | ||
| 167 | }, | ||
| 168 | { | ||
| 164 | .matches = { | 169 | .matches = { |
| 165 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 170 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 166 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), | 171 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv9700"), |
| @@ -177,72 +182,72 @@ static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { | |||
| 177 | * ... apparently some Toshibas don't like MUX mode either and | 182 | * ... apparently some Toshibas don't like MUX mode either and |
| 178 | * die horrible death on reboot. | 183 | * die horrible death on reboot. |
| 179 | */ | 184 | */ |
| 180 | static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | 185 | static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { |
| 181 | { | 186 | { |
| 182 | .ident = "Fujitsu Lifebook P7010/P7010D", | 187 | /* Fujitsu Lifebook P7010/P7010D */ |
| 183 | .matches = { | 188 | .matches = { |
| 184 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 189 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 185 | DMI_MATCH(DMI_PRODUCT_NAME, "P7010"), | 190 | DMI_MATCH(DMI_PRODUCT_NAME, "P7010"), |
| 186 | }, | 191 | }, |
| 187 | }, | 192 | }, |
| 188 | { | 193 | { |
| 189 | .ident = "Fujitsu Lifebook P7010", | 194 | /* Fujitsu Lifebook P7010 */ |
| 190 | .matches = { | 195 | .matches = { |
| 191 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 196 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 192 | DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"), | 197 | DMI_MATCH(DMI_PRODUCT_NAME, "0000000000"), |
| 193 | }, | 198 | }, |
| 194 | }, | 199 | }, |
| 195 | { | 200 | { |
| 196 | .ident = "Fujitsu Lifebook P5020D", | 201 | /* Fujitsu Lifebook P5020D */ |
| 197 | .matches = { | 202 | .matches = { |
| 198 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 203 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 199 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"), | 204 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"), |
| 200 | }, | 205 | }, |
| 201 | }, | 206 | }, |
| 202 | { | 207 | { |
| 203 | .ident = "Fujitsu Lifebook S2000", | 208 | /* Fujitsu Lifebook S2000 */ |
| 204 | .matches = { | 209 | .matches = { |
| 205 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 210 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 206 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"), | 211 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"), |
| 207 | }, | 212 | }, |
| 208 | }, | 213 | }, |
| 209 | { | 214 | { |
| 210 | .ident = "Fujitsu Lifebook S6230", | 215 | /* Fujitsu Lifebook S6230 */ |
| 211 | .matches = { | 216 | .matches = { |
| 212 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 217 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 213 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), | 218 | DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"), |
| 214 | }, | 219 | }, |
| 215 | }, | 220 | }, |
| 216 | { | 221 | { |
| 217 | .ident = "Fujitsu T70H", | 222 | /* Fujitsu T70H */ |
| 218 | .matches = { | 223 | .matches = { |
| 219 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), | 224 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), |
| 220 | DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"), | 225 | DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"), |
| 221 | }, | 226 | }, |
| 222 | }, | 227 | }, |
| 223 | { | 228 | { |
| 224 | .ident = "Fujitsu-Siemens Lifebook T3010", | 229 | /* Fujitsu-Siemens Lifebook T3010 */ |
| 225 | .matches = { | 230 | .matches = { |
| 226 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 231 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 227 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), | 232 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), |
| 228 | }, | 233 | }, |
| 229 | }, | 234 | }, |
| 230 | { | 235 | { |
| 231 | .ident = "Fujitsu-Siemens Lifebook E4010", | 236 | /* Fujitsu-Siemens Lifebook E4010 */ |
| 232 | .matches = { | 237 | .matches = { |
| 233 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 238 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 234 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), | 239 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), |
| 235 | }, | 240 | }, |
| 236 | }, | 241 | }, |
| 237 | { | 242 | { |
| 238 | .ident = "Fujitsu-Siemens Amilo Pro 2010", | 243 | /* Fujitsu-Siemens Amilo Pro 2010 */ |
| 239 | .matches = { | 244 | .matches = { |
| 240 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 245 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 241 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"), | 246 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pro V2010"), |
| 242 | }, | 247 | }, |
| 243 | }, | 248 | }, |
| 244 | { | 249 | { |
| 245 | .ident = "Fujitsu-Siemens Amilo Pro 2030", | 250 | /* Fujitsu-Siemens Amilo Pro 2030 */ |
| 246 | .matches = { | 251 | .matches = { |
| 247 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), | 252 | DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), |
| 248 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), | 253 | DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), |
| @@ -253,7 +258,7 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 253 | * No data is coming from the touchscreen unless KBC | 258 | * No data is coming from the touchscreen unless KBC |
| 254 | * is in legacy mode. | 259 | * is in legacy mode. |
| 255 | */ | 260 | */ |
| 256 | .ident = "Panasonic CF-29", | 261 | /* Panasonic CF-29 */ |
| 257 | .matches = { | 262 | .matches = { |
| 258 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), | 263 | DMI_MATCH(DMI_SYS_VENDOR, "Matsushita"), |
| 259 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), | 264 | DMI_MATCH(DMI_PRODUCT_NAME, "CF-29"), |
| @@ -261,10 +266,10 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 261 | }, | 266 | }, |
| 262 | { | 267 | { |
| 263 | /* | 268 | /* |
| 264 | * Errors on MUX ports are reported without raising AUXDATA | 269 | * HP Pavilion DV4017EA - |
| 270 | * errors on MUX ports are reported without raising AUXDATA | ||
| 265 | * causing "spurious NAK" messages. | 271 | * causing "spurious NAK" messages. |
| 266 | */ | 272 | */ |
| 267 | .ident = "HP Pavilion DV4017EA", | ||
| 268 | .matches = { | 273 | .matches = { |
| 269 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 274 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 270 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"), | 275 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EA032EA#ABF)"), |
| @@ -272,9 +277,9 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 272 | }, | 277 | }, |
| 273 | { | 278 | { |
| 274 | /* | 279 | /* |
| 275 | * Like DV4017EA does not raise AUXERR for errors on MUX ports. | 280 | * HP Pavilion ZT1000 - |
| 281 | * like DV4017EA does not raise AUXERR for errors on MUX ports. | ||
| 276 | */ | 282 | */ |
| 277 | .ident = "HP Pavilion ZT1000", | ||
| 278 | .matches = { | 283 | .matches = { |
| 279 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 284 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 280 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), | 285 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Notebook PC"), |
| @@ -283,44 +288,41 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 283 | }, | 288 | }, |
| 284 | { | 289 | { |
| 285 | /* | 290 | /* |
| 286 | * Like DV4017EA does not raise AUXERR for errors on MUX ports. | 291 | * HP Pavilion DV4270ca - |
| 292 | * like DV4017EA does not raise AUXERR for errors on MUX ports. | ||
| 287 | */ | 293 | */ |
| 288 | .ident = "HP Pavilion DV4270ca", | ||
| 289 | .matches = { | 294 | .matches = { |
| 290 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | 295 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), |
| 291 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"), | 296 | DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion dv4000 (EH476UA#ABL)"), |
| 292 | }, | 297 | }, |
| 293 | }, | 298 | }, |
| 294 | { | 299 | { |
| 295 | .ident = "Toshiba P10", | ||
| 296 | .matches = { | 300 | .matches = { |
| 297 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 301 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 298 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), | 302 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), |
| 299 | }, | 303 | }, |
| 300 | }, | 304 | }, |
| 301 | { | 305 | { |
| 302 | .ident = "Toshiba Equium A110", | ||
| 303 | .matches = { | 306 | .matches = { |
| 304 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | 307 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), |
| 305 | DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), | 308 | DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), |
| 306 | }, | 309 | }, |
| 307 | }, | 310 | }, |
| 308 | { | 311 | { |
| 309 | .ident = "Alienware Sentia", | ||
| 310 | .matches = { | 312 | .matches = { |
| 311 | DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), | 313 | DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), |
| 312 | DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), | 314 | DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), |
| 313 | }, | 315 | }, |
| 314 | }, | 316 | }, |
| 315 | { | 317 | { |
| 316 | .ident = "Sharp Actius MM20", | 318 | /* Sharp Actius MM20 */ |
| 317 | .matches = { | 319 | .matches = { |
| 318 | DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), | 320 | DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), |
| 319 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), | 321 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), |
| 320 | }, | 322 | }, |
| 321 | }, | 323 | }, |
| 322 | { | 324 | { |
| 323 | .ident = "Sony Vaio FS-115b", | 325 | /* Sony Vaio FS-115b */ |
| 324 | .matches = { | 326 | .matches = { |
| 325 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 327 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
| 326 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | 328 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), |
| @@ -328,73 +330,72 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 328 | }, | 330 | }, |
| 329 | { | 331 | { |
| 330 | /* | 332 | /* |
| 331 | * Reset and GET ID commands issued via KBD port are | 333 | * Sony Vaio FZ-240E - |
| 334 | * reset and GET ID commands issued via KBD port are | ||
| 332 | * sometimes being delivered to AUX3. | 335 | * sometimes being delivered to AUX3. |
| 333 | */ | 336 | */ |
| 334 | .ident = "Sony Vaio FZ-240E", | ||
| 335 | .matches = { | 337 | .matches = { |
| 336 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 338 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
| 337 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"), | 339 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"), |
| 338 | }, | 340 | }, |
| 339 | }, | 341 | }, |
| 340 | { | 342 | { |
| 341 | .ident = "Amoi M636/A737", | 343 | /* Amoi M636/A737 */ |
| 342 | .matches = { | 344 | .matches = { |
| 343 | DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), | 345 | DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."), |
| 344 | DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), | 346 | DMI_MATCH(DMI_PRODUCT_NAME, "M636/A737 platform"), |
| 345 | }, | 347 | }, |
| 346 | }, | 348 | }, |
| 347 | { | 349 | { |
| 348 | .ident = "Lenovo 3000 n100", | 350 | /* Lenovo 3000 n100 */ |
| 349 | .matches = { | 351 | .matches = { |
| 350 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | 352 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), |
| 351 | DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), | 353 | DMI_MATCH(DMI_PRODUCT_NAME, "076804U"), |
| 352 | }, | 354 | }, |
| 353 | }, | 355 | }, |
| 354 | { | 356 | { |
| 355 | .ident = "Acer Aspire 1360", | ||
| 356 | .matches = { | 357 | .matches = { |
| 357 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 358 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 358 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), | 359 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 1360"), |
| 359 | }, | 360 | }, |
| 360 | }, | 361 | }, |
| 361 | { | 362 | { |
| 362 | .ident = "Gericom Bellagio", | 363 | /* Gericom Bellagio */ |
| 363 | .matches = { | 364 | .matches = { |
| 364 | DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), | 365 | DMI_MATCH(DMI_SYS_VENDOR, "Gericom"), |
| 365 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), | 366 | DMI_MATCH(DMI_PRODUCT_NAME, "N34AS6"), |
| 366 | }, | 367 | }, |
| 367 | }, | 368 | }, |
| 368 | { | 369 | { |
| 369 | .ident = "IBM 2656", | 370 | /* IBM 2656 */ |
| 370 | .matches = { | 371 | .matches = { |
| 371 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), | 372 | DMI_MATCH(DMI_SYS_VENDOR, "IBM"), |
| 372 | DMI_MATCH(DMI_PRODUCT_NAME, "2656"), | 373 | DMI_MATCH(DMI_PRODUCT_NAME, "2656"), |
| 373 | }, | 374 | }, |
| 374 | }, | 375 | }, |
| 375 | { | 376 | { |
| 376 | .ident = "Dell XPS M1530", | 377 | /* Dell XPS M1530 */ |
| 377 | .matches = { | 378 | .matches = { |
| 378 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 379 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 379 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), | 380 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS M1530"), |
| 380 | }, | 381 | }, |
| 381 | }, | 382 | }, |
| 382 | { | 383 | { |
| 383 | .ident = "Compal HEL80I", | 384 | /* Compal HEL80I */ |
| 384 | .matches = { | 385 | .matches = { |
| 385 | DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), | 386 | DMI_MATCH(DMI_SYS_VENDOR, "COMPAL"), |
| 386 | DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), | 387 | DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), |
| 387 | }, | 388 | }, |
| 388 | }, | 389 | }, |
| 389 | { | 390 | { |
| 390 | .ident = "Dell Vostro 1510", | 391 | /* Dell Vostro 1510 */ |
| 391 | .matches = { | 392 | .matches = { |
| 392 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 393 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 393 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), | 394 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro1510"), |
| 394 | }, | 395 | }, |
| 395 | }, | 396 | }, |
| 396 | { | 397 | { |
| 397 | .ident = "Acer Aspire 5536", | 398 | /* Acer Aspire 5536 */ |
| 398 | .matches = { | 399 | .matches = { |
| 399 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 400 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 400 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), | 401 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5536"), |
| @@ -404,65 +405,72 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
| 404 | { } | 405 | { } |
| 405 | }; | 406 | }; |
| 406 | 407 | ||
| 407 | static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | 408 | static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { |
| 408 | { | 409 | { |
| 409 | .ident = "MSI Wind U-100", | 410 | /* MSI Wind U-100 */ |
| 410 | .matches = { | 411 | .matches = { |
| 411 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | 412 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), |
| 412 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | 413 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), |
| 413 | }, | 414 | }, |
| 414 | }, | 415 | }, |
| 415 | { | 416 | { |
| 416 | .ident = "LG Electronics X110", | 417 | /* LG Electronics X110 */ |
| 417 | .matches = { | 418 | .matches = { |
| 418 | DMI_MATCH(DMI_BOARD_NAME, "X110"), | 419 | DMI_MATCH(DMI_BOARD_NAME, "X110"), |
| 419 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), | 420 | DMI_MATCH(DMI_BOARD_VENDOR, "LG Electronics Inc."), |
| 420 | }, | 421 | }, |
| 421 | }, | 422 | }, |
| 422 | { | 423 | { |
| 423 | .ident = "Acer Aspire One 150", | 424 | /* Acer Aspire One 150 */ |
| 424 | .matches = { | 425 | .matches = { |
| 425 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 426 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 426 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), | 427 | DMI_MATCH(DMI_PRODUCT_NAME, "AOA150"), |
| 427 | }, | 428 | }, |
| 428 | }, | 429 | }, |
| 429 | { | 430 | { |
| 430 | .ident = "Advent 4211", | 431 | /* Advent 4211 */ |
| 431 | .matches = { | 432 | .matches = { |
| 432 | DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), | 433 | DMI_MATCH(DMI_SYS_VENDOR, "DIXONSXP"), |
| 433 | DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), | 434 | DMI_MATCH(DMI_PRODUCT_NAME, "Advent 4211"), |
| 434 | }, | 435 | }, |
| 435 | }, | 436 | }, |
| 436 | { | 437 | { |
| 437 | .ident = "Medion Akoya Mini E1210", | 438 | /* Medion Akoya Mini E1210 */ |
| 438 | .matches = { | 439 | .matches = { |
| 439 | DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), | 440 | DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), |
| 440 | DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), | 441 | DMI_MATCH(DMI_PRODUCT_NAME, "E1210"), |
| 441 | }, | 442 | }, |
| 442 | }, | 443 | }, |
| 443 | { | 444 | { |
| 444 | .ident = "Mivvy M310", | 445 | /* Medion Akoya E1222 */ |
| 446 | .matches = { | ||
| 447 | DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), | ||
| 448 | DMI_MATCH(DMI_PRODUCT_NAME, "E122X"), | ||
| 449 | }, | ||
| 450 | }, | ||
| 451 | { | ||
| 452 | /* Mivvy M310 */ | ||
| 445 | .matches = { | 453 | .matches = { |
| 446 | DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), | 454 | DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), |
| 447 | DMI_MATCH(DMI_PRODUCT_NAME, "N10"), | 455 | DMI_MATCH(DMI_PRODUCT_NAME, "N10"), |
| 448 | }, | 456 | }, |
| 449 | }, | 457 | }, |
| 450 | { | 458 | { |
| 451 | .ident = "Dell Vostro 1320", | 459 | /* Dell Vostro 1320 */ |
| 452 | .matches = { | 460 | .matches = { |
| 453 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 461 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 454 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), | 462 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1320"), |
| 455 | }, | 463 | }, |
| 456 | }, | 464 | }, |
| 457 | { | 465 | { |
| 458 | .ident = "Dell Vostro 1520", | 466 | /* Dell Vostro 1520 */ |
| 459 | .matches = { | 467 | .matches = { |
| 460 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 468 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 461 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), | 469 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1520"), |
| 462 | }, | 470 | }, |
| 463 | }, | 471 | }, |
| 464 | { | 472 | { |
| 465 | .ident = "Dell Vostro 1720", | 473 | /* Dell Vostro 1720 */ |
| 466 | .matches = { | 474 | .matches = { |
| 467 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | 475 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), |
| 468 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), | 476 | DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 1720"), |
| @@ -472,16 +480,16 @@ static struct dmi_system_id __initdata i8042_dmi_reset_table[] = { | |||
| 472 | }; | 480 | }; |
| 473 | 481 | ||
| 474 | #ifdef CONFIG_PNP | 482 | #ifdef CONFIG_PNP |
| 475 | static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | 483 | static const struct dmi_system_id __initconst i8042_dmi_nopnp_table[] = { |
| 476 | { | 484 | { |
| 477 | .ident = "Intel MBO Desktop D845PESV", | 485 | /* Intel MBO Desktop D845PESV */ |
| 478 | .matches = { | 486 | .matches = { |
| 479 | DMI_MATCH(DMI_BOARD_NAME, "D845PESV"), | 487 | DMI_MATCH(DMI_BOARD_NAME, "D845PESV"), |
| 480 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | 488 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), |
| 481 | }, | 489 | }, |
| 482 | }, | 490 | }, |
| 483 | { | 491 | { |
| 484 | .ident = "MSI Wind U-100", | 492 | /* MSI Wind U-100 */ |
| 485 | .matches = { | 493 | .matches = { |
| 486 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), | 494 | DMI_MATCH(DMI_BOARD_NAME, "U-100"), |
| 487 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), | 495 | DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"), |
| @@ -490,27 +498,23 @@ static struct dmi_system_id __initdata i8042_dmi_nopnp_table[] = { | |||
| 490 | { } | 498 | { } |
| 491 | }; | 499 | }; |
| 492 | 500 | ||
| 493 | static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { | 501 | static const struct dmi_system_id __initconst i8042_dmi_laptop_table[] = { |
| 494 | { | 502 | { |
| 495 | .ident = "Portable", | ||
| 496 | .matches = { | 503 | .matches = { |
| 497 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ | 504 | DMI_MATCH(DMI_CHASSIS_TYPE, "8"), /* Portable */ |
| 498 | }, | 505 | }, |
| 499 | }, | 506 | }, |
| 500 | { | 507 | { |
| 501 | .ident = "Laptop", | ||
| 502 | .matches = { | 508 | .matches = { |
| 503 | DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ | 509 | DMI_MATCH(DMI_CHASSIS_TYPE, "9"), /* Laptop */ |
| 504 | }, | 510 | }, |
| 505 | }, | 511 | }, |
| 506 | { | 512 | { |
| 507 | .ident = "Notebook", | ||
| 508 | .matches = { | 513 | .matches = { |
| 509 | DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ | 514 | DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ |
| 510 | }, | 515 | }, |
| 511 | }, | 516 | }, |
| 512 | { | 517 | { |
| 513 | .ident = "Sub-Notebook", | ||
| 514 | .matches = { | 518 | .matches = { |
| 515 | DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ | 519 | DMI_MATCH(DMI_CHASSIS_TYPE, "14"), /* Sub-Notebook */ |
| 516 | }, | 520 | }, |
| @@ -525,58 +529,65 @@ static struct dmi_system_id __initdata i8042_dmi_laptop_table[] = { | |||
| 525 | * Originally, this was just confined to older laptops, but a few Acer laptops | 529 | * Originally, this was just confined to older laptops, but a few Acer laptops |
| 526 | * have turned up in 2007 that also need this again. | 530 | * have turned up in 2007 that also need this again. |
| 527 | */ | 531 | */ |
| 528 | static struct dmi_system_id __initdata i8042_dmi_dritek_table[] = { | 532 | static const struct dmi_system_id __initconst i8042_dmi_dritek_table[] = { |
| 533 | { | ||
| 534 | /* Acer Aspire 5610 */ | ||
| 535 | .matches = { | ||
| 536 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
| 537 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), | ||
| 538 | }, | ||
| 539 | }, | ||
| 529 | { | 540 | { |
| 530 | .ident = "Acer Aspire 5630", | 541 | /* Acer Aspire 5630 */ |
| 531 | .matches = { | 542 | .matches = { |
| 532 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 543 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 533 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), | 544 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), |
| 534 | }, | 545 | }, |
| 535 | }, | 546 | }, |
| 536 | { | 547 | { |
| 537 | .ident = "Acer Aspire 5650", | 548 | /* Acer Aspire 5650 */ |
| 538 | .matches = { | 549 | .matches = { |
| 539 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 550 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 540 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), | 551 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), |
| 541 | }, | 552 | }, |
| 542 | }, | 553 | }, |
| 543 | { | 554 | { |
| 544 | .ident = "Acer Aspire 5680", | 555 | /* Acer Aspire 5680 */ |
| 545 | .matches = { | 556 | .matches = { |
| 546 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 557 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 547 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), | 558 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), |
| 548 | }, | 559 | }, |
| 549 | }, | 560 | }, |
| 550 | { | 561 | { |
| 551 | .ident = "Acer Aspire 5720", | 562 | /* Acer Aspire 5720 */ |
| 552 | .matches = { | 563 | .matches = { |
| 553 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 564 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 554 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), | 565 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5720"), |
| 555 | }, | 566 | }, |
| 556 | }, | 567 | }, |
| 557 | { | 568 | { |
| 558 | .ident = "Acer Aspire 9110", | 569 | /* Acer Aspire 9110 */ |
| 559 | .matches = { | 570 | .matches = { |
| 560 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 571 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 561 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), | 572 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), |
| 562 | }, | 573 | }, |
| 563 | }, | 574 | }, |
| 564 | { | 575 | { |
| 565 | .ident = "Acer TravelMate 660", | 576 | /* Acer TravelMate 660 */ |
| 566 | .matches = { | 577 | .matches = { |
| 567 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 578 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 568 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"), | 579 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 660"), |
| 569 | }, | 580 | }, |
| 570 | }, | 581 | }, |
| 571 | { | 582 | { |
| 572 | .ident = "Acer TravelMate 2490", | 583 | /* Acer TravelMate 2490 */ |
| 573 | .matches = { | 584 | .matches = { |
| 574 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 585 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 575 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), | 586 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), |
| 576 | }, | 587 | }, |
| 577 | }, | 588 | }, |
| 578 | { | 589 | { |
| 579 | .ident = "Acer TravelMate 4280", | 590 | /* Acer TravelMate 4280 */ |
| 580 | .matches = { | 591 | .matches = { |
| 581 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | 592 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), |
| 582 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), | 593 | DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), |
| @@ -620,6 +631,9 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * | |||
| 620 | strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); | 631 | strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); |
| 621 | } | 632 | } |
| 622 | 633 | ||
| 634 | /* Keyboard ports are always supposed to be wakeup-enabled */ | ||
| 635 | device_set_wakeup_enable(&dev->dev, true); | ||
| 636 | |||
| 623 | i8042_pnp_kbd_devices++; | 637 | i8042_pnp_kbd_devices++; |
| 624 | return 0; | 638 | return 0; |
| 625 | } | 639 | } |
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index 1df02d25aca5..577688b5b951 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/rcupdate.h> | 21 | #include <linux/rcupdate.h> |
| 22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
| 23 | #include <linux/i8042.h> | 23 | #include <linux/i8042.h> |
| 24 | #include <linux/slab.h> | ||
| 24 | 25 | ||
| 25 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| 26 | 27 | ||
| @@ -126,6 +127,8 @@ static unsigned char i8042_suppress_kbd_ack; | |||
| 126 | static struct platform_device *i8042_platform_device; | 127 | static struct platform_device *i8042_platform_device; |
| 127 | 128 | ||
| 128 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); | 129 | static irqreturn_t i8042_interrupt(int irq, void *dev_id); |
| 130 | static bool (*i8042_platform_filter)(unsigned char data, unsigned char str, | ||
| 131 | struct serio *serio); | ||
| 129 | 132 | ||
| 130 | void i8042_lock_chip(void) | 133 | void i8042_lock_chip(void) |
| 131 | { | 134 | { |
| @@ -139,6 +142,48 @@ void i8042_unlock_chip(void) | |||
| 139 | } | 142 | } |
| 140 | EXPORT_SYMBOL(i8042_unlock_chip); | 143 | EXPORT_SYMBOL(i8042_unlock_chip); |
| 141 | 144 | ||
| 145 | int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 146 | struct serio *serio)) | ||
| 147 | { | ||
| 148 | unsigned long flags; | ||
| 149 | int ret = 0; | ||
| 150 | |||
| 151 | spin_lock_irqsave(&i8042_lock, flags); | ||
| 152 | |||
| 153 | if (i8042_platform_filter) { | ||
| 154 | ret = -EBUSY; | ||
| 155 | goto out; | ||
| 156 | } | ||
| 157 | |||
| 158 | i8042_platform_filter = filter; | ||
| 159 | |||
| 160 | out: | ||
| 161 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | EXPORT_SYMBOL(i8042_install_filter); | ||
| 165 | |||
| 166 | int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str, | ||
| 167 | struct serio *port)) | ||
| 168 | { | ||
| 169 | unsigned long flags; | ||
| 170 | int ret = 0; | ||
| 171 | |||
| 172 | spin_lock_irqsave(&i8042_lock, flags); | ||
| 173 | |||
| 174 | if (i8042_platform_filter != filter) { | ||
| 175 | ret = -EINVAL; | ||
| 176 | goto out; | ||
| 177 | } | ||
| 178 | |||
| 179 | i8042_platform_filter = NULL; | ||
| 180 | |||
| 181 | out: | ||
| 182 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 183 | return ret; | ||
| 184 | } | ||
| 185 | EXPORT_SYMBOL(i8042_remove_filter); | ||
| 186 | |||
| 142 | /* | 187 | /* |
| 143 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to | 188 | * The i8042_wait_read() and i8042_wait_write functions wait for the i8042 to |
| 144 | * be ready for reading values from it / writing values to it. | 189 | * be ready for reading values from it / writing values to it. |
| @@ -369,6 +414,31 @@ static void i8042_stop(struct serio *serio) | |||
| 369 | } | 414 | } |
| 370 | 415 | ||
| 371 | /* | 416 | /* |
| 417 | * i8042_filter() filters out unwanted bytes from the input data stream. | ||
| 418 | * It is called from i8042_interrupt and thus is running with interrupts | ||
| 419 | * off and i8042_lock held. | ||
| 420 | */ | ||
| 421 | static bool i8042_filter(unsigned char data, unsigned char str, | ||
| 422 | struct serio *serio) | ||
| 423 | { | ||
| 424 | if (unlikely(i8042_suppress_kbd_ack)) { | ||
| 425 | if ((~str & I8042_STR_AUXDATA) && | ||
| 426 | (data == 0xfa || data == 0xfe)) { | ||
| 427 | i8042_suppress_kbd_ack--; | ||
| 428 | dbg("Extra keyboard ACK - filtered out\n"); | ||
| 429 | return true; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | if (i8042_platform_filter && i8042_platform_filter(data, str, serio)) { | ||
| 434 | dbg("Filtered out by platform filter\n"); | ||
| 435 | return true; | ||
| 436 | } | ||
| 437 | |||
| 438 | return false; | ||
| 439 | } | ||
| 440 | |||
| 441 | /* | ||
| 372 | * i8042_interrupt() is the most important function in this driver - | 442 | * i8042_interrupt() is the most important function in this driver - |
| 373 | * it handles the interrupts from the i8042, and sends incoming bytes | 443 | * it handles the interrupts from the i8042, and sends incoming bytes |
| 374 | * to the upper layers. | 444 | * to the upper layers. |
| @@ -377,13 +447,16 @@ static void i8042_stop(struct serio *serio) | |||
| 377 | static irqreturn_t i8042_interrupt(int irq, void *dev_id) | 447 | static irqreturn_t i8042_interrupt(int irq, void *dev_id) |
| 378 | { | 448 | { |
| 379 | struct i8042_port *port; | 449 | struct i8042_port *port; |
| 450 | struct serio *serio; | ||
| 380 | unsigned long flags; | 451 | unsigned long flags; |
| 381 | unsigned char str, data; | 452 | unsigned char str, data; |
| 382 | unsigned int dfl; | 453 | unsigned int dfl; |
| 383 | unsigned int port_no; | 454 | unsigned int port_no; |
| 455 | bool filtered; | ||
| 384 | int ret = 1; | 456 | int ret = 1; |
| 385 | 457 | ||
| 386 | spin_lock_irqsave(&i8042_lock, flags); | 458 | spin_lock_irqsave(&i8042_lock, flags); |
| 459 | |||
| 387 | str = i8042_read_status(); | 460 | str = i8042_read_status(); |
| 388 | if (unlikely(~str & I8042_STR_OBF)) { | 461 | if (unlikely(~str & I8042_STR_OBF)) { |
| 389 | spin_unlock_irqrestore(&i8042_lock, flags); | 462 | spin_unlock_irqrestore(&i8042_lock, flags); |
| @@ -391,8 +464,8 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
| 391 | ret = 0; | 464 | ret = 0; |
| 392 | goto out; | 465 | goto out; |
| 393 | } | 466 | } |
| 467 | |||
| 394 | data = i8042_read_data(); | 468 | data = i8042_read_data(); |
| 395 | spin_unlock_irqrestore(&i8042_lock, flags); | ||
| 396 | 469 | ||
| 397 | if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { | 470 | if (i8042_mux_present && (str & I8042_STR_AUXDATA)) { |
| 398 | static unsigned long last_transmit; | 471 | static unsigned long last_transmit; |
| @@ -441,21 +514,19 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id) | |||
| 441 | } | 514 | } |
| 442 | 515 | ||
| 443 | port = &i8042_ports[port_no]; | 516 | port = &i8042_ports[port_no]; |
| 517 | serio = port->exists ? port->serio : NULL; | ||
| 444 | 518 | ||
| 445 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", | 519 | dbg("%02x <- i8042 (interrupt, %d, %d%s%s)", |
| 446 | data, port_no, irq, | 520 | data, port_no, irq, |
| 447 | dfl & SERIO_PARITY ? ", bad parity" : "", | 521 | dfl & SERIO_PARITY ? ", bad parity" : "", |
| 448 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); | 522 | dfl & SERIO_TIMEOUT ? ", timeout" : ""); |
| 449 | 523 | ||
| 450 | if (unlikely(i8042_suppress_kbd_ack)) | 524 | filtered = i8042_filter(data, str, serio); |
| 451 | if (port_no == I8042_KBD_PORT_NO && | 525 | |
| 452 | (data == 0xfa || data == 0xfe)) { | 526 | spin_unlock_irqrestore(&i8042_lock, flags); |
| 453 | i8042_suppress_kbd_ack--; | ||
| 454 | goto out; | ||
| 455 | } | ||
| 456 | 527 | ||
| 457 | if (likely(port->exists)) | 528 | if (likely(port->exists && !filtered)) |
| 458 | serio_interrupt(port->serio, data, dfl); | 529 | serio_interrupt(serio, data, dfl); |
| 459 | 530 | ||
| 460 | out: | 531 | out: |
| 461 | return IRQ_RETVAL(ret); | 532 | return IRQ_RETVAL(ret); |
| @@ -1091,9 +1162,17 @@ static int i8042_pm_restore(struct device *dev) | |||
| 1091 | return 0; | 1162 | return 0; |
| 1092 | } | 1163 | } |
| 1093 | 1164 | ||
| 1165 | static int i8042_pm_thaw(struct device *dev) | ||
| 1166 | { | ||
| 1167 | i8042_interrupt(0, NULL); | ||
| 1168 | |||
| 1169 | return 0; | ||
| 1170 | } | ||
| 1171 | |||
| 1094 | static const struct dev_pm_ops i8042_pm_ops = { | 1172 | static const struct dev_pm_ops i8042_pm_ops = { |
| 1095 | .suspend = i8042_pm_reset, | 1173 | .suspend = i8042_pm_reset, |
| 1096 | .resume = i8042_pm_restore, | 1174 | .resume = i8042_pm_restore, |
| 1175 | .thaw = i8042_pm_thaw, | ||
| 1097 | .poweroff = i8042_pm_reset, | 1176 | .poweroff = i8042_pm_reset, |
| 1098 | .restore = i8042_pm_restore, | 1177 | .restore = i8042_pm_restore, |
| 1099 | }; | 1178 | }; |
| @@ -1308,6 +1387,8 @@ static int __init i8042_probe(struct platform_device *dev) | |||
| 1308 | { | 1387 | { |
| 1309 | int error; | 1388 | int error; |
| 1310 | 1389 | ||
| 1390 | i8042_platform_device = dev; | ||
| 1391 | |||
| 1311 | error = i8042_controller_selftest(); | 1392 | error = i8042_controller_selftest(); |
| 1312 | if (error) | 1393 | if (error) |
| 1313 | return error; | 1394 | return error; |
| @@ -1343,6 +1424,7 @@ static int __init i8042_probe(struct platform_device *dev) | |||
| 1343 | i8042_free_aux_ports(); /* in case KBD failed but AUX not */ | 1424 | i8042_free_aux_ports(); /* in case KBD failed but AUX not */ |
| 1344 | i8042_free_irqs(); | 1425 | i8042_free_irqs(); |
| 1345 | i8042_controller_reset(); | 1426 | i8042_controller_reset(); |
| 1427 | i8042_platform_device = NULL; | ||
| 1346 | 1428 | ||
| 1347 | return error; | 1429 | return error; |
| 1348 | } | 1430 | } |
| @@ -1352,6 +1434,7 @@ static int __devexit i8042_remove(struct platform_device *dev) | |||
| 1352 | i8042_unregister_ports(); | 1434 | i8042_unregister_ports(); |
| 1353 | i8042_free_irqs(); | 1435 | i8042_free_irqs(); |
| 1354 | i8042_controller_reset(); | 1436 | i8042_controller_reset(); |
| 1437 | i8042_platform_device = NULL; | ||
| 1355 | 1438 | ||
| 1356 | return 0; | 1439 | return 0; |
| 1357 | } | 1440 | } |
| @@ -1370,6 +1453,7 @@ static struct platform_driver i8042_driver = { | |||
| 1370 | 1453 | ||
| 1371 | static int __init i8042_init(void) | 1454 | static int __init i8042_init(void) |
| 1372 | { | 1455 | { |
| 1456 | struct platform_device *pdev; | ||
| 1373 | int err; | 1457 | int err; |
| 1374 | 1458 | ||
| 1375 | dbg_init(); | 1459 | dbg_init(); |
| @@ -1382,31 +1466,18 @@ static int __init i8042_init(void) | |||
| 1382 | if (err) | 1466 | if (err) |
| 1383 | goto err_platform_exit; | 1467 | goto err_platform_exit; |
| 1384 | 1468 | ||
| 1385 | i8042_platform_device = platform_device_alloc("i8042", -1); | 1469 | pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); |
| 1386 | if (!i8042_platform_device) { | 1470 | if (IS_ERR(pdev)) { |
| 1387 | err = -ENOMEM; | 1471 | err = PTR_ERR(pdev); |
| 1388 | goto err_platform_exit; | 1472 | goto err_platform_exit; |
| 1389 | } | 1473 | } |
| 1390 | 1474 | ||
| 1391 | err = platform_device_add(i8042_platform_device); | ||
| 1392 | if (err) | ||
| 1393 | goto err_free_device; | ||
| 1394 | |||
| 1395 | err = platform_driver_probe(&i8042_driver, i8042_probe); | ||
| 1396 | if (err) | ||
| 1397 | goto err_del_device; | ||
| 1398 | |||
| 1399 | panic_blink = i8042_panic_blink; | 1475 | panic_blink = i8042_panic_blink; |
| 1400 | 1476 | ||
| 1401 | return 0; | 1477 | return 0; |
| 1402 | 1478 | ||
| 1403 | err_del_device: | ||
| 1404 | platform_device_del(i8042_platform_device); | ||
| 1405 | err_free_device: | ||
| 1406 | platform_device_put(i8042_platform_device); | ||
| 1407 | err_platform_exit: | 1479 | err_platform_exit: |
| 1408 | i8042_platform_exit(); | 1480 | i8042_platform_exit(); |
| 1409 | |||
| 1410 | return err; | 1481 | return err; |
| 1411 | } | 1482 | } |
| 1412 | 1483 | ||
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index f3876acc3e83..980af94ba9c8 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
| 16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 19 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 20 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
diff --git a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c index b089977e0ef9..26b45936f9fd 100644 --- a/drivers/input/serio/parkbd.c +++ b/drivers/input/serio/parkbd.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | #include <linux/module.h> | 47 | #include <linux/module.h> |
| 48 | #include <linux/parport.h> | 48 | #include <linux/parport.h> |
| 49 | #include <linux/slab.h> | ||
| 49 | #include <linux/init.h> | 50 | #include <linux/init.h> |
| 50 | #include <linux/serio.h> | 51 | #include <linux/serio.h> |
| 51 | 52 | ||
diff --git a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c index 1dacbe0d9348..43494742541c 100644 --- a/drivers/input/serio/pcips2.c +++ b/drivers/input/serio/pcips2.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
| 16 | #include <linux/input.h> | 16 | #include <linux/input.h> |
| 17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
| 18 | #include <linux/slab.h> | ||
| 18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 19 | #include <linux/serio.h> | 20 | #include <linux/serio.h> |
| 20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
| @@ -186,7 +187,7 @@ static void __devexit pcips2_remove(struct pci_dev *dev) | |||
| 186 | pci_disable_device(dev); | 187 | pci_disable_device(dev); |
| 187 | } | 188 | } |
| 188 | 189 | ||
| 189 | static struct pci_device_id pcips2_ids[] = { | 190 | static const struct pci_device_id pcips2_ids[] = { |
| 190 | { | 191 | { |
| 191 | .vendor = 0x14f2, /* MOBILITY */ | 192 | .vendor = 0x14f2, /* MOBILITY */ |
| 192 | .device = 0x0123, /* Keyboard */ | 193 | .device = 0x0123, /* Keyboard */ |
diff --git a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c index e36a0901646c..5eb84b3b67fb 100644 --- a/drivers/input/serio/q40kbd.c +++ b/drivers/input/serio/q40kbd.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/err.h> | 36 | #include <linux/err.h> |
| 37 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
| 38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
| 39 | #include <linux/slab.h> | ||
| 39 | 40 | ||
| 40 | #include <asm/io.h> | 41 | #include <asm/io.h> |
| 41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index ed045c99f84b..9da6fbcaaa7e 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
| 35 | #include <linux/platform_device.h> | 35 | #include <linux/platform_device.h> |
| 36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
| 37 | #include <linux/slab.h> | ||
| 37 | 38 | ||
| 38 | #include <asm/irq.h> | 39 | #include <asm/irq.h> |
| 39 | #include <mach/hardware.h> | 40 | #include <mach/hardware.h> |
diff --git a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c index f412c69478a8..d55874e5d1c2 100644 --- a/drivers/input/serio/sa1111ps2.c +++ b/drivers/input/serio/sa1111ps2.c | |||
| @@ -180,8 +180,8 @@ static void __devinit ps2_clear_input(struct ps2if *ps2if) | |||
| 180 | } | 180 | } |
| 181 | } | 181 | } |
| 182 | 182 | ||
| 183 | static inline unsigned int | 183 | static unsigned int __devinit ps2_test_one(struct ps2if *ps2if, |
| 184 | ps2_test_one(struct ps2if *ps2if, unsigned int mask) | 184 | unsigned int mask) |
| 185 | { | 185 | { |
| 186 | unsigned int val; | 186 | unsigned int val; |
| 187 | 187 | ||
| @@ -197,7 +197,7 @@ ps2_test_one(struct ps2if *ps2if, unsigned int mask) | |||
| 197 | * Test the keyboard interface. We basically check to make sure that | 197 | * Test the keyboard interface. We basically check to make sure that |
| 198 | * we can drive each line to the keyboard independently of each other. | 198 | * we can drive each line to the keyboard independently of each other. |
| 199 | */ | 199 | */ |
| 200 | static int __init ps2_test(struct ps2if *ps2if) | 200 | static int __devinit ps2_test(struct ps2if *ps2if) |
| 201 | { | 201 | { |
| 202 | unsigned int stat; | 202 | unsigned int stat; |
| 203 | int ret = 0; | 203 | int ret = 0; |
| @@ -312,7 +312,7 @@ static int __devinit ps2_probe(struct sa1111_dev *dev) | |||
| 312 | /* | 312 | /* |
| 313 | * Remove one device from this driver. | 313 | * Remove one device from this driver. |
| 314 | */ | 314 | */ |
| 315 | static int ps2_remove(struct sa1111_dev *dev) | 315 | static int __devexit ps2_remove(struct sa1111_dev *dev) |
| 316 | { | 316 | { |
| 317 | struct ps2if *ps2if = sa1111_get_drvdata(dev); | 317 | struct ps2if *ps2if = sa1111_get_drvdata(dev); |
| 318 | 318 | ||
| @@ -335,7 +335,7 @@ static struct sa1111_driver ps2_driver = { | |||
| 335 | }, | 335 | }, |
| 336 | .devid = SA1111_DEVID_PS2, | 336 | .devid = SA1111_DEVID_PS2, |
| 337 | .probe = ps2_probe, | 337 | .probe = ps2_probe, |
| 338 | .remove = ps2_remove, | 338 | .remove = __devexit_p(ps2_remove), |
| 339 | }; | 339 | }; |
| 340 | 340 | ||
| 341 | static int __init ps2_init(void) | 341 | static int __init ps2_init(void) |
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 0236f0d5fd91..c3b626e9eae7 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| 27 | */ | 27 | */ |
| 28 | 28 | ||
| 29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 30 | |||
| 29 | #include <linux/stddef.h> | 31 | #include <linux/stddef.h> |
| 30 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 31 | #include <linux/serio.h> | 33 | #include <linux/serio.h> |
| @@ -119,11 +121,10 @@ static int serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
| 119 | 121 | ||
| 120 | error = device_bind_driver(&serio->dev); | 122 | error = device_bind_driver(&serio->dev); |
| 121 | if (error) { | 123 | if (error) { |
| 122 | printk(KERN_WARNING | 124 | dev_warn(&serio->dev, |
| 123 | "serio: device_bind_driver() failed " | 125 | "device_bind_driver() failed for %s (%s) and %s, error: %d\n", |
| 124 | "for %s (%s) and %s, error: %d\n", | 126 | serio->phys, serio->name, |
| 125 | serio->phys, serio->name, | 127 | drv->description, error); |
| 126 | drv->description, error); | ||
| 127 | serio_disconnect_driver(serio); | 128 | serio_disconnect_driver(serio); |
| 128 | serio->dev.driver = NULL; | 129 | serio->dev.driver = NULL; |
| 129 | return error; | 130 | return error; |
| @@ -138,9 +139,9 @@ static void serio_find_driver(struct serio *serio) | |||
| 138 | 139 | ||
| 139 | error = device_attach(&serio->dev); | 140 | error = device_attach(&serio->dev); |
| 140 | if (error < 0) | 141 | if (error < 0) |
| 141 | printk(KERN_WARNING | 142 | dev_warn(&serio->dev, |
| 142 | "serio: device_attach() failed for %s (%s), error: %d\n", | 143 | "device_attach() failed for %s (%s), error: %d\n", |
| 143 | serio->phys, serio->name, error); | 144 | serio->phys, serio->name, error); |
| 144 | } | 145 | } |
| 145 | 146 | ||
| 146 | 147 | ||
| @@ -194,17 +195,14 @@ static int serio_queue_event(void *object, struct module *owner, | |||
| 194 | 195 | ||
| 195 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); | 196 | event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC); |
| 196 | if (!event) { | 197 | if (!event) { |
| 197 | printk(KERN_ERR | 198 | pr_err("Not enough memory to queue event %d\n", event_type); |
| 198 | "serio: Not enough memory to queue event %d\n", | ||
| 199 | event_type); | ||
| 200 | retval = -ENOMEM; | 199 | retval = -ENOMEM; |
| 201 | goto out; | 200 | goto out; |
| 202 | } | 201 | } |
| 203 | 202 | ||
| 204 | if (!try_module_get(owner)) { | 203 | if (!try_module_get(owner)) { |
| 205 | printk(KERN_WARNING | 204 | pr_warning("Can't get module reference, dropping event %d\n", |
| 206 | "serio: Can't get module reference, dropping event %d\n", | 205 | event_type); |
| 207 | event_type); | ||
| 208 | kfree(event); | 206 | kfree(event); |
| 209 | retval = -EINVAL; | 207 | retval = -EINVAL; |
| 210 | goto out; | 208 | goto out; |
| @@ -230,14 +228,12 @@ static void serio_free_event(struct serio_event *event) | |||
| 230 | 228 | ||
| 231 | static void serio_remove_duplicate_events(struct serio_event *event) | 229 | static void serio_remove_duplicate_events(struct serio_event *event) |
| 232 | { | 230 | { |
| 233 | struct list_head *node, *next; | 231 | struct serio_event *e, *next; |
| 234 | struct serio_event *e; | ||
| 235 | unsigned long flags; | 232 | unsigned long flags; |
| 236 | 233 | ||
| 237 | spin_lock_irqsave(&serio_event_lock, flags); | 234 | spin_lock_irqsave(&serio_event_lock, flags); |
| 238 | 235 | ||
| 239 | list_for_each_safe(node, next, &serio_event_list) { | 236 | list_for_each_entry_safe(e, next, &serio_event_list, node) { |
| 240 | e = list_entry(node, struct serio_event, node); | ||
| 241 | if (event->object == e->object) { | 237 | if (event->object == e->object) { |
| 242 | /* | 238 | /* |
| 243 | * If this event is of different type we should not | 239 | * If this event is of different type we should not |
| @@ -247,7 +243,7 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
| 247 | if (event->type != e->type) | 243 | if (event->type != e->type) |
| 248 | break; | 244 | break; |
| 249 | 245 | ||
| 250 | list_del_init(node); | 246 | list_del_init(&e->node); |
| 251 | serio_free_event(e); | 247 | serio_free_event(e); |
| 252 | } | 248 | } |
| 253 | } | 249 | } |
| @@ -258,23 +254,18 @@ static void serio_remove_duplicate_events(struct serio_event *event) | |||
| 258 | 254 | ||
| 259 | static struct serio_event *serio_get_event(void) | 255 | static struct serio_event *serio_get_event(void) |
| 260 | { | 256 | { |
| 261 | struct serio_event *event; | 257 | struct serio_event *event = NULL; |
| 262 | struct list_head *node; | ||
| 263 | unsigned long flags; | 258 | unsigned long flags; |
| 264 | 259 | ||
| 265 | spin_lock_irqsave(&serio_event_lock, flags); | 260 | spin_lock_irqsave(&serio_event_lock, flags); |
| 266 | 261 | ||
| 267 | if (list_empty(&serio_event_list)) { | 262 | if (!list_empty(&serio_event_list)) { |
| 268 | spin_unlock_irqrestore(&serio_event_lock, flags); | 263 | event = list_first_entry(&serio_event_list, |
| 269 | return NULL; | 264 | struct serio_event, node); |
| 265 | list_del_init(&event->node); | ||
| 270 | } | 266 | } |
| 271 | 267 | ||
| 272 | node = serio_event_list.next; | ||
| 273 | event = list_entry(node, struct serio_event, node); | ||
| 274 | list_del_init(node); | ||
| 275 | |||
| 276 | spin_unlock_irqrestore(&serio_event_lock, flags); | 268 | spin_unlock_irqrestore(&serio_event_lock, flags); |
| 277 | |||
| 278 | return event; | 269 | return event; |
| 279 | } | 270 | } |
| 280 | 271 | ||
| @@ -284,38 +275,30 @@ static void serio_handle_event(void) | |||
| 284 | 275 | ||
| 285 | mutex_lock(&serio_mutex); | 276 | mutex_lock(&serio_mutex); |
| 286 | 277 | ||
| 287 | /* | 278 | while ((event = serio_get_event())) { |
| 288 | * Note that we handle only one event here to give swsusp | ||
| 289 | * a chance to freeze kseriod thread. Serio events should | ||
| 290 | * be pretty rare so we are not concerned about taking | ||
| 291 | * performance hit. | ||
| 292 | */ | ||
| 293 | if ((event = serio_get_event())) { | ||
| 294 | 279 | ||
| 295 | switch (event->type) { | 280 | switch (event->type) { |
| 296 | case SERIO_REGISTER_PORT: | ||
| 297 | serio_add_port(event->object); | ||
| 298 | break; | ||
| 299 | 281 | ||
| 300 | case SERIO_RECONNECT_PORT: | 282 | case SERIO_REGISTER_PORT: |
| 301 | serio_reconnect_port(event->object); | 283 | serio_add_port(event->object); |
| 302 | break; | 284 | break; |
| 303 | 285 | ||
| 304 | case SERIO_RESCAN_PORT: | 286 | case SERIO_RECONNECT_PORT: |
| 305 | serio_disconnect_port(event->object); | 287 | serio_reconnect_port(event->object); |
| 306 | serio_find_driver(event->object); | 288 | break; |
| 307 | break; | ||
| 308 | 289 | ||
| 309 | case SERIO_RECONNECT_CHAIN: | 290 | case SERIO_RESCAN_PORT: |
| 310 | serio_reconnect_chain(event->object); | 291 | serio_disconnect_port(event->object); |
| 311 | break; | 292 | serio_find_driver(event->object); |
| 293 | break; | ||
| 312 | 294 | ||
| 313 | case SERIO_ATTACH_DRIVER: | 295 | case SERIO_RECONNECT_CHAIN: |
| 314 | serio_attach_driver(event->object); | 296 | serio_reconnect_chain(event->object); |
| 315 | break; | 297 | break; |
| 316 | 298 | ||
| 317 | default: | 299 | case SERIO_ATTACH_DRIVER: |
| 318 | break; | 300 | serio_attach_driver(event->object); |
| 301 | break; | ||
| 319 | } | 302 | } |
| 320 | 303 | ||
| 321 | serio_remove_duplicate_events(event); | 304 | serio_remove_duplicate_events(event); |
| @@ -331,16 +314,14 @@ static void serio_handle_event(void) | |||
| 331 | */ | 314 | */ |
| 332 | static void serio_remove_pending_events(void *object) | 315 | static void serio_remove_pending_events(void *object) |
| 333 | { | 316 | { |
| 334 | struct list_head *node, *next; | 317 | struct serio_event *event, *next; |
| 335 | struct serio_event *event; | ||
| 336 | unsigned long flags; | 318 | unsigned long flags; |
| 337 | 319 | ||
| 338 | spin_lock_irqsave(&serio_event_lock, flags); | 320 | spin_lock_irqsave(&serio_event_lock, flags); |
| 339 | 321 | ||
| 340 | list_for_each_safe(node, next, &serio_event_list) { | 322 | list_for_each_entry_safe(event, next, &serio_event_list, node) { |
| 341 | event = list_entry(node, struct serio_event, node); | ||
| 342 | if (event->object == object) { | 323 | if (event->object == object) { |
| 343 | list_del_init(node); | 324 | list_del_init(&event->node); |
| 344 | serio_free_event(event); | 325 | serio_free_event(event); |
| 345 | } | 326 | } |
| 346 | } | 327 | } |
| @@ -380,14 +361,12 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
| 380 | 361 | ||
| 381 | static int serio_thread(void *nothing) | 362 | static int serio_thread(void *nothing) |
| 382 | { | 363 | { |
| 383 | set_freezable(); | ||
| 384 | do { | 364 | do { |
| 385 | serio_handle_event(); | 365 | serio_handle_event(); |
| 386 | wait_event_freezable(serio_wait, | 366 | wait_event_interruptible(serio_wait, |
| 387 | kthread_should_stop() || !list_empty(&serio_event_list)); | 367 | kthread_should_stop() || !list_empty(&serio_event_list)); |
| 388 | } while (!kthread_should_stop()); | 368 | } while (!kthread_should_stop()); |
| 389 | 369 | ||
| 390 | printk(KERN_DEBUG "serio: kseriod exiting\n"); | ||
| 391 | return 0; | 370 | return 0; |
| 392 | } | 371 | } |
| 393 | 372 | ||
| @@ -452,6 +431,11 @@ static struct attribute_group serio_id_attr_group = { | |||
| 452 | .attrs = serio_device_id_attrs, | 431 | .attrs = serio_device_id_attrs, |
| 453 | }; | 432 | }; |
| 454 | 433 | ||
| 434 | static const struct attribute_group *serio_device_attr_groups[] = { | ||
| 435 | &serio_id_attr_group, | ||
| 436 | NULL | ||
| 437 | }; | ||
| 438 | |||
| 455 | static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 439 | static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
| 456 | { | 440 | { |
| 457 | struct serio *serio = to_serio_port(dev); | 441 | struct serio *serio = to_serio_port(dev); |
| @@ -539,6 +523,7 @@ static void serio_init_port(struct serio *serio) | |||
| 539 | (long)atomic_inc_return(&serio_no) - 1); | 523 | (long)atomic_inc_return(&serio_no) - 1); |
| 540 | serio->dev.bus = &serio_bus; | 524 | serio->dev.bus = &serio_bus; |
| 541 | serio->dev.release = serio_release_port; | 525 | serio->dev.release = serio_release_port; |
| 526 | serio->dev.groups = serio_device_attr_groups; | ||
| 542 | if (serio->parent) { | 527 | if (serio->parent) { |
| 543 | serio->dev.parent = &serio->parent->dev; | 528 | serio->dev.parent = &serio->parent->dev; |
| 544 | serio->depth = serio->parent->depth + 1; | 529 | serio->depth = serio->parent->depth + 1; |
| @@ -562,21 +547,15 @@ static void serio_add_port(struct serio *serio) | |||
| 562 | } | 547 | } |
| 563 | 548 | ||
| 564 | list_add_tail(&serio->node, &serio_list); | 549 | list_add_tail(&serio->node, &serio_list); |
| 550 | |||
| 565 | if (serio->start) | 551 | if (serio->start) |
| 566 | serio->start(serio); | 552 | serio->start(serio); |
| 553 | |||
| 567 | error = device_add(&serio->dev); | 554 | error = device_add(&serio->dev); |
| 568 | if (error) | 555 | if (error) |
| 569 | printk(KERN_ERR | 556 | dev_err(&serio->dev, |
| 570 | "serio: device_add() failed for %s (%s), error: %d\n", | 557 | "device_add() failed for %s (%s), error: %d\n", |
| 571 | serio->phys, serio->name, error); | 558 | serio->phys, serio->name, error); |
| 572 | else { | ||
| 573 | serio->registered = true; | ||
| 574 | error = sysfs_create_group(&serio->dev.kobj, &serio_id_attr_group); | ||
| 575 | if (error) | ||
| 576 | printk(KERN_ERR | ||
| 577 | "serio: sysfs_create_group() failed for %s (%s), error: %d\n", | ||
| 578 | serio->phys, serio->name, error); | ||
| 579 | } | ||
| 580 | } | 559 | } |
| 581 | 560 | ||
| 582 | /* | 561 | /* |
| @@ -603,11 +582,8 @@ static void serio_destroy_port(struct serio *serio) | |||
| 603 | serio->parent = NULL; | 582 | serio->parent = NULL; |
| 604 | } | 583 | } |
| 605 | 584 | ||
| 606 | if (serio->registered) { | 585 | if (device_is_registered(&serio->dev)) |
| 607 | sysfs_remove_group(&serio->dev.kobj, &serio_id_attr_group); | ||
| 608 | device_del(&serio->dev); | 586 | device_del(&serio->dev); |
| 609 | serio->registered = false; | ||
| 610 | } | ||
| 611 | 587 | ||
| 612 | list_del_init(&serio->node); | 588 | list_del_init(&serio->node); |
| 613 | serio_remove_pending_events(serio); | 589 | serio_remove_pending_events(serio); |
| @@ -805,9 +781,8 @@ static void serio_attach_driver(struct serio_driver *drv) | |||
| 805 | 781 | ||
| 806 | error = driver_attach(&drv->driver); | 782 | error = driver_attach(&drv->driver); |
| 807 | if (error) | 783 | if (error) |
| 808 | printk(KERN_WARNING | 784 | pr_warning("driver_attach() failed for %s with error %d\n", |
| 809 | "serio: driver_attach() failed for %s with error %d\n", | 785 | drv->driver.name, error); |
| 810 | drv->driver.name, error); | ||
| 811 | } | 786 | } |
| 812 | 787 | ||
| 813 | int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) | 788 | int __serio_register_driver(struct serio_driver *drv, struct module *owner, const char *mod_name) |
| @@ -827,8 +802,7 @@ int __serio_register_driver(struct serio_driver *drv, struct module *owner, cons | |||
| 827 | 802 | ||
| 828 | error = driver_register(&drv->driver); | 803 | error = driver_register(&drv->driver); |
| 829 | if (error) { | 804 | if (error) { |
| 830 | printk(KERN_ERR | 805 | pr_err("driver_register() failed for %s, error: %d\n", |
| 831 | "serio: driver_register() failed for %s, error: %d\n", | ||
| 832 | drv->driver.name, error); | 806 | drv->driver.name, error); |
| 833 | return error; | 807 | return error; |
| 834 | } | 808 | } |
| @@ -994,7 +968,7 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
| 994 | 968 | ||
| 995 | if (likely(serio->drv)) { | 969 | if (likely(serio->drv)) { |
| 996 | ret = serio->drv->interrupt(serio, data, dfl); | 970 | ret = serio->drv->interrupt(serio, data, dfl); |
| 997 | } else if (!dfl && serio->registered) { | 971 | } else if (!dfl && device_is_registered(&serio->dev)) { |
| 998 | serio_rescan(serio); | 972 | serio_rescan(serio); |
| 999 | ret = IRQ_HANDLED; | 973 | ret = IRQ_HANDLED; |
| 1000 | } | 974 | } |
| @@ -1025,7 +999,7 @@ static int __init serio_init(void) | |||
| 1025 | 999 | ||
| 1026 | error = bus_register(&serio_bus); | 1000 | error = bus_register(&serio_bus); |
| 1027 | if (error) { | 1001 | if (error) { |
| 1028 | printk(KERN_ERR "serio: failed to register serio bus, error: %d\n", error); | 1002 | pr_err("Failed to register serio bus, error: %d\n", error); |
| 1029 | return error; | 1003 | return error; |
| 1030 | } | 1004 | } |
| 1031 | 1005 | ||
| @@ -1033,7 +1007,7 @@ static int __init serio_init(void) | |||
| 1033 | if (IS_ERR(serio_task)) { | 1007 | if (IS_ERR(serio_task)) { |
| 1034 | bus_unregister(&serio_bus); | 1008 | bus_unregister(&serio_bus); |
| 1035 | error = PTR_ERR(serio_task); | 1009 | error = PTR_ERR(serio_task); |
| 1036 | printk(KERN_ERR "serio: Failed to start kseriod, error: %d\n", error); | 1010 | pr_err("Failed to start kseriod, error: %d\n", error); |
| 1037 | return error; | 1011 | return error; |
| 1038 | } | 1012 | } |
| 1039 | 1013 | ||
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 27fdaaffbb40..998664854440 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c | |||
| @@ -81,12 +81,12 @@ static int serio_raw_open(struct inode *inode, struct file *file) | |||
| 81 | struct serio_raw_list *list; | 81 | struct serio_raw_list *list; |
| 82 | int retval = 0; | 82 | int retval = 0; |
| 83 | 83 | ||
| 84 | lock_kernel(); | ||
| 85 | retval = mutex_lock_interruptible(&serio_raw_mutex); | 84 | retval = mutex_lock_interruptible(&serio_raw_mutex); |
| 86 | if (retval) | 85 | if (retval) |
| 87 | goto out_bkl; | 86 | return retval; |
| 88 | 87 | ||
| 89 | if (!(serio_raw = serio_raw_locate(iminor(inode)))) { | 88 | serio_raw = serio_raw_locate(iminor(inode)); |
| 89 | if (!serio_raw) { | ||
| 90 | retval = -ENODEV; | 90 | retval = -ENODEV; |
| 91 | goto out; | 91 | goto out; |
| 92 | } | 92 | } |
| @@ -96,7 +96,8 @@ static int serio_raw_open(struct inode *inode, struct file *file) | |||
| 96 | goto out; | 96 | goto out; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { | 99 | list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); |
| 100 | if (!list) { | ||
| 100 | retval = -ENOMEM; | 101 | retval = -ENOMEM; |
| 101 | goto out; | 102 | goto out; |
| 102 | } | 103 | } |
| @@ -109,8 +110,6 @@ static int serio_raw_open(struct inode *inode, struct file *file) | |||
| 109 | 110 | ||
| 110 | out: | 111 | out: |
| 111 | mutex_unlock(&serio_raw_mutex); | 112 | mutex_unlock(&serio_raw_mutex); |
| 112 | out_bkl: | ||
| 113 | unlock_kernel(); | ||
| 114 | return retval; | 113 | return retval; |
| 115 | } | 114 | } |
| 116 | 115 | ||
diff --git a/drivers/input/serio/xilinx_ps2.c b/drivers/input/serio/xilinx_ps2.c index ebb22f88c842..f84f8e32e3f1 100644 --- a/drivers/input/serio/xilinx_ps2.c +++ b/drivers/input/serio/xilinx_ps2.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/serio.h> | 19 | #include <linux/serio.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| 23 | #include <linux/list.h> | 24 | #include <linux/list.h> |
| 24 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| @@ -270,7 +271,7 @@ static int __devinit xps2_of_probe(struct of_device *ofdev, | |||
| 270 | drvdata->irq = r_irq.start; | 271 | drvdata->irq = r_irq.start; |
| 271 | 272 | ||
| 272 | phys_addr = r_mem.start; | 273 | phys_addr = r_mem.start; |
| 273 | remap_size = r_mem.end - r_mem.start + 1; | 274 | remap_size = resource_size(&r_mem); |
| 274 | if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { | 275 | if (!request_mem_region(phys_addr, remap_size, DRIVER_NAME)) { |
| 275 | dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", | 276 | dev_err(dev, "Couldn't lock memory region at 0x%08llX\n", |
| 276 | (unsigned long long)phys_addr); | 277 | (unsigned long long)phys_addr); |
| @@ -344,7 +345,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev) | |||
| 344 | if (of_address_to_resource(of_dev->node, 0, &r_mem)) | 345 | if (of_address_to_resource(of_dev->node, 0, &r_mem)) |
| 345 | dev_err(dev, "invalid address\n"); | 346 | dev_err(dev, "invalid address\n"); |
| 346 | else | 347 | else |
| 347 | release_mem_region(r_mem.start, r_mem.end - r_mem.start + 1); | 348 | release_mem_region(r_mem.start, resource_size(&r_mem)); |
| 348 | 349 | ||
| 349 | kfree(drvdata); | 350 | kfree(drvdata); |
| 350 | 351 | ||
| @@ -354,7 +355,7 @@ static int __devexit xps2_of_remove(struct of_device *of_dev) | |||
| 354 | } | 355 | } |
| 355 | 356 | ||
| 356 | /* Match table for of_platform binding */ | 357 | /* Match table for of_platform binding */ |
| 357 | static struct of_device_id xps2_of_match[] __devinitdata = { | 358 | static const struct of_device_id xps2_of_match[] __devinitconst = { |
| 358 | { .compatible = "xlnx,xps-ps2-1.00.a", }, | 359 | { .compatible = "xlnx,xps-ps2-1.00.a", }, |
| 359 | { /* end of list */ }, | 360 | { /* end of list */ }, |
| 360 | }; | 361 | }; |
diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c new file mode 100644 index 000000000000..82ae18d29685 --- /dev/null +++ b/drivers/input/sparse-keymap.c | |||
| @@ -0,0 +1,253 @@ | |||
| 1 | /* | ||
| 2 | * Generic support for sparse keymaps | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Dmitry Torokhov | ||
| 5 | * | ||
| 6 | * Derived from wistron button driver: | ||
| 7 | * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz> | ||
| 8 | * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org> | ||
| 9 | * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru> | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License version 2 as published by | ||
| 13 | * the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/input/sparse-keymap.h> | ||
| 18 | #include <linux/slab.h> | ||
| 19 | |||
| 20 | MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); | ||
| 21 | MODULE_DESCRIPTION("Generic support for sparse keymaps"); | ||
| 22 | MODULE_LICENSE("GPL v2"); | ||
| 23 | MODULE_VERSION("0.1"); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * sparse_keymap_entry_from_scancode - perform sparse keymap lookup | ||
| 27 | * @dev: Input device using sparse keymap | ||
| 28 | * @code: Scan code | ||
| 29 | * | ||
| 30 | * This function is used to perform &struct key_entry lookup in an | ||
| 31 | * input device using sparse keymap. | ||
| 32 | */ | ||
| 33 | struct key_entry *sparse_keymap_entry_from_scancode(struct input_dev *dev, | ||
| 34 | unsigned int code) | ||
| 35 | { | ||
| 36 | struct key_entry *key; | ||
| 37 | |||
| 38 | for (key = dev->keycode; key->type != KE_END; key++) | ||
| 39 | if (code == key->code) | ||
| 40 | return key; | ||
| 41 | |||
| 42 | return NULL; | ||
| 43 | } | ||
| 44 | EXPORT_SYMBOL(sparse_keymap_entry_from_scancode); | ||
| 45 | |||
| 46 | /** | ||
| 47 | * sparse_keymap_entry_from_keycode - perform sparse keymap lookup | ||
| 48 | * @dev: Input device using sparse keymap | ||
| 49 | * @keycode: Key code | ||
| 50 | * | ||
| 51 | * This function is used to perform &struct key_entry lookup in an | ||
| 52 | * input device using sparse keymap. | ||
| 53 | */ | ||
| 54 | struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, | ||
| 55 | unsigned int keycode) | ||
| 56 | { | ||
| 57 | struct key_entry *key; | ||
| 58 | |||
| 59 | for (key = dev->keycode; key->type != KE_END; key++) | ||
| 60 | if (key->type == KE_KEY && keycode == key->keycode) | ||
| 61 | return key; | ||
| 62 | |||
| 63 | return NULL; | ||
| 64 | } | ||
| 65 | EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); | ||
| 66 | |||
| 67 | static int sparse_keymap_getkeycode(struct input_dev *dev, | ||
| 68 | unsigned int scancode, | ||
| 69 | unsigned int *keycode) | ||
| 70 | { | ||
| 71 | const struct key_entry *key = | ||
| 72 | sparse_keymap_entry_from_scancode(dev, scancode); | ||
| 73 | |||
| 74 | if (key && key->type == KE_KEY) { | ||
| 75 | *keycode = key->keycode; | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | return -EINVAL; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int sparse_keymap_setkeycode(struct input_dev *dev, | ||
| 83 | unsigned int scancode, | ||
| 84 | unsigned int keycode) | ||
| 85 | { | ||
| 86 | struct key_entry *key; | ||
| 87 | int old_keycode; | ||
| 88 | |||
| 89 | if (keycode < 0 || keycode > KEY_MAX) | ||
| 90 | return -EINVAL; | ||
| 91 | |||
| 92 | key = sparse_keymap_entry_from_scancode(dev, scancode); | ||
| 93 | if (key && key->type == KE_KEY) { | ||
| 94 | old_keycode = key->keycode; | ||
| 95 | key->keycode = keycode; | ||
| 96 | set_bit(keycode, dev->keybit); | ||
| 97 | if (!sparse_keymap_entry_from_keycode(dev, old_keycode)) | ||
| 98 | clear_bit(old_keycode, dev->keybit); | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | return -EINVAL; | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * sparse_keymap_setup - set up sparse keymap for an input device | ||
| 107 | * @dev: Input device | ||
| 108 | * @keymap: Keymap in form of array of &key_entry structures ending | ||
| 109 | * with %KE_END type entry | ||
| 110 | * @setup: Function that can be used to adjust keymap entries | ||
| 111 | * depending on device's deeds, may be %NULL | ||
| 112 | * | ||
| 113 | * The function calculates size and allocates copy of the original | ||
| 114 | * keymap after which sets up input device event bits appropriately. | ||
| 115 | * Before destroying input device allocated keymap should be freed | ||
| 116 | * with a call to sparse_keymap_free(). | ||
| 117 | */ | ||
| 118 | int sparse_keymap_setup(struct input_dev *dev, | ||
| 119 | const struct key_entry *keymap, | ||
| 120 | int (*setup)(struct input_dev *, struct key_entry *)) | ||
| 121 | { | ||
| 122 | size_t map_size = 1; /* to account for the last KE_END entry */ | ||
| 123 | const struct key_entry *e; | ||
| 124 | struct key_entry *map, *entry; | ||
| 125 | int i; | ||
| 126 | int error; | ||
| 127 | |||
| 128 | for (e = keymap; e->type != KE_END; e++) | ||
| 129 | map_size++; | ||
| 130 | |||
| 131 | map = kcalloc(map_size, sizeof (struct key_entry), GFP_KERNEL); | ||
| 132 | if (!map) | ||
| 133 | return -ENOMEM; | ||
| 134 | |||
| 135 | memcpy(map, keymap, map_size * sizeof (struct key_entry)); | ||
| 136 | |||
| 137 | for (i = 0; i < map_size; i++) { | ||
| 138 | entry = &map[i]; | ||
| 139 | |||
| 140 | if (setup) { | ||
| 141 | error = setup(dev, entry); | ||
| 142 | if (error) | ||
| 143 | goto err_out; | ||
| 144 | } | ||
| 145 | |||
| 146 | switch (entry->type) { | ||
| 147 | case KE_KEY: | ||
| 148 | __set_bit(EV_KEY, dev->evbit); | ||
| 149 | __set_bit(entry->keycode, dev->keybit); | ||
| 150 | break; | ||
| 151 | |||
| 152 | case KE_SW: | ||
| 153 | __set_bit(EV_SW, dev->evbit); | ||
| 154 | __set_bit(entry->sw.code, dev->swbit); | ||
| 155 | break; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | |||
| 159 | dev->keycode = map; | ||
| 160 | dev->keycodemax = map_size; | ||
| 161 | dev->getkeycode = sparse_keymap_getkeycode; | ||
| 162 | dev->setkeycode = sparse_keymap_setkeycode; | ||
| 163 | |||
| 164 | return 0; | ||
| 165 | |||
| 166 | err_out: | ||
| 167 | kfree(keymap); | ||
| 168 | return error; | ||
| 169 | |||
| 170 | } | ||
| 171 | EXPORT_SYMBOL(sparse_keymap_setup); | ||
| 172 | |||
| 173 | /** | ||
| 174 | * sparse_keymap_free - free memory allocated for sparse keymap | ||
| 175 | * @dev: Input device using sparse keymap | ||
| 176 | * | ||
| 177 | * This function is used to free memory allocated by sparse keymap | ||
| 178 | * in an input device that was set up by sparse_keymap_setup(). | ||
| 179 | */ | ||
| 180 | void sparse_keymap_free(struct input_dev *dev) | ||
| 181 | { | ||
| 182 | kfree(dev->keycode); | ||
| 183 | dev->keycode = NULL; | ||
| 184 | dev->keycodemax = 0; | ||
| 185 | dev->getkeycode = NULL; | ||
| 186 | dev->setkeycode = NULL; | ||
| 187 | } | ||
| 188 | EXPORT_SYMBOL(sparse_keymap_free); | ||
| 189 | |||
| 190 | /** | ||
| 191 | * sparse_keymap_report_entry - report event corresponding to given key entry | ||
| 192 | * @dev: Input device for which event should be reported | ||
| 193 | * @ke: key entry describing event | ||
| 194 | * @value: Value that should be reported (ignored by %KE_SW entries) | ||
| 195 | * @autorelease: Signals whether release event should be emitted for %KE_KEY | ||
| 196 | * entries right after reporting press event, ignored by all other | ||
| 197 | * entries | ||
| 198 | * | ||
| 199 | * This function is used to report input event described by given | ||
| 200 | * &struct key_entry. | ||
| 201 | */ | ||
| 202 | void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *ke, | ||
| 203 | unsigned int value, bool autorelease) | ||
| 204 | { | ||
| 205 | switch (ke->type) { | ||
| 206 | case KE_KEY: | ||
| 207 | input_report_key(dev, ke->keycode, value); | ||
| 208 | input_sync(dev); | ||
| 209 | if (value && autorelease) { | ||
| 210 | input_report_key(dev, ke->keycode, 0); | ||
| 211 | input_sync(dev); | ||
| 212 | } | ||
| 213 | break; | ||
| 214 | |||
| 215 | case KE_SW: | ||
| 216 | value = ke->sw.value; | ||
| 217 | /* fall through */ | ||
| 218 | |||
| 219 | case KE_VSW: | ||
| 220 | input_report_switch(dev, ke->sw.code, value); | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | } | ||
| 224 | EXPORT_SYMBOL(sparse_keymap_report_entry); | ||
| 225 | |||
| 226 | /** | ||
| 227 | * sparse_keymap_report_event - report event corresponding to given scancode | ||
| 228 | * @dev: Input device using sparse keymap | ||
| 229 | * @code: Scan code | ||
| 230 | * @value: Value that should be reported (ignored by %KE_SW entries) | ||
| 231 | * @autorelease: Signals whether release event should be emitted for %KE_KEY | ||
| 232 | * entries right after reporting press event, ignored by all other | ||
| 233 | * entries | ||
| 234 | * | ||
| 235 | * This function is used to perform lookup in an input device using sparse | ||
| 236 | * keymap and report corresponding event. Returns %true if lookup was | ||
| 237 | * successful and %false otherwise. | ||
| 238 | */ | ||
| 239 | bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code, | ||
| 240 | unsigned int value, bool autorelease) | ||
| 241 | { | ||
| 242 | const struct key_entry *ke = | ||
| 243 | sparse_keymap_entry_from_scancode(dev, code); | ||
| 244 | |||
| 245 | if (ke) { | ||
| 246 | sparse_keymap_report_entry(dev, ke, value, autorelease); | ||
| 247 | return true; | ||
| 248 | } | ||
| 249 | |||
| 250 | return false; | ||
| 251 | } | ||
| 252 | EXPORT_SYMBOL(sparse_keymap_report_event); | ||
| 253 | |||
diff --git a/drivers/input/tablet/aiptek.c b/drivers/input/tablet/aiptek.c index 7d005a3616d7..4be039d7dcad 100644 --- a/drivers/input/tablet/aiptek.c +++ b/drivers/input/tablet/aiptek.c | |||
| @@ -362,7 +362,7 @@ static const int macroKeyEvents[] = { | |||
| 362 | }; | 362 | }; |
| 363 | 363 | ||
| 364 | /*********************************************************************** | 364 | /*********************************************************************** |
| 365 | * Map values to strings and back. Every map shoudl have the following | 365 | * Map values to strings and back. Every map should have the following |
| 366 | * as its last element: { NULL, AIPTEK_INVALID_VALUE }. | 366 | * as its last element: { NULL, AIPTEK_INVALID_VALUE }. |
| 367 | */ | 367 | */ |
| 368 | #define AIPTEK_INVALID_VALUE -1 | 368 | #define AIPTEK_INVALID_VALUE -1 |
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index 3d32d3f4e486..866a9ee1af1a 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c | |||
| @@ -92,7 +92,7 @@ Scott Hill shill@gtcocalcomp.com | |||
| 92 | /* DATA STRUCTURES */ | 92 | /* DATA STRUCTURES */ |
| 93 | 93 | ||
| 94 | /* Device table */ | 94 | /* Device table */ |
| 95 | static struct usb_device_id gtco_usbid_table [] = { | 95 | static const struct usb_device_id gtco_usbid_table[] = { |
| 96 | { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, | 96 | { USB_DEVICE(VENDOR_ID_GTCO, PID_400) }, |
| 97 | { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, | 97 | { USB_DEVICE(VENDOR_ID_GTCO, PID_401) }, |
| 98 | { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, | 98 | { USB_DEVICE(VENDOR_ID_GTCO, PID_1000) }, |
diff --git a/drivers/input/tablet/wacom.h b/drivers/input/tablet/wacom.h index 9114ae1c7488..8fef1b689c69 100644 --- a/drivers/input/tablet/wacom.h +++ b/drivers/input/tablet/wacom.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom.h | 2 | * drivers/input/tablet/wacom.h |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support | 4 | * USB Wacom tablet support |
| 5 | * | 5 | * |
| 6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> | 6 | * Copyright (c) 2000-2004 Vojtech Pavlik <vojtech@ucw.cz> |
| 7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> | 7 | * Copyright (c) 2000 Andreas Bach Aaen <abach@stofanet.dk> |
| @@ -69,6 +69,9 @@ | |||
| 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) | 69 | * v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A) |
| 70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 | 70 | * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28 |
| 71 | * v1.51 (pc) - Added support for Intuos4 | 71 | * v1.51 (pc) - Added support for Intuos4 |
| 72 | * v1.52 (pc) - Query Wacom data upon system resume | ||
| 73 | * - add defines for features->type | ||
| 74 | * - add new devices (0x9F, 0xE2, and 0XE3) | ||
| 72 | */ | 75 | */ |
| 73 | 76 | ||
| 74 | /* | 77 | /* |
| @@ -82,6 +85,7 @@ | |||
| 82 | #include <linux/kernel.h> | 85 | #include <linux/kernel.h> |
| 83 | #include <linux/slab.h> | 86 | #include <linux/slab.h> |
| 84 | #include <linux/module.h> | 87 | #include <linux/module.h> |
| 88 | #include <linux/mod_devicetable.h> | ||
| 85 | #include <linux/init.h> | 89 | #include <linux/init.h> |
| 86 | #include <linux/usb/input.h> | 90 | #include <linux/usb/input.h> |
| 87 | #include <asm/unaligned.h> | 91 | #include <asm/unaligned.h> |
| @@ -89,9 +93,9 @@ | |||
| 89 | /* | 93 | /* |
| 90 | * Version Information | 94 | * Version Information |
| 91 | */ | 95 | */ |
| 92 | #define DRIVER_VERSION "v1.51" | 96 | #define DRIVER_VERSION "v1.52" |
| 93 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" | 97 | #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>" |
| 94 | #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver" | 98 | #define DRIVER_DESC "USB Wacom tablet driver" |
| 95 | #define DRIVER_LICENSE "GPL" | 99 | #define DRIVER_LICENSE "GPL" |
| 96 | 100 | ||
| 97 | MODULE_AUTHOR(DRIVER_AUTHOR); | 101 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| @@ -117,6 +121,8 @@ struct wacom_combo { | |||
| 117 | struct urb *urb; | 121 | struct urb *urb; |
| 118 | }; | 122 | }; |
| 119 | 123 | ||
| 124 | extern const struct usb_device_id wacom_ids[]; | ||
| 125 | |||
| 120 | extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); | 126 | extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); |
| 121 | extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); | 127 | extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); |
| 122 | extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); | 128 | extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); |
| @@ -133,11 +139,11 @@ extern void input_dev_i4s(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 133 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 139 | extern void input_dev_i4(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 134 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 140 | extern void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 135 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 141 | extern void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 142 | extern void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
| 143 | extern void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | ||
| 136 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 144 | extern void input_dev_mo(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 137 | extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); | 145 | extern void input_dev_bee(struct input_dev *input_dev, struct wacom_wac *wacom_wac); |
| 138 | extern __u16 wacom_le16_to_cpu(unsigned char *data); | 146 | extern __u16 wacom_le16_to_cpu(unsigned char *data); |
| 139 | extern __u16 wacom_be16_to_cpu(unsigned char *data); | 147 | extern __u16 wacom_be16_to_cpu(unsigned char *data); |
| 140 | extern struct wacom_features *get_wacom_feature(const struct usb_device_id *id); | ||
| 141 | extern const struct usb_device_id *get_device_table(void); | ||
| 142 | 148 | ||
| 143 | #endif | 149 | #endif |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index ea30c983a33e..8b5d2873f0c4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom_sys.c | 2 | * drivers/input/tablet/wacom_sys.c |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support - system specific code | 4 | * USB Wacom tablet support - system specific code |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | /* | 7 | /* |
| @@ -209,8 +209,10 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 209 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | | 209 | input_dev->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_LEFT) | |
| 210 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); | 210 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE); |
| 211 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | 211 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | |
| 212 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
| 212 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); | 213 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); |
| 213 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | 214 | input_set_abs_params(input_dev, ABS_DISTANCE, |
| 215 | 0, wacom_wac->features.distance_max, 0, 0); | ||
| 214 | } | 216 | } |
| 215 | 217 | ||
| 216 | void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 218 | void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| @@ -256,10 +258,12 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 256 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | | 258 | BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE) | |
| 257 | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); | 259 | BIT_MASK(BTN_SIDE) | BIT_MASK(BTN_EXTRA); |
| 258 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | | 260 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | |
| 261 | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | | ||
| 259 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | | 262 | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | |
| 260 | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | | 263 | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | |
| 261 | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); | 264 | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); |
| 262 | input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); | 265 | input_set_abs_params(input_dev, ABS_DISTANCE, |
| 266 | 0, wacom_wac->features.distance_max, 0, 0); | ||
| 263 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); | 267 | input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); |
| 264 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); | 268 | input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); |
| 265 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); | 269 | input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); |
| @@ -269,7 +273,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 269 | 273 | ||
| 270 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 274 | void input_dev_pl(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| 271 | { | 275 | { |
| 272 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_STYLUS2); | 276 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | |
| 277 | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_STYLUS2); | ||
| 273 | } | 278 | } |
| 274 | 279 | ||
| 275 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 280 | void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| @@ -277,12 +282,34 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | |||
| 277 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); | 282 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER); |
| 278 | } | 283 | } |
| 279 | 284 | ||
| 285 | void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
| 286 | { | ||
| 287 | struct wacom_features *features = &wacom_wac->features; | ||
| 288 | |||
| 289 | if (features->device_type == BTN_TOOL_DOUBLETAP || | ||
| 290 | features->device_type == BTN_TOOL_TRIPLETAP) { | ||
| 291 | input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); | ||
| 292 | input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); | ||
| 293 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
| 294 | } | ||
| 295 | } | ||
| 296 | |||
| 297 | void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | ||
| 298 | { | ||
| 299 | if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { | ||
| 300 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); | ||
| 301 | input_dev->evbit[0] |= BIT_MASK(EV_MSC); | ||
| 302 | input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); | ||
| 303 | } | ||
| 304 | } | ||
| 305 | |||
| 280 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, | 306 | static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc, |
| 281 | struct wacom_wac *wacom_wac) | 307 | struct wacom_features *features) |
| 282 | { | 308 | { |
| 283 | struct usb_device *dev = interface_to_usbdev(intf); | 309 | struct usb_device *dev = interface_to_usbdev(intf); |
| 284 | struct wacom_features *features = wacom_wac->features; | 310 | char limit = 0; |
| 285 | char limit = 0, result = 0; | 311 | /* result has to be defined as int for some devices */ |
| 312 | int result = 0; | ||
| 286 | int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; | 313 | int i = 0, usage = WCM_UNDEFINED, finger = 0, pen = 0; |
| 287 | unsigned char *report; | 314 | unsigned char *report; |
| 288 | 315 | ||
| @@ -328,13 +355,24 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 328 | case HID_USAGE_X: | 355 | case HID_USAGE_X: |
| 329 | if (usage == WCM_DESKTOP) { | 356 | if (usage == WCM_DESKTOP) { |
| 330 | if (finger) { | 357 | if (finger) { |
| 331 | features->touch_x_max = | 358 | features->device_type = BTN_TOOL_DOUBLETAP; |
| 332 | features->touch_y_max = | 359 | if (features->type == TABLETPC2FG) { |
| 333 | wacom_le16_to_cpu(&report[i + 3]); | 360 | /* need to reset back */ |
| 361 | features->pktlen = WACOM_PKGLEN_TPC2FG; | ||
| 362 | features->device_type = BTN_TOOL_TRIPLETAP; | ||
| 363 | } | ||
| 334 | features->x_max = | 364 | features->x_max = |
| 365 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 366 | features->x_phy = | ||
| 335 | wacom_le16_to_cpu(&report[i + 6]); | 367 | wacom_le16_to_cpu(&report[i + 6]); |
| 336 | i += 7; | 368 | features->unit = report[i + 9]; |
| 369 | features->unitExpo = report[i + 11]; | ||
| 370 | i += 12; | ||
| 337 | } else if (pen) { | 371 | } else if (pen) { |
| 372 | /* penabled only accepts exact bytes of data */ | ||
| 373 | if (features->type == TABLETPC2FG) | ||
| 374 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | ||
| 375 | features->device_type = BTN_TOOL_PEN; | ||
| 338 | features->x_max = | 376 | features->x_max = |
| 339 | wacom_le16_to_cpu(&report[i + 3]); | 377 | wacom_le16_to_cpu(&report[i + 3]); |
| 340 | i += 4; | 378 | i += 4; |
| @@ -350,10 +388,35 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 350 | break; | 388 | break; |
| 351 | 389 | ||
| 352 | case HID_USAGE_Y: | 390 | case HID_USAGE_Y: |
| 353 | if (usage == WCM_DESKTOP) | 391 | if (usage == WCM_DESKTOP) { |
| 354 | features->y_max = | 392 | if (finger) { |
| 355 | wacom_le16_to_cpu(&report[i + 3]); | 393 | features->device_type = BTN_TOOL_DOUBLETAP; |
| 356 | i += 4; | 394 | if (features->type == TABLETPC2FG) { |
| 395 | /* need to reset back */ | ||
| 396 | features->pktlen = WACOM_PKGLEN_TPC2FG; | ||
| 397 | features->device_type = BTN_TOOL_TRIPLETAP; | ||
| 398 | features->y_max = | ||
| 399 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 400 | features->y_phy = | ||
| 401 | wacom_le16_to_cpu(&report[i + 6]); | ||
| 402 | i += 7; | ||
| 403 | } else { | ||
| 404 | features->y_max = | ||
| 405 | features->x_max; | ||
| 406 | features->y_phy = | ||
| 407 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 408 | i += 4; | ||
| 409 | } | ||
| 410 | } else if (pen) { | ||
| 411 | /* penabled only accepts exact bytes of data */ | ||
| 412 | if (features->type == TABLETPC2FG) | ||
| 413 | features->pktlen = WACOM_PKGLEN_GRAPHIRE; | ||
| 414 | features->device_type = BTN_TOOL_PEN; | ||
| 415 | features->y_max = | ||
| 416 | wacom_le16_to_cpu(&report[i + 3]); | ||
| 417 | i += 4; | ||
| 418 | } | ||
| 419 | } | ||
| 357 | break; | 420 | break; |
| 358 | 421 | ||
| 359 | case HID_USAGE_FINGER: | 422 | case HID_USAGE_FINGER: |
| @@ -376,7 +439,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 376 | break; | 439 | break; |
| 377 | 440 | ||
| 378 | case HID_COLLECTION: | 441 | case HID_COLLECTION: |
| 379 | /* reset UsagePage ans Finger */ | 442 | /* reset UsagePage and Finger */ |
| 380 | finger = usage = 0; | 443 | finger = usage = 0; |
| 381 | break; | 444 | break; |
| 382 | } | 445 | } |
| @@ -388,57 +451,123 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi | |||
| 388 | return result; | 451 | return result; |
| 389 | } | 452 | } |
| 390 | 453 | ||
| 391 | static int wacom_query_tablet_data(struct usb_interface *intf) | 454 | static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_features *features) |
| 392 | { | 455 | { |
| 393 | unsigned char *rep_data; | 456 | unsigned char *rep_data; |
| 394 | int limit = 0; | 457 | int limit = 0, report_id = 2; |
| 395 | int error; | 458 | int error = -ENOMEM; |
| 396 | 459 | ||
| 397 | rep_data = kmalloc(2, GFP_KERNEL); | 460 | rep_data = kmalloc(2, GFP_KERNEL); |
| 398 | if (!rep_data) | 461 | if (!rep_data) |
| 399 | return -ENOMEM; | 462 | return error; |
| 400 | 463 | ||
| 401 | do { | 464 | /* ask to report tablet data if it is 2FGT or not a Tablet PC */ |
| 402 | rep_data[0] = 2; | 465 | if (features->device_type == BTN_TOOL_TRIPLETAP) { |
| 403 | rep_data[1] = 2; | 466 | do { |
| 404 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | 467 | rep_data[0] = 3; |
| 405 | 2, rep_data, 2); | 468 | rep_data[1] = 4; |
| 406 | if (error >= 0) | 469 | report_id = 3; |
| 407 | error = usb_get_report(intf, | 470 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, |
| 408 | WAC_HID_FEATURE_REPORT, 2, | 471 | report_id, rep_data, 2); |
| 409 | rep_data, 2); | 472 | if (error >= 0) |
| 410 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | 473 | error = usb_get_report(intf, |
| 474 | WAC_HID_FEATURE_REPORT, report_id, | ||
| 475 | rep_data, 3); | ||
| 476 | } while ((error < 0 || rep_data[1] != 4) && limit++ < 5); | ||
| 477 | } else if (features->type != TABLETPC && features->type != TABLETPC2FG) { | ||
| 478 | do { | ||
| 479 | rep_data[0] = 2; | ||
| 480 | rep_data[1] = 2; | ||
| 481 | error = usb_set_report(intf, WAC_HID_FEATURE_REPORT, | ||
| 482 | report_id, rep_data, 2); | ||
| 483 | if (error >= 0) | ||
| 484 | error = usb_get_report(intf, | ||
| 485 | WAC_HID_FEATURE_REPORT, report_id, | ||
| 486 | rep_data, 2); | ||
| 487 | } while ((error < 0 || rep_data[1] != 2) && limit++ < 5); | ||
| 488 | } | ||
| 411 | 489 | ||
| 412 | kfree(rep_data); | 490 | kfree(rep_data); |
| 413 | 491 | ||
| 414 | return error < 0 ? error : 0; | 492 | return error < 0 ? error : 0; |
| 415 | } | 493 | } |
| 416 | 494 | ||
| 495 | static int wacom_retrieve_hid_descriptor(struct usb_interface *intf, | ||
| 496 | struct wacom_features *features) | ||
| 497 | { | ||
| 498 | int error = 0; | ||
| 499 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 500 | struct hid_descriptor *hid_desc; | ||
| 501 | |||
| 502 | /* default device to penabled */ | ||
| 503 | features->device_type = BTN_TOOL_PEN; | ||
| 504 | |||
| 505 | /* only Tablet PCs need to retrieve the info */ | ||
| 506 | if ((features->type != TABLETPC) && (features->type != TABLETPC2FG)) | ||
| 507 | goto out; | ||
| 508 | |||
| 509 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | ||
| 510 | if (usb_get_extra_descriptor(&interface->endpoint[0], | ||
| 511 | HID_DEVICET_REPORT, &hid_desc)) { | ||
| 512 | printk("wacom: can not retrieve extra class descriptor\n"); | ||
| 513 | error = 1; | ||
| 514 | goto out; | ||
| 515 | } | ||
| 516 | } | ||
| 517 | error = wacom_parse_hid(intf, hid_desc, features); | ||
| 518 | if (error) | ||
| 519 | goto out; | ||
| 520 | |||
| 521 | /* touch device found but size is not defined. use default */ | ||
| 522 | if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) { | ||
| 523 | features->x_max = 1023; | ||
| 524 | features->y_max = 1023; | ||
| 525 | } | ||
| 526 | |||
| 527 | out: | ||
| 528 | return error; | ||
| 529 | } | ||
| 530 | |||
| 417 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 531 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 418 | { | 532 | { |
| 419 | struct usb_device *dev = interface_to_usbdev(intf); | 533 | struct usb_device *dev = interface_to_usbdev(intf); |
| 420 | struct usb_host_interface *interface = intf->cur_altsetting; | ||
| 421 | struct usb_endpoint_descriptor *endpoint; | 534 | struct usb_endpoint_descriptor *endpoint; |
| 422 | struct wacom *wacom; | 535 | struct wacom *wacom; |
| 423 | struct wacom_wac *wacom_wac; | 536 | struct wacom_wac *wacom_wac; |
| 424 | struct wacom_features *features; | 537 | struct wacom_features *features; |
| 425 | struct input_dev *input_dev; | 538 | struct input_dev *input_dev; |
| 426 | int error = -ENOMEM; | 539 | int error; |
| 427 | struct hid_descriptor *hid_desc; | 540 | |
| 541 | if (!id->driver_info) | ||
| 542 | return -EINVAL; | ||
| 428 | 543 | ||
| 429 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); | 544 | wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); |
| 430 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); | 545 | wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); |
| 431 | input_dev = input_allocate_device(); | 546 | input_dev = input_allocate_device(); |
| 432 | if (!wacom || !input_dev || !wacom_wac) | 547 | if (!wacom || !input_dev || !wacom_wac) { |
| 548 | error = -ENOMEM; | ||
| 433 | goto fail1; | 549 | goto fail1; |
| 550 | } | ||
| 434 | 551 | ||
| 435 | wacom_wac->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); | 552 | wacom_wac->features = *((struct wacom_features *)id->driver_info); |
| 436 | if (!wacom_wac->data) | 553 | features = &wacom_wac->features; |
| 554 | if (features->pktlen > WACOM_PKGLEN_MAX) { | ||
| 555 | error = -EINVAL; | ||
| 437 | goto fail1; | 556 | goto fail1; |
| 557 | } | ||
| 558 | |||
| 559 | wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, | ||
| 560 | GFP_KERNEL, &wacom->data_dma); | ||
| 561 | if (!wacom_wac->data) { | ||
| 562 | error = -ENOMEM; | ||
| 563 | goto fail1; | ||
| 564 | } | ||
| 438 | 565 | ||
| 439 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); | 566 | wacom->irq = usb_alloc_urb(0, GFP_KERNEL); |
| 440 | if (!wacom->irq) | 567 | if (!wacom->irq) { |
| 568 | error = -ENOMEM; | ||
| 441 | goto fail2; | 569 | goto fail2; |
| 570 | } | ||
| 442 | 571 | ||
| 443 | wacom->usbdev = dev; | 572 | wacom->usbdev = dev; |
| 444 | wacom->dev = input_dev; | 573 | wacom->dev = input_dev; |
| @@ -447,11 +576,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 447 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); | 576 | usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); |
| 448 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); | 577 | strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); |
| 449 | 578 | ||
| 450 | wacom_wac->features = features = get_wacom_feature(id); | ||
| 451 | BUG_ON(features->pktlen > 10); | ||
| 452 | |||
| 453 | input_dev->name = wacom_wac->features->name; | ||
| 454 | wacom->wacom_wac = wacom_wac; | ||
| 455 | usb_to_input_id(dev, &input_dev->id); | 579 | usb_to_input_id(dev, &input_dev->id); |
| 456 | 580 | ||
| 457 | input_dev->dev.parent = &intf->dev; | 581 | input_dev->dev.parent = &intf->dev; |
| @@ -463,47 +587,37 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 463 | 587 | ||
| 464 | endpoint = &intf->cur_altsetting->endpoint[0].desc; | 588 | endpoint = &intf->cur_altsetting->endpoint[0].desc; |
| 465 | 589 | ||
| 466 | /* Initialize touch_x_max and touch_y_max in case it is not defined */ | 590 | /* Retrieve the physical and logical size for OEM devices */ |
| 467 | if (wacom_wac->features->type == TABLETPC) { | 591 | error = wacom_retrieve_hid_descriptor(intf, features); |
| 468 | features->touch_x_max = 1023; | 592 | if (error) |
| 469 | features->touch_y_max = 1023; | 593 | goto fail2; |
| 470 | } else { | ||
| 471 | features->touch_x_max = 0; | ||
| 472 | features->touch_y_max = 0; | ||
| 473 | } | ||
| 474 | 594 | ||
| 475 | /* TabletPC need to retrieve the physical and logical maximum from report descriptor */ | 595 | strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); |
| 476 | if (wacom_wac->features->type == TABLETPC) { | 596 | |
| 477 | if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) { | 597 | if (features->type == TABLETPC || features->type == TABLETPC2FG) { |
| 478 | if (usb_get_extra_descriptor(&interface->endpoint[0], | 598 | /* Append the device type to the name */ |
| 479 | HID_DEVICET_REPORT, &hid_desc)) { | 599 | strlcat(wacom_wac->name, |
| 480 | printk("wacom: can not retrive extra class descriptor\n"); | 600 | features->device_type == BTN_TOOL_PEN ? |
| 481 | goto fail2; | 601 | " Pen" : " Finger", |
| 482 | } | 602 | sizeof(wacom_wac->name)); |
| 483 | } | ||
| 484 | error = wacom_parse_hid(intf, hid_desc, wacom_wac); | ||
| 485 | if (error) | ||
| 486 | goto fail2; | ||
| 487 | } | 603 | } |
| 488 | 604 | ||
| 605 | input_dev->name = wacom_wac->name; | ||
| 606 | wacom->wacom_wac = wacom_wac; | ||
| 607 | |||
| 489 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 608 | input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); |
| 490 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_PEN) | | 609 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); |
| 491 | BIT_MASK(BTN_TOUCH) | BIT_MASK(BTN_STYLUS); | 610 | |
| 492 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); | 611 | input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0); |
| 493 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); | 612 | input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0); |
| 494 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); | 613 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0); |
| 495 | if (features->type == TABLETPC) { | ||
| 496 | input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); | ||
| 497 | input_set_abs_params(input_dev, ABS_RX, 0, features->touch_x_max, 4, 0); | ||
| 498 | input_set_abs_params(input_dev, ABS_RY, 0, features->touch_y_max, 4, 0); | ||
| 499 | } | ||
| 500 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); | 614 | input_dev->absbit[BIT_WORD(ABS_MISC)] |= BIT_MASK(ABS_MISC); |
| 501 | 615 | ||
| 502 | wacom_init_input_dev(input_dev, wacom_wac); | 616 | wacom_init_input_dev(input_dev, wacom_wac); |
| 503 | 617 | ||
| 504 | usb_fill_int_urb(wacom->irq, dev, | 618 | usb_fill_int_urb(wacom->irq, dev, |
| 505 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), | 619 | usb_rcvintpipe(dev, endpoint->bEndpointAddress), |
| 506 | wacom_wac->data, wacom_wac->features->pktlen, | 620 | wacom_wac->data, features->pktlen, |
| 507 | wacom_sys_irq, wacom, endpoint->bInterval); | 621 | wacom_sys_irq, wacom, endpoint->bInterval); |
| 508 | wacom->irq->transfer_dma = wacom->data_dma; | 622 | wacom->irq->transfer_dma = wacom->data_dma; |
| 509 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 623 | wacom->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| @@ -512,18 +626,14 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 512 | if (error) | 626 | if (error) |
| 513 | goto fail3; | 627 | goto fail3; |
| 514 | 628 | ||
| 515 | /* | 629 | /* Note that if query fails it is not a hard failure */ |
| 516 | * Ask the tablet to report tablet data if it is not a Tablet PC. | 630 | wacom_query_tablet_data(intf, features); |
| 517 | * Note that if query fails it is not a hard failure. | ||
| 518 | */ | ||
| 519 | if (wacom_wac->features->type != TABLETPC) | ||
| 520 | wacom_query_tablet_data(intf); | ||
| 521 | 631 | ||
| 522 | usb_set_intfdata(intf, wacom); | 632 | usb_set_intfdata(intf, wacom); |
| 523 | return 0; | 633 | return 0; |
| 524 | 634 | ||
| 525 | fail3: usb_free_urb(wacom->irq); | 635 | fail3: usb_free_urb(wacom->irq); |
| 526 | fail2: usb_buffer_free(dev, 10, wacom_wac->data, wacom->data_dma); | 636 | fail2: usb_buffer_free(dev, WACOM_PKGLEN_MAX, wacom_wac->data, wacom->data_dma); |
| 527 | fail1: input_free_device(input_dev); | 637 | fail1: input_free_device(input_dev); |
| 528 | kfree(wacom); | 638 | kfree(wacom); |
| 529 | kfree(wacom_wac); | 639 | kfree(wacom_wac); |
| @@ -539,7 +649,7 @@ static void wacom_disconnect(struct usb_interface *intf) | |||
| 539 | usb_kill_urb(wacom->irq); | 649 | usb_kill_urb(wacom->irq); |
| 540 | input_unregister_device(wacom->dev); | 650 | input_unregister_device(wacom->dev); |
| 541 | usb_free_urb(wacom->irq); | 651 | usb_free_urb(wacom->irq); |
| 542 | usb_buffer_free(interface_to_usbdev(intf), 10, | 652 | usb_buffer_free(interface_to_usbdev(intf), WACOM_PKGLEN_MAX, |
| 543 | wacom->wacom_wac->data, wacom->data_dma); | 653 | wacom->wacom_wac->data, wacom->data_dma); |
| 544 | kfree(wacom->wacom_wac); | 654 | kfree(wacom->wacom_wac); |
| 545 | kfree(wacom); | 655 | kfree(wacom); |
| @@ -559,12 +669,16 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 559 | static int wacom_resume(struct usb_interface *intf) | 669 | static int wacom_resume(struct usb_interface *intf) |
| 560 | { | 670 | { |
| 561 | struct wacom *wacom = usb_get_intfdata(intf); | 671 | struct wacom *wacom = usb_get_intfdata(intf); |
| 672 | struct wacom_features *features = &wacom->wacom_wac->features; | ||
| 562 | int rv; | 673 | int rv; |
| 563 | 674 | ||
| 564 | mutex_lock(&wacom->lock); | 675 | mutex_lock(&wacom->lock); |
| 565 | if (wacom->open) | 676 | if (wacom->open) { |
| 566 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); | 677 | rv = usb_submit_urb(wacom->irq, GFP_NOIO); |
| 567 | else | 678 | /* switch to wacom mode if needed */ |
| 679 | if (!wacom_retrieve_hid_descriptor(intf, features)) | ||
| 680 | wacom_query_tablet_data(intf, features); | ||
| 681 | } else | ||
| 568 | rv = 0; | 682 | rv = 0; |
| 569 | mutex_unlock(&wacom->lock); | 683 | mutex_unlock(&wacom->lock); |
| 570 | 684 | ||
| @@ -578,6 +692,7 @@ static int wacom_reset_resume(struct usb_interface *intf) | |||
| 578 | 692 | ||
| 579 | static struct usb_driver wacom_driver = { | 693 | static struct usb_driver wacom_driver = { |
| 580 | .name = "wacom", | 694 | .name = "wacom", |
| 695 | .id_table = wacom_ids, | ||
| 581 | .probe = wacom_probe, | 696 | .probe = wacom_probe, |
| 582 | .disconnect = wacom_disconnect, | 697 | .disconnect = wacom_disconnect, |
| 583 | .suspend = wacom_suspend, | 698 | .suspend = wacom_suspend, |
| @@ -589,7 +704,7 @@ static struct usb_driver wacom_driver = { | |||
| 589 | static int __init wacom_init(void) | 704 | static int __init wacom_init(void) |
| 590 | { | 705 | { |
| 591 | int result; | 706 | int result; |
| 592 | wacom_driver.id_table = get_device_table(); | 707 | |
| 593 | result = usb_register(&wacom_driver); | 708 | result = usb_register(&wacom_driver); |
| 594 | if (result == 0) | 709 | if (result == 0) |
| 595 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" | 710 | printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index c896d6a21b7e..b3ba3437a2eb 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * drivers/input/tablet/wacom_wac.c | 2 | * drivers/input/tablet/wacom_wac.c |
| 3 | * | 3 | * |
| 4 | * USB Wacom Graphire and Wacom Intuos tablet support - Wacom specific code | 4 | * USB Wacom tablet support - Wacom specific code |
| 5 | * | 5 | * |
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| @@ -55,23 +55,23 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 55 | 55 | ||
| 56 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) | 56 | static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) |
| 57 | { | 57 | { |
| 58 | struct wacom_features *features = &wacom->features; | ||
| 58 | unsigned char *data = wacom->data; | 59 | unsigned char *data = wacom->data; |
| 59 | int prox, pressure; | 60 | int prox, pressure; |
| 60 | 61 | ||
| 61 | if (data[0] != 2) { | 62 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 62 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); | 63 | dbg("wacom_pl_irq: received unknown report #%d", data[0]); |
| 63 | return 0; | 64 | return 0; |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | prox = data[1] & 0x40; | 67 | prox = data[1] & 0x40; |
| 67 | 68 | ||
| 68 | wacom->id[0] = ERASER_DEVICE_ID; | ||
| 69 | if (prox) { | 69 | if (prox) { |
| 70 | 70 | wacom->id[0] = ERASER_DEVICE_ID; | |
| 71 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 71 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
| 72 | if (wacom->features->pressure_max > 255) | 72 | if (features->pressure_max > 255) |
| 73 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); | 73 | pressure = (pressure << 1) | ((data[4] >> 6) & 1); |
| 74 | pressure += (wacom->features->pressure_max + 1) / 2; | 74 | pressure += (features->pressure_max + 1) / 2; |
| 75 | 75 | ||
| 76 | /* | 76 | /* |
| 77 | * if going from out of proximity into proximity select between the eraser | 77 | * if going from out of proximity into proximity select between the eraser |
| @@ -128,7 +128,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 128 | { | 128 | { |
| 129 | unsigned char *data = wacom->data; | 129 | unsigned char *data = wacom->data; |
| 130 | 130 | ||
| 131 | if (data[0] != 2) { | 131 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 132 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); | 132 | printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]); |
| 133 | return 0; | 133 | return 0; |
| 134 | } | 134 | } |
| @@ -153,18 +153,21 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 153 | 153 | ||
| 154 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | 154 | static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) |
| 155 | { | 155 | { |
| 156 | struct wacom_features *features = &wacom->features; | ||
| 156 | unsigned char *data = wacom->data; | 157 | unsigned char *data = wacom->data; |
| 157 | int x, y, rw; | 158 | int x, y, prox; |
| 159 | int rw = 0; | ||
| 160 | int retval = 0; | ||
| 158 | 161 | ||
| 159 | if (data[0] != 2) { | 162 | if (data[0] != WACOM_REPORT_PENABLED) { |
| 160 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); | 163 | dbg("wacom_graphire_irq: received unknown report #%d", data[0]); |
| 161 | return 0; | 164 | goto exit; |
| 162 | } | 165 | } |
| 163 | 166 | ||
| 164 | if (data[1] & 0x80) { | 167 | prox = data[1] & 0x80; |
| 165 | /* in prox and not a pad data */ | 168 | if (prox || wacom->id[0]) { |
| 166 | 169 | if (prox) { | |
| 167 | switch ((data[1] >> 5) & 3) { | 170 | switch ((data[1] >> 5) & 3) { |
| 168 | 171 | ||
| 169 | case 0: /* Pen */ | 172 | case 0: /* Pen */ |
| 170 | wacom->tool[0] = BTN_TOOL_PEN; | 173 | wacom->tool[0] = BTN_TOOL_PEN; |
| @@ -178,25 +181,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 178 | 181 | ||
| 179 | case 2: /* Mouse with wheel */ | 182 | case 2: /* Mouse with wheel */ |
| 180 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); | 183 | wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); |
| 181 | if (wacom->features->type == WACOM_G4 || | ||
| 182 | wacom->features->type == WACOM_MO) { | ||
| 183 | rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); | ||
| 184 | wacom_report_rel(wcombo, REL_WHEEL, -rw); | ||
| 185 | } else | ||
| 186 | wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); | ||
| 187 | /* fall through */ | 184 | /* fall through */ |
| 188 | 185 | ||
| 189 | case 3: /* Mouse without wheel */ | 186 | case 3: /* Mouse without wheel */ |
| 190 | wacom->tool[0] = BTN_TOOL_MOUSE; | 187 | wacom->tool[0] = BTN_TOOL_MOUSE; |
| 191 | wacom->id[0] = CURSOR_DEVICE_ID; | 188 | wacom->id[0] = CURSOR_DEVICE_ID; |
| 192 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); | ||
| 193 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); | ||
| 194 | if (wacom->features->type == WACOM_G4 || | ||
| 195 | wacom->features->type == WACOM_MO) | ||
| 196 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
| 197 | else | ||
| 198 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
| 199 | break; | 189 | break; |
| 190 | } | ||
| 200 | } | 191 | } |
| 201 | x = wacom_le16_to_cpu(&data[2]); | 192 | x = wacom_le16_to_cpu(&data[2]); |
| 202 | y = wacom_le16_to_cpu(&data[4]); | 193 | y = wacom_le16_to_cpu(&data[4]); |
| @@ -207,32 +198,32 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 207 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); | 198 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); |
| 208 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | 199 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
| 209 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); | 200 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); |
| 210 | } | ||
| 211 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
| 212 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
| 213 | } else if (wacom->id[0]) { | ||
| 214 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 215 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 216 | if (wacom->tool[0] == BTN_TOOL_MOUSE) { | ||
| 217 | wacom_report_key(wcombo, BTN_LEFT, 0); | ||
| 218 | wacom_report_key(wcombo, BTN_RIGHT, 0); | ||
| 219 | wacom_report_abs(wcombo, ABS_DISTANCE, 0); | ||
| 220 | } else { | 201 | } else { |
| 221 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | 202 | wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); |
| 222 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 203 | wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); |
| 223 | wacom_report_key(wcombo, BTN_STYLUS, 0); | 204 | if (features->type == WACOM_G4 || |
| 224 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 205 | features->type == WACOM_MO) { |
| 206 | wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); | ||
| 207 | rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); | ||
| 208 | } else { | ||
| 209 | wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); | ||
| 210 | rw = -(signed)data[6]; | ||
| 211 | } | ||
| 212 | wacom_report_rel(wcombo, REL_WHEEL, rw); | ||
| 225 | } | 213 | } |
| 226 | wacom->id[0] = 0; | 214 | |
| 227 | wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ | 215 | if (!prox) |
| 228 | wacom_report_key(wcombo, wacom->tool[0], 0); | 216 | wacom->id[0] = 0; |
| 217 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ | ||
| 218 | wacom_report_key(wcombo, wacom->tool[0], prox); | ||
| 219 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 229 | } | 220 | } |
| 230 | 221 | ||
| 231 | /* send pad data */ | 222 | /* send pad data */ |
| 232 | switch (wacom->features->type) { | 223 | switch (features->type) { |
| 233 | case WACOM_G4: | 224 | case WACOM_G4: |
| 234 | if (data[7] & 0xf8) { | 225 | prox = data[7] & 0xf8; |
| 235 | wacom_input_sync(wcombo); /* sync last event */ | 226 | if (prox || wacom->id[1]) { |
| 236 | wacom->id[1] = PAD_DEVICE_ID; | 227 | wacom->id[1] = PAD_DEVICE_ID; |
| 237 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | 228 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); |
| 238 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | 229 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); |
| @@ -240,20 +231,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 240 | wacom_report_rel(wcombo, REL_WHEEL, rw); | 231 | wacom_report_rel(wcombo, REL_WHEEL, rw); |
| 241 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 232 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); |
| 242 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 233 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 243 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 234 | if (!prox) |
| 244 | } else if (wacom->id[1]) { | 235 | wacom->id[1] = 0; |
| 245 | wacom_input_sync(wcombo); /* sync last event */ | 236 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 246 | wacom->id[1] = 0; | ||
| 247 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); | ||
| 248 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); | ||
| 249 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
| 250 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 251 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 237 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 252 | } | 238 | } |
| 239 | retval = 1; | ||
| 253 | break; | 240 | break; |
| 254 | case WACOM_MO: | 241 | case WACOM_MO: |
| 255 | if ((data[7] & 0xf8) || (data[8] & 0xff)) { | 242 | prox = (data[7] & 0xf8) || data[8]; |
| 256 | wacom_input_sync(wcombo); /* sync last event */ | 243 | if (prox || wacom->id[1]) { |
| 257 | wacom->id[1] = PAD_DEVICE_ID; | 244 | wacom->id[1] = PAD_DEVICE_ID; |
| 258 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | 245 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); |
| 259 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | 246 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); |
| @@ -261,32 +248,26 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 261 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | 248 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); |
| 262 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | 249 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); |
| 263 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); | 250 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); |
| 251 | if (!prox) | ||
| 252 | wacom->id[1] = 0; | ||
| 264 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); | 253 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); |
| 265 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | 254 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); |
| 266 | } else if (wacom->id[1]) { | ||
| 267 | wacom_input_sync(wcombo); /* sync last event */ | ||
| 268 | wacom->id[1] = 0; | ||
| 269 | wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); | ||
| 270 | wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); | ||
| 271 | wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); | ||
| 272 | wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); | ||
| 273 | wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); | ||
| 274 | wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); | ||
| 275 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 276 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 277 | } | 255 | } |
| 256 | retval = 1; | ||
| 278 | break; | 257 | break; |
| 279 | } | 258 | } |
| 280 | return 1; | 259 | exit: |
| 260 | return retval; | ||
| 281 | } | 261 | } |
| 282 | 262 | ||
| 283 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | 263 | static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) |
| 284 | { | 264 | { |
| 265 | struct wacom_features *features = &wacom->features; | ||
| 285 | unsigned char *data = wacom->data; | 266 | unsigned char *data = wacom->data; |
| 286 | int idx = 0; | 267 | int idx = 0; |
| 287 | 268 | ||
| 288 | /* tool number */ | 269 | /* tool number */ |
| 289 | if (wacom->features->type == INTUOS) | 270 | if (features->type == INTUOS) |
| 290 | idx = data[1] & 0x01; | 271 | idx = data[1] & 0x01; |
| 291 | 272 | ||
| 292 | /* Enter report */ | 273 | /* Enter report */ |
| @@ -384,7 +365,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
| 384 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | 365 | wacom_report_key(wcombo, BTN_STYLUS2, 0); |
| 385 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 366 | wacom_report_key(wcombo, BTN_TOUCH, 0); |
| 386 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 367 | wacom_report_abs(wcombo, ABS_WHEEL, 0); |
| 387 | if (wacom->features->type >= INTUOS3S) | 368 | if (features->type >= INTUOS3S) |
| 388 | wacom_report_abs(wcombo, ABS_Z, 0); | 369 | wacom_report_abs(wcombo, ABS_Z, 0); |
| 389 | } | 370 | } |
| 390 | wacom_report_key(wcombo, wacom->tool[idx], 0); | 371 | wacom_report_key(wcombo, wacom->tool[idx], 0); |
| @@ -398,13 +379,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) | |||
| 398 | 379 | ||
| 399 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | 380 | static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) |
| 400 | { | 381 | { |
| 382 | struct wacom_features *features = &wacom->features; | ||
| 401 | unsigned char *data = wacom->data; | 383 | unsigned char *data = wacom->data; |
| 402 | unsigned int t; | 384 | unsigned int t; |
| 403 | 385 | ||
| 404 | /* general pen packet */ | 386 | /* general pen packet */ |
| 405 | if ((data[1] & 0xb8) == 0xa0) { | 387 | if ((data[1] & 0xb8) == 0xa0) { |
| 406 | t = (data[6] << 2) | ((data[7] >> 6) & 3); | 388 | t = (data[6] << 2) | ((data[7] >> 6) & 3); |
| 407 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) | 389 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) |
| 408 | t = (t << 1) | (data[1] & 1); | 390 | t = (t << 1) | (data[1] & 1); |
| 409 | wacom_report_abs(wcombo, ABS_PRESSURE, t); | 391 | wacom_report_abs(wcombo, ABS_PRESSURE, t); |
| 410 | wacom_report_abs(wcombo, ABS_TILT_X, | 392 | wacom_report_abs(wcombo, ABS_TILT_X, |
| @@ -428,26 +410,28 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) | |||
| 428 | 410 | ||
| 429 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | 411 | static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) |
| 430 | { | 412 | { |
| 413 | struct wacom_features *features = &wacom->features; | ||
| 431 | unsigned char *data = wacom->data; | 414 | unsigned char *data = wacom->data; |
| 432 | unsigned int t; | 415 | unsigned int t; |
| 433 | int idx = 0, result; | 416 | int idx = 0, result; |
| 434 | 417 | ||
| 435 | if (data[0] != 2 && data[0] != 5 && data[0] != 6 && data[0] != 12) { | 418 | if (data[0] != WACOM_REPORT_PENABLED && data[0] != WACOM_REPORT_INTUOSREAD |
| 419 | && data[0] != WACOM_REPORT_INTUOSWRITE && data[0] != WACOM_REPORT_INTUOSPAD) { | ||
| 436 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); | 420 | dbg("wacom_intuos_irq: received unknown report #%d", data[0]); |
| 437 | return 0; | 421 | return 0; |
| 438 | } | 422 | } |
| 439 | 423 | ||
| 440 | /* tool number */ | 424 | /* tool number */ |
| 441 | if (wacom->features->type == INTUOS) | 425 | if (features->type == INTUOS) |
| 442 | idx = data[1] & 0x01; | 426 | idx = data[1] & 0x01; |
| 443 | 427 | ||
| 444 | /* pad packets. Works as a second tool and is always in prox */ | 428 | /* pad packets. Works as a second tool and is always in prox */ |
| 445 | if (data[0] == 12) { | 429 | if (data[0] == WACOM_REPORT_INTUOSPAD) { |
| 446 | /* initiate the pad as a device */ | 430 | /* initiate the pad as a device */ |
| 447 | if (wacom->tool[1] != BTN_TOOL_FINGER) | 431 | if (wacom->tool[1] != BTN_TOOL_FINGER) |
| 448 | wacom->tool[1] = BTN_TOOL_FINGER; | 432 | wacom->tool[1] = BTN_TOOL_FINGER; |
| 449 | 433 | ||
| 450 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { | 434 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
| 451 | wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); | 435 | wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); |
| 452 | wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); | 436 | wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); |
| 453 | wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); | 437 | wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); |
| @@ -461,7 +445,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 461 | /* Out of proximity, clear wheel value. */ | 445 | /* Out of proximity, clear wheel value. */ |
| 462 | wacom_report_abs(wcombo, ABS_WHEEL, 0); | 446 | wacom_report_abs(wcombo, ABS_WHEEL, 0); |
| 463 | } | 447 | } |
| 464 | if (wacom->features->type != INTUOS4S) { | 448 | if (features->type != INTUOS4S) { |
| 465 | wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); | 449 | wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); |
| 466 | wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); | 450 | wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); |
| 467 | } | 451 | } |
| @@ -509,18 +493,20 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 509 | return 0; | 493 | return 0; |
| 510 | 494 | ||
| 511 | /* Only large Intuos support Lense Cursor */ | 495 | /* Only large Intuos support Lense Cursor */ |
| 512 | if ((wacom->tool[idx] == BTN_TOOL_LENS) | 496 | if (wacom->tool[idx] == BTN_TOOL_LENS && |
| 513 | && ((wacom->features->type == INTUOS3) | 497 | (features->type == INTUOS3 || |
| 514 | || (wacom->features->type == INTUOS3S) | 498 | features->type == INTUOS3S || |
| 515 | || (wacom->features->type == INTUOS4) | 499 | features->type == INTUOS4 || |
| 516 | || (wacom->features->type == INTUOS4S))) | 500 | features->type == INTUOS4S)) { |
| 501 | |||
| 517 | return 0; | 502 | return 0; |
| 503 | } | ||
| 518 | 504 | ||
| 519 | /* Cintiq doesn't send data when RDY bit isn't set */ | 505 | /* Cintiq doesn't send data when RDY bit isn't set */ |
| 520 | if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) | 506 | if (features->type == CINTIQ && !(data[1] & 0x40)) |
| 521 | return 0; | 507 | return 0; |
| 522 | 508 | ||
| 523 | if (wacom->features->type >= INTUOS3S) { | 509 | if (features->type >= INTUOS3S) { |
| 524 | wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); | 510 | wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); |
| 525 | wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); | 511 | wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); |
| 526 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); | 512 | wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); |
| @@ -538,7 +524,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 538 | 524 | ||
| 539 | if (data[1] & 0x02) { | 525 | if (data[1] & 0x02) { |
| 540 | /* Rotation packet */ | 526 | /* Rotation packet */ |
| 541 | if (wacom->features->type >= INTUOS3S) { | 527 | if (features->type >= INTUOS3S) { |
| 542 | /* I3 marker pen rotation */ | 528 | /* I3 marker pen rotation */ |
| 543 | t = (data[6] << 3) | ((data[7] >> 5) & 7); | 529 | t = (data[6] << 3) | ((data[7] >> 5) & 7); |
| 544 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : | 530 | t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : |
| @@ -551,7 +537,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 551 | ((t - 1) / 2) : -t / 2); | 537 | ((t - 1) / 2) : -t / 2); |
| 552 | } | 538 | } |
| 553 | 539 | ||
| 554 | } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { | 540 | } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { |
| 555 | /* 4D mouse packet */ | 541 | /* 4D mouse packet */ |
| 556 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | 542 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); |
| 557 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); | 543 | wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); |
| @@ -564,7 +550,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 564 | 550 | ||
| 565 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { | 551 | } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { |
| 566 | /* I4 mouse */ | 552 | /* I4 mouse */ |
| 567 | if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { | 553 | if (features->type >= INTUOS4S && features->type <= INTUOS4L) { |
| 568 | wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); | 554 | wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); |
| 569 | wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); | 555 | wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); |
| 570 | wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); | 556 | wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); |
| @@ -585,13 +571,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 585 | - ((data[8] & 0x02) >> 1)); | 571 | - ((data[8] & 0x02) >> 1)); |
| 586 | 572 | ||
| 587 | /* I3 2D mouse side buttons */ | 573 | /* I3 2D mouse side buttons */ |
| 588 | if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { | 574 | if (features->type >= INTUOS3S && features->type <= INTUOS3L) { |
| 589 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); | 575 | wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); |
| 590 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); | 576 | wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); |
| 591 | } | 577 | } |
| 592 | } | 578 | } |
| 593 | } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L || | 579 | } else if ((features->type < INTUOS3S || features->type == INTUOS3L || |
| 594 | wacom->features->type == INTUOS4L) && | 580 | features->type == INTUOS4L) && |
| 595 | wacom->tool[idx] == BTN_TOOL_LENS) { | 581 | wacom->tool[idx] == BTN_TOOL_LENS) { |
| 596 | /* Lens cursor packets */ | 582 | /* Lens cursor packets */ |
| 597 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); | 583 | wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); |
| @@ -608,115 +594,181 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 608 | return 1; | 594 | return 1; |
| 609 | } | 595 | } |
| 610 | 596 | ||
| 597 | |||
| 598 | static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) | ||
| 599 | { | ||
| 600 | wacom_report_abs(wcombo, ABS_X, | ||
| 601 | data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); | ||
| 602 | wacom_report_abs(wcombo, ABS_Y, | ||
| 603 | data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); | ||
| 604 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 605 | wacom_report_key(wcombo, wacom->tool[idx], 1); | ||
| 606 | if (idx) | ||
| 607 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 608 | else | ||
| 609 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 610 | } | ||
| 611 | |||
| 612 | static void wacom_tpc_touch_out(struct wacom_wac *wacom, void *wcombo, int idx) | ||
| 613 | { | ||
| 614 | wacom_report_abs(wcombo, ABS_X, 0); | ||
| 615 | wacom_report_abs(wcombo, ABS_Y, 0); | ||
| 616 | wacom_report_abs(wcombo, ABS_MISC, 0); | ||
| 617 | wacom_report_key(wcombo, wacom->tool[idx], 0); | ||
| 618 | if (idx) | ||
| 619 | wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); | ||
| 620 | else | ||
| 621 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 622 | return; | ||
| 623 | } | ||
| 624 | |||
| 625 | static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) | ||
| 626 | { | ||
| 627 | char *data = wacom->data; | ||
| 628 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | ||
| 629 | static int firstFinger = 0; | ||
| 630 | static int secondFinger = 0; | ||
| 631 | |||
| 632 | wacom->tool[0] = BTN_TOOL_DOUBLETAP; | ||
| 633 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
| 634 | wacom->tool[1] = BTN_TOOL_TRIPLETAP; | ||
| 635 | |||
| 636 | if (urb->actual_length != WACOM_PKGLEN_TPC1FG) { | ||
| 637 | switch (data[0]) { | ||
| 638 | case WACOM_REPORT_TPC1FG: | ||
| 639 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 640 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 641 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
| 642 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
| 643 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 644 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
| 645 | break; | ||
| 646 | case WACOM_REPORT_TPC2FG: | ||
| 647 | /* keep this byte to send proper out-prox event */ | ||
| 648 | wacom->id[1] = data[1] & 0x03; | ||
| 649 | |||
| 650 | if (data[1] & 0x01) { | ||
| 651 | wacom_tpc_finger_in(wacom, wcombo, data, 0); | ||
| 652 | firstFinger = 1; | ||
| 653 | } else if (firstFinger) { | ||
| 654 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
| 655 | } | ||
| 656 | |||
| 657 | if (data[1] & 0x02) { | ||
| 658 | /* sync first finger data */ | ||
| 659 | if (firstFinger) | ||
| 660 | wacom_input_sync(wcombo); | ||
| 661 | |||
| 662 | wacom_tpc_finger_in(wacom, wcombo, data, 1); | ||
| 663 | secondFinger = 1; | ||
| 664 | } else if (secondFinger) { | ||
| 665 | /* sync first finger data */ | ||
| 666 | if (firstFinger) | ||
| 667 | wacom_input_sync(wcombo); | ||
| 668 | |||
| 669 | wacom_tpc_touch_out(wacom, wcombo, 1); | ||
| 670 | secondFinger = 0; | ||
| 671 | } | ||
| 672 | if (!(data[1] & 0x01)) | ||
| 673 | firstFinger = 0; | ||
| 674 | break; | ||
| 675 | } | ||
| 676 | } else { | ||
| 677 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
| 678 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
| 679 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 680 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 681 | wacom_report_key(wcombo, wacom->tool[0], 1); | ||
| 682 | } | ||
| 683 | return; | ||
| 684 | } | ||
| 685 | |||
| 611 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | 686 | static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) |
| 612 | { | 687 | { |
| 688 | struct wacom_features *features = &wacom->features; | ||
| 613 | char *data = wacom->data; | 689 | char *data = wacom->data; |
| 614 | int prox = 0, pressure; | 690 | int prox = 0, pressure, idx = -1; |
| 615 | static int stylusInProx, touchInProx = 1, touchOut; | 691 | static int stylusInProx, touchInProx = 1, touchOut; |
| 616 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; | 692 | struct urb *urb = ((struct wacom_combo *)wcombo)->urb; |
| 617 | 693 | ||
| 618 | dbg("wacom_tpc_irq: received report #%d", data[0]); | 694 | dbg("wacom_tpc_irq: received report #%d", data[0]); |
| 619 | 695 | ||
| 620 | if (urb->actual_length == 5 || data[0] == 6) { /* Touch data */ | 696 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG || /* single touch */ |
| 621 | if (urb->actual_length == 5) { /* with touch */ | 697 | data[0] == WACOM_REPORT_TPC1FG || /* single touch */ |
| 622 | prox = data[0] & 0x03; | 698 | data[0] == WACOM_REPORT_TPC2FG) { /* 2FG touch */ |
| 699 | if (urb->actual_length == WACOM_PKGLEN_TPC1FG) { /* with touch */ | ||
| 700 | prox = data[0] & 0x01; | ||
| 623 | } else { /* with capacity */ | 701 | } else { /* with capacity */ |
| 624 | prox = data[1] & 0x03; | 702 | if (data[0] == WACOM_REPORT_TPC1FG) |
| 703 | /* single touch */ | ||
| 704 | prox = data[1] & 0x01; | ||
| 705 | else | ||
| 706 | /* 2FG touch data */ | ||
| 707 | prox = data[1] & 0x03; | ||
| 625 | } | 708 | } |
| 626 | 709 | ||
| 627 | if (!stylusInProx) { /* stylus not in prox */ | 710 | if (!stylusInProx) { /* stylus not in prox */ |
| 628 | if (prox) { | 711 | if (prox) { |
| 629 | if (touchInProx) { | 712 | if (touchInProx) { |
| 630 | wacom->tool[1] = BTN_TOOL_DOUBLETAP; | 713 | wacom_tpc_touch_in(wacom, wcombo); |
| 631 | wacom->id[0] = TOUCH_DEVICE_ID; | ||
| 632 | if (urb->actual_length != 5) { | ||
| 633 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 634 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 635 | wacom_report_abs(wcombo, ABS_PRESSURE, wacom_le16_to_cpu(&data[6])); | ||
| 636 | wacom_report_key(wcombo, BTN_TOUCH, wacom_le16_to_cpu(&data[6])); | ||
| 637 | } else { | ||
| 638 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[1])); | ||
| 639 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[3])); | ||
| 640 | wacom_report_key(wcombo, BTN_TOUCH, 1); | ||
| 641 | } | ||
| 642 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 643 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | ||
| 644 | touchOut = 1; | 714 | touchOut = 1; |
| 645 | return 1; | 715 | return 1; |
| 646 | } | 716 | } |
| 647 | } else { | 717 | } else { |
| 648 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 718 | /* 2FGT out-prox */ |
| 649 | wacom_report_key(wcombo, wacom->tool[1], prox & 0x01); | 719 | if (data[0] == WACOM_REPORT_TPC2FG) { |
| 650 | wacom_report_key(wcombo, BTN_TOUCH, 0); | 720 | idx = (wacom->id[1] & 0x01) - 1; |
| 721 | if (idx == 0) { | ||
| 722 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
| 723 | /* sync first finger event */ | ||
| 724 | if (wacom->id[1] & 0x02) | ||
| 725 | wacom_input_sync(wcombo); | ||
| 726 | } | ||
| 727 | idx = (wacom->id[1] & 0x02) - 1; | ||
| 728 | if (idx == 1) | ||
| 729 | wacom_tpc_touch_out(wacom, wcombo, idx); | ||
| 730 | } else /* one finger touch */ | ||
| 731 | wacom_tpc_touch_out(wacom, wcombo, 0); | ||
| 651 | touchOut = 0; | 732 | touchOut = 0; |
| 652 | touchInProx = 1; | 733 | touchInProx = 1; |
| 653 | return 1; | 734 | return 1; |
| 654 | } | 735 | } |
| 655 | } else if (touchOut || !prox) { /* force touch out-prox */ | 736 | } else if (touchOut || !prox) { /* force touch out-prox */ |
| 656 | wacom_report_abs(wcombo, ABS_MISC, TOUCH_DEVICE_ID); | 737 | wacom_tpc_touch_out(wacom, wcombo, 0); |
| 657 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
| 658 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 659 | touchOut = 0; | 738 | touchOut = 0; |
| 660 | touchInProx = 1; | 739 | touchInProx = 1; |
| 661 | return 1; | 740 | return 1; |
| 662 | } | 741 | } |
| 663 | } else if (data[0] == 2) { /* Penabled */ | 742 | } else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */ |
| 664 | prox = data[1] & 0x20; | 743 | prox = data[1] & 0x20; |
| 665 | 744 | ||
| 666 | touchInProx = 0; | 745 | touchInProx = 0; |
| 667 | 746 | ||
| 668 | wacom->id[0] = ERASER_DEVICE_ID; | 747 | if (!wacom->id[0]) { /* first in prox */ |
| 669 | 748 | /* Going into proximity select tool */ | |
| 670 | /* | 749 | wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; |
| 671 | * if going from out of proximity into proximity select between the eraser | 750 | if (wacom->tool[0] == BTN_TOOL_PEN) |
| 672 | * and the pen based on the state of the stylus2 button, choose eraser if | ||
| 673 | * pressed else choose pen. if not a proximity change from out to in, send | ||
| 674 | * an out of proximity for previous tool then a in for new tool. | ||
| 675 | */ | ||
| 676 | if (prox) { /* in prox */ | ||
| 677 | if (!wacom->tool[0]) { | ||
| 678 | /* Going into proximity select tool */ | ||
| 679 | wacom->tool[1] = (data[1] & 0x08) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; | ||
| 680 | if (wacom->tool[1] == BTN_TOOL_PEN) | ||
| 681 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
| 682 | } else if (wacom->tool[1] == BTN_TOOL_RUBBER && !(data[1] & 0x08)) { | ||
| 683 | /* | ||
| 684 | * was entered with stylus2 pressed | ||
| 685 | * report out proximity for previous tool | ||
| 686 | */ | ||
| 687 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | ||
| 688 | wacom_report_key(wcombo, wacom->tool[1], 0); | ||
| 689 | wacom_input_sync(wcombo); | ||
| 690 | |||
| 691 | /* set new tool */ | ||
| 692 | wacom->tool[1] = BTN_TOOL_PEN; | ||
| 693 | wacom->id[0] = STYLUS_DEVICE_ID; | 751 | wacom->id[0] = STYLUS_DEVICE_ID; |
| 694 | return 0; | 752 | else |
| 695 | } | 753 | wacom->id[0] = ERASER_DEVICE_ID; |
| 696 | if (wacom->tool[1] != BTN_TOOL_RUBBER) { | ||
| 697 | /* Unknown tool selected default to pen tool */ | ||
| 698 | wacom->tool[1] = BTN_TOOL_PEN; | ||
| 699 | wacom->id[0] = STYLUS_DEVICE_ID; | ||
| 700 | } | ||
| 701 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); | ||
| 702 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | ||
| 703 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 704 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 705 | pressure = ((data[7] & 0x01) << 8) | data[6]; | ||
| 706 | if (pressure < 0) | ||
| 707 | pressure = wacom->features->pressure_max + pressure + 1; | ||
| 708 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | ||
| 709 | wacom_report_key(wcombo, BTN_TOUCH, pressure); | ||
| 710 | } else { | ||
| 711 | wacom_report_abs(wcombo, ABS_PRESSURE, 0); | ||
| 712 | wacom_report_key(wcombo, BTN_STYLUS, 0); | ||
| 713 | wacom_report_key(wcombo, BTN_STYLUS2, 0); | ||
| 714 | wacom_report_key(wcombo, BTN_TOUCH, 0); | ||
| 715 | } | 754 | } |
| 716 | wacom_report_key(wcombo, wacom->tool[1], prox); | 755 | wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); |
| 756 | wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); | ||
| 757 | wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); | ||
| 758 | wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); | ||
| 759 | pressure = ((data[7] & 0x01) << 8) | data[6]; | ||
| 760 | if (pressure < 0) | ||
| 761 | pressure = features->pressure_max + pressure + 1; | ||
| 762 | wacom_report_abs(wcombo, ABS_PRESSURE, pressure); | ||
| 763 | wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); | ||
| 764 | if (!prox) { /* out-prox */ | ||
| 765 | wacom->id[0] = 0; | ||
| 766 | /* pen is out so touch can be enabled now */ | ||
| 767 | touchInProx = 1; | ||
| 768 | } | ||
| 769 | wacom_report_key(wcombo, wacom->tool[0], prox); | ||
| 717 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); | 770 | wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); |
| 718 | stylusInProx = prox; | 771 | stylusInProx = prox; |
| 719 | wacom->tool[0] = prox; | ||
| 720 | return 1; | 772 | return 1; |
| 721 | } | 773 | } |
| 722 | return 0; | 774 | return 0; |
| @@ -724,7 +776,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) | |||
| 724 | 776 | ||
| 725 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | 777 | int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) |
| 726 | { | 778 | { |
| 727 | switch (wacom_wac->features->type) { | 779 | switch (wacom_wac->features.type) { |
| 728 | case PENPARTNER: | 780 | case PENPARTNER: |
| 729 | return wacom_penpartner_irq(wacom_wac, wcombo); | 781 | return wacom_penpartner_irq(wacom_wac, wcombo); |
| 730 | 782 | ||
| @@ -751,6 +803,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
| 751 | return wacom_intuos_irq(wacom_wac, wcombo); | 803 | return wacom_intuos_irq(wacom_wac, wcombo); |
| 752 | 804 | ||
| 753 | case TABLETPC: | 805 | case TABLETPC: |
| 806 | case TABLETPC2FG: | ||
| 754 | return wacom_tpc_irq(wacom_wac, wcombo); | 807 | return wacom_tpc_irq(wacom_wac, wcombo); |
| 755 | 808 | ||
| 756 | default: | 809 | default: |
| @@ -761,7 +814,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) | |||
| 761 | 814 | ||
| 762 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) | 815 | void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) |
| 763 | { | 816 | { |
| 764 | switch (wacom_wac->features->type) { | 817 | switch (wacom_wac->features.type) { |
| 765 | case WACOM_MO: | 818 | case WACOM_MO: |
| 766 | input_dev_mo(input_dev, wacom_wac); | 819 | input_dev_mo(input_dev, wacom_wac); |
| 767 | case WACOM_G4: | 820 | case WACOM_G4: |
| @@ -791,9 +844,17 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 791 | input_dev_i4s(input_dev, wacom_wac); | 844 | input_dev_i4s(input_dev, wacom_wac); |
| 792 | input_dev_i(input_dev, wacom_wac); | 845 | input_dev_i(input_dev, wacom_wac); |
| 793 | break; | 846 | break; |
| 847 | case TABLETPC2FG: | ||
| 848 | input_dev_tpc2fg(input_dev, wacom_wac); | ||
| 849 | /* fall through */ | ||
| 850 | case TABLETPC: | ||
| 851 | input_dev_tpc(input_dev, wacom_wac); | ||
| 852 | if (wacom_wac->features.device_type != BTN_TOOL_PEN) | ||
| 853 | break; /* no need to process stylus stuff */ | ||
| 854 | |||
| 855 | /* fall through */ | ||
| 794 | case PL: | 856 | case PL: |
| 795 | case PTU: | 857 | case PTU: |
| 796 | case TABLETPC: | ||
| 797 | input_dev_pl(input_dev, wacom_wac); | 858 | input_dev_pl(input_dev, wacom_wac); |
| 798 | /* fall through */ | 859 | /* fall through */ |
| 799 | case PENPARTNER: | 860 | case PENPARTNER: |
| @@ -803,147 +864,201 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w | |||
| 803 | return; | 864 | return; |
| 804 | } | 865 | } |
| 805 | 866 | ||
| 806 | static struct wacom_features wacom_features[] = { | 867 | static const struct wacom_features wacom_features_0x00 = |
| 807 | { "Wacom Penpartner", 7, 5040, 3780, 255, 0, PENPARTNER }, | 868 | { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }; |
| 808 | { "Wacom Graphire", 8, 10206, 7422, 511, 63, GRAPHIRE }, | 869 | static const struct wacom_features wacom_features_0x10 = |
| 809 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 63, GRAPHIRE }, | 870 | { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; |
| 810 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 63, GRAPHIRE }, | 871 | static const struct wacom_features wacom_features_0x11 = |
| 811 | { "Wacom Graphire3", 8, 10208, 7424, 511, 63, GRAPHIRE }, | 872 | { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; |
| 812 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 63, GRAPHIRE }, | 873 | static const struct wacom_features wacom_features_0x12 = |
| 813 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 63, WACOM_G4 }, | 874 | { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }; |
| 814 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 63, WACOM_G4 }, | 875 | static const struct wacom_features wacom_features_0x13 = |
| 815 | { "Wacom BambooFun 4x5", 9, 14760, 9225, 511, 63, WACOM_MO }, | 876 | { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }; |
| 816 | { "Wacom BambooFun 6x8", 9, 21648, 13530, 511, 63, WACOM_MO }, | 877 | static const struct wacom_features wacom_features_0x14 = |
| 817 | { "Wacom Bamboo1 Medium",8, 16704, 12064, 511, 63, GRAPHIRE }, | 878 | { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; |
| 818 | { "Wacom Volito", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 879 | static const struct wacom_features wacom_features_0x15 = |
| 819 | { "Wacom PenStation2", 8, 3250, 2320, 255, 63, GRAPHIRE }, | 880 | { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }; |
| 820 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 881 | static const struct wacom_features wacom_features_0x16 = |
| 821 | { "Wacom Volito2 2x3", 8, 3248, 2320, 511, 63, GRAPHIRE }, | 882 | { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }; |
| 822 | { "Wacom PenPartner2", 8, 3250, 2320, 511, 63, GRAPHIRE }, | 883 | static const struct wacom_features wacom_features_0x17 = |
| 823 | { "Wacom Bamboo", 9, 14760, 9225, 511, 63, WACOM_MO }, | 884 | { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; |
| 824 | { "Wacom Bamboo1", 8, 5104, 3712, 511, 63, GRAPHIRE }, | 885 | static const struct wacom_features wacom_features_0x18 = |
| 825 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 886 | { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }; |
| 826 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 887 | static const struct wacom_features wacom_features_0x19 = |
| 827 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | 888 | { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; |
| 828 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | 889 | static const struct wacom_features wacom_features_0x60 = |
| 829 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | 890 | { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; |
| 830 | { "Wacom PL400", 8, 5408, 4056, 255, 0, PL }, | 891 | static const struct wacom_features wacom_features_0x61 = |
| 831 | { "Wacom PL500", 8, 6144, 4608, 255, 0, PL }, | 892 | { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }; |
| 832 | { "Wacom PL600", 8, 6126, 4604, 255, 0, PL }, | 893 | static const struct wacom_features wacom_features_0x62 = |
| 833 | { "Wacom PL600SX", 8, 6260, 5016, 255, 0, PL }, | 894 | { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; |
| 834 | { "Wacom PL550", 8, 6144, 4608, 511, 0, PL }, | 895 | static const struct wacom_features wacom_features_0x63 = |
| 835 | { "Wacom PL800", 8, 7220, 5780, 511, 0, PL }, | 896 | { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }; |
| 836 | { "Wacom PL700", 8, 6758, 5406, 511, 0, PL }, | 897 | static const struct wacom_features wacom_features_0x64 = |
| 837 | { "Wacom PL510", 8, 6282, 4762, 511, 0, PL }, | 898 | { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }; |
| 838 | { "Wacom DTU710", 8, 34080, 27660, 511, 0, PL }, | 899 | static const struct wacom_features wacom_features_0x65 = |
| 839 | { "Wacom DTF521", 8, 6282, 4762, 511, 0, PL }, | 900 | { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; |
| 840 | { "Wacom DTF720", 8, 6858, 5506, 511, 0, PL }, | 901 | static const struct wacom_features wacom_features_0x69 = |
| 841 | { "Wacom DTF720a", 8, 6858, 5506, 511, 0, PL }, | 902 | { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; |
| 842 | { "Wacom Cintiq Partner",8, 20480, 15360, 511, 0, PTU }, | 903 | static const struct wacom_features wacom_features_0x20 = |
| 843 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 31, INTUOS }, | 904 | { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; |
| 844 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 905 | static const struct wacom_features wacom_features_0x21 = |
| 845 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 31, INTUOS }, | 906 | { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; |
| 846 | { "Wacom Intuos2 12x12", 10, 30480, 31680, 1023, 31, INTUOS }, | 907 | static const struct wacom_features wacom_features_0x22 = |
| 847 | { "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 31, INTUOS }, | 908 | { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; |
| 848 | { "Wacom Intuos3 4x5", 10, 25400, 20320, 1023, 63, INTUOS3S }, | 909 | static const struct wacom_features wacom_features_0x23 = |
| 849 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 63, INTUOS3 }, | 910 | { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; |
| 850 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 63, INTUOS3 }, | 911 | static const struct wacom_features wacom_features_0x24 = |
| 851 | { "Wacom Intuos3 12x12", 10, 60960, 60960, 1023, 63, INTUOS3L }, | 912 | { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; |
| 852 | { "Wacom Intuos3 12x19", 10, 97536, 60960, 1023, 63, INTUOS3L }, | 913 | static const struct wacom_features wacom_features_0x30 = |
| 853 | { "Wacom Intuos3 6x11", 10, 54204, 31750, 1023, 63, INTUOS3 }, | 914 | { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }; |
| 854 | { "Wacom Intuos3 4x6", 10, 31496, 19685, 1023, 63, INTUOS3S }, | 915 | static const struct wacom_features wacom_features_0x31 = |
| 855 | { "Wacom Intuos4 4x6", 10, 31496, 19685, 2047, 63, INTUOS4S }, | 916 | { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }; |
| 856 | { "Wacom Intuos4 6x9", 10, 44704, 27940, 2047, 63, INTUOS4 }, | 917 | static const struct wacom_features wacom_features_0x32 = |
| 857 | { "Wacom Intuos4 8x13", 10, 65024, 40640, 2047, 63, INTUOS4L }, | 918 | { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }; |
| 858 | { "Wacom Intuos4 12x19", 10, 97536, 60960, 2047, 63, INTUOS4L }, | 919 | static const struct wacom_features wacom_features_0x33 = |
| 859 | { "Wacom Cintiq 21UX", 10, 87200, 65600, 1023, 63, CINTIQ }, | 920 | { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }; |
| 860 | { "Wacom Cintiq 20WSX", 10, 86680, 54180, 1023, 63, WACOM_BEE }, | 921 | static const struct wacom_features wacom_features_0x34 = |
| 861 | { "Wacom Cintiq 12WX", 10, 53020, 33440, 1023, 63, WACOM_BEE }, | 922 | { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }; |
| 862 | { "Wacom DTU1931", 8, 37832, 30305, 511, 0, PL }, | 923 | static const struct wacom_features wacom_features_0x35 = |
| 863 | { "Wacom ISDv4 90", 8, 26202, 16325, 255, 0, TABLETPC }, | 924 | { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }; |
| 864 | { "Wacom ISDv4 93", 8, 26202, 16325, 255, 0, TABLETPC }, | 925 | static const struct wacom_features wacom_features_0x37 = |
| 865 | { "Wacom ISDv4 9A", 8, 26202, 16325, 255, 0, TABLETPC }, | 926 | { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }; |
| 866 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 31, INTUOS }, | 927 | static const struct wacom_features wacom_features_0x38 = |
| 928 | { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; | ||
| 929 | static const struct wacom_features wacom_features_0x39 = | ||
| 930 | { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }; | ||
| 931 | static const struct wacom_features wacom_features_0xC4 = | ||
| 932 | { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; | ||
| 933 | static const struct wacom_features wacom_features_0xC0 = | ||
| 934 | { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; | ||
| 935 | static const struct wacom_features wacom_features_0xC2 = | ||
| 936 | { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; | ||
| 937 | static const struct wacom_features wacom_features_0x03 = | ||
| 938 | { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }; | ||
| 939 | static const struct wacom_features wacom_features_0x41 = | ||
| 940 | { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; | ||
| 941 | static const struct wacom_features wacom_features_0x42 = | ||
| 942 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | ||
| 943 | static const struct wacom_features wacom_features_0x43 = | ||
| 944 | { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; | ||
| 945 | static const struct wacom_features wacom_features_0x44 = | ||
| 946 | { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; | ||
| 947 | static const struct wacom_features wacom_features_0x45 = | ||
| 948 | { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; | ||
| 949 | static const struct wacom_features wacom_features_0xB0 = | ||
| 950 | { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }; | ||
| 951 | static const struct wacom_features wacom_features_0xB1 = | ||
| 952 | { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }; | ||
| 953 | static const struct wacom_features wacom_features_0xB2 = | ||
| 954 | { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }; | ||
| 955 | static const struct wacom_features wacom_features_0xB3 = | ||
| 956 | { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }; | ||
| 957 | static const struct wacom_features wacom_features_0xB4 = | ||
| 958 | { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }; | ||
| 959 | static const struct wacom_features wacom_features_0xB5 = | ||
| 960 | { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }; | ||
| 961 | static const struct wacom_features wacom_features_0xB7 = | ||
| 962 | { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }; | ||
| 963 | static const struct wacom_features wacom_features_0xB8 = | ||
| 964 | { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }; | ||
| 965 | static const struct wacom_features wacom_features_0xB9 = | ||
| 966 | { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }; | ||
| 967 | static const struct wacom_features wacom_features_0xBA = | ||
| 968 | { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; | ||
| 969 | static const struct wacom_features wacom_features_0xBB = | ||
| 970 | { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; | ||
| 971 | static const struct wacom_features wacom_features_0x3F = | ||
| 972 | { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; | ||
| 973 | static const struct wacom_features wacom_features_0xC5 = | ||
| 974 | { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }; | ||
| 975 | static const struct wacom_features wacom_features_0xC6 = | ||
| 976 | { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; | ||
| 977 | static const struct wacom_features wacom_features_0xC7 = | ||
| 978 | { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; | ||
| 979 | static const struct wacom_features wacom_features_0x90 = | ||
| 980 | { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | ||
| 981 | static const struct wacom_features wacom_features_0x93 = | ||
| 982 | { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | ||
| 983 | static const struct wacom_features wacom_features_0x9A = | ||
| 984 | { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | ||
| 985 | static const struct wacom_features wacom_features_0x9F = | ||
| 986 | { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; | ||
| 987 | static const struct wacom_features wacom_features_0xE2 = | ||
| 988 | { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; | ||
| 989 | static const struct wacom_features wacom_features_0xE3 = | ||
| 990 | { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; | ||
| 991 | static const struct wacom_features wacom_features_0x47 = | ||
| 992 | { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; | ||
| 993 | |||
| 994 | #define USB_DEVICE_WACOM(prod) \ | ||
| 995 | USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ | ||
| 996 | .driver_info = (kernel_ulong_t)&wacom_features_##prod | ||
| 997 | |||
| 998 | const struct usb_device_id wacom_ids[] = { | ||
| 999 | { USB_DEVICE_WACOM(0x00) }, | ||
| 1000 | { USB_DEVICE_WACOM(0x10) }, | ||
| 1001 | { USB_DEVICE_WACOM(0x11) }, | ||
| 1002 | { USB_DEVICE_WACOM(0x12) }, | ||
| 1003 | { USB_DEVICE_WACOM(0x13) }, | ||
| 1004 | { USB_DEVICE_WACOM(0x14) }, | ||
| 1005 | { USB_DEVICE_WACOM(0x15) }, | ||
| 1006 | { USB_DEVICE_WACOM(0x16) }, | ||
| 1007 | { USB_DEVICE_WACOM(0x17) }, | ||
| 1008 | { USB_DEVICE_WACOM(0x18) }, | ||
| 1009 | { USB_DEVICE_WACOM(0x19) }, | ||
| 1010 | { USB_DEVICE_WACOM(0x60) }, | ||
| 1011 | { USB_DEVICE_WACOM(0x61) }, | ||
| 1012 | { USB_DEVICE_WACOM(0x62) }, | ||
| 1013 | { USB_DEVICE_WACOM(0x63) }, | ||
| 1014 | { USB_DEVICE_WACOM(0x64) }, | ||
| 1015 | { USB_DEVICE_WACOM(0x65) }, | ||
| 1016 | { USB_DEVICE_WACOM(0x69) }, | ||
| 1017 | { USB_DEVICE_WACOM(0x20) }, | ||
| 1018 | { USB_DEVICE_WACOM(0x21) }, | ||
| 1019 | { USB_DEVICE_WACOM(0x22) }, | ||
| 1020 | { USB_DEVICE_WACOM(0x23) }, | ||
| 1021 | { USB_DEVICE_WACOM(0x24) }, | ||
| 1022 | { USB_DEVICE_WACOM(0x30) }, | ||
| 1023 | { USB_DEVICE_WACOM(0x31) }, | ||
| 1024 | { USB_DEVICE_WACOM(0x32) }, | ||
| 1025 | { USB_DEVICE_WACOM(0x33) }, | ||
| 1026 | { USB_DEVICE_WACOM(0x34) }, | ||
| 1027 | { USB_DEVICE_WACOM(0x35) }, | ||
| 1028 | { USB_DEVICE_WACOM(0x37) }, | ||
| 1029 | { USB_DEVICE_WACOM(0x38) }, | ||
| 1030 | { USB_DEVICE_WACOM(0x39) }, | ||
| 1031 | { USB_DEVICE_WACOM(0xC4) }, | ||
| 1032 | { USB_DEVICE_WACOM(0xC0) }, | ||
| 1033 | { USB_DEVICE_WACOM(0xC2) }, | ||
| 1034 | { USB_DEVICE_WACOM(0x03) }, | ||
| 1035 | { USB_DEVICE_WACOM(0x41) }, | ||
| 1036 | { USB_DEVICE_WACOM(0x42) }, | ||
| 1037 | { USB_DEVICE_WACOM(0x43) }, | ||
| 1038 | { USB_DEVICE_WACOM(0x44) }, | ||
| 1039 | { USB_DEVICE_WACOM(0x45) }, | ||
| 1040 | { USB_DEVICE_WACOM(0xB0) }, | ||
| 1041 | { USB_DEVICE_WACOM(0xB1) }, | ||
| 1042 | { USB_DEVICE_WACOM(0xB2) }, | ||
| 1043 | { USB_DEVICE_WACOM(0xB3) }, | ||
| 1044 | { USB_DEVICE_WACOM(0xB4) }, | ||
| 1045 | { USB_DEVICE_WACOM(0xB5) }, | ||
| 1046 | { USB_DEVICE_WACOM(0xB7) }, | ||
| 1047 | { USB_DEVICE_WACOM(0xB8) }, | ||
| 1048 | { USB_DEVICE_WACOM(0xB9) }, | ||
| 1049 | { USB_DEVICE_WACOM(0xBA) }, | ||
| 1050 | { USB_DEVICE_WACOM(0xBB) }, | ||
| 1051 | { USB_DEVICE_WACOM(0x3F) }, | ||
| 1052 | { USB_DEVICE_WACOM(0xC5) }, | ||
| 1053 | { USB_DEVICE_WACOM(0xC6) }, | ||
| 1054 | { USB_DEVICE_WACOM(0xC7) }, | ||
| 1055 | { USB_DEVICE_WACOM(0x90) }, | ||
| 1056 | { USB_DEVICE_WACOM(0x93) }, | ||
| 1057 | { USB_DEVICE_WACOM(0x9A) }, | ||
| 1058 | { USB_DEVICE_WACOM(0x9F) }, | ||
| 1059 | { USB_DEVICE_WACOM(0xE2) }, | ||
| 1060 | { USB_DEVICE_WACOM(0xE3) }, | ||
| 1061 | { USB_DEVICE_WACOM(0x47) }, | ||
| 867 | { } | 1062 | { } |
| 868 | }; | 1063 | }; |
| 869 | |||
| 870 | static struct usb_device_id wacom_ids[] = { | ||
| 871 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x00) }, | ||
| 872 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10) }, | ||
| 873 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x11) }, | ||
| 874 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x12) }, | ||
| 875 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x13) }, | ||
| 876 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x14) }, | ||
| 877 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x15) }, | ||
| 878 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x16) }, | ||
| 879 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x17) }, | ||
| 880 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x18) }, | ||
| 881 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x19) }, | ||
| 882 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) }, | ||
| 883 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x61) }, | ||
| 884 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x62) }, | ||
| 885 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x63) }, | ||
| 886 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x64) }, | ||
| 887 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x65) }, | ||
| 888 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x69) }, | ||
| 889 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20) }, | ||
| 890 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21) }, | ||
| 891 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22) }, | ||
| 892 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23) }, | ||
| 893 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24) }, | ||
| 894 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x30) }, | ||
| 895 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31) }, | ||
| 896 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x32) }, | ||
| 897 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x33) }, | ||
| 898 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x34) }, | ||
| 899 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x35) }, | ||
| 900 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x37) }, | ||
| 901 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x38) }, | ||
| 902 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x39) }, | ||
| 903 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC4) }, | ||
| 904 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC0) }, | ||
| 905 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC2) }, | ||
| 906 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) }, | ||
| 907 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x41) }, | ||
| 908 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x42) }, | ||
| 909 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x43) }, | ||
| 910 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x44) }, | ||
| 911 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) }, | ||
| 912 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) }, | ||
| 913 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) }, | ||
| 914 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) }, | ||
| 915 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB3) }, | ||
| 916 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB4) }, | ||
| 917 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB5) }, | ||
| 918 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB7) }, | ||
| 919 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB8) }, | ||
| 920 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB9) }, | ||
| 921 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBA) }, | ||
| 922 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xBB) }, | ||
| 923 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x3F) }, | ||
| 924 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC5) }, | ||
| 925 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC6) }, | ||
| 926 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0xC7) }, | ||
| 927 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x90) }, | ||
| 928 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x93) }, | ||
| 929 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x9A) }, | ||
| 930 | { USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) }, | ||
| 931 | { } | ||
| 932 | }; | ||
| 933 | |||
| 934 | const struct usb_device_id *get_device_table(void) | ||
| 935 | { | ||
| 936 | const struct usb_device_id *id_table = wacom_ids; | ||
| 937 | |||
| 938 | return id_table; | ||
| 939 | } | ||
| 940 | |||
| 941 | struct wacom_features * get_wacom_feature(const struct usb_device_id *id) | ||
| 942 | { | ||
| 943 | int index = id - wacom_ids; | ||
| 944 | struct wacom_features *wf = &wacom_features[index]; | ||
| 945 | |||
| 946 | return wf; | ||
| 947 | } | ||
| 948 | |||
| 949 | MODULE_DEVICE_TABLE(usb, wacom_ids); | 1064 | MODULE_DEVICE_TABLE(usb, wacom_ids); |
diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index c10235aba7e5..b50cf04e61a8 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h | |||
| @@ -9,12 +9,32 @@ | |||
| 9 | #ifndef WACOM_WAC_H | 9 | #ifndef WACOM_WAC_H |
| 10 | #define WACOM_WAC_H | 10 | #define WACOM_WAC_H |
| 11 | 11 | ||
| 12 | /* maximum packet length for USB devices */ | ||
| 13 | #define WACOM_PKGLEN_MAX 32 | ||
| 14 | |||
| 15 | /* packet length for individual models */ | ||
| 16 | #define WACOM_PKGLEN_PENPRTN 7 | ||
| 17 | #define WACOM_PKGLEN_GRAPHIRE 8 | ||
| 18 | #define WACOM_PKGLEN_BBFUN 9 | ||
| 19 | #define WACOM_PKGLEN_INTUOS 10 | ||
| 20 | #define WACOM_PKGLEN_TPC1FG 5 | ||
| 21 | #define WACOM_PKGLEN_TPC2FG 14 | ||
| 22 | |||
| 23 | /* device IDs */ | ||
| 12 | #define STYLUS_DEVICE_ID 0x02 | 24 | #define STYLUS_DEVICE_ID 0x02 |
| 13 | #define TOUCH_DEVICE_ID 0x03 | 25 | #define TOUCH_DEVICE_ID 0x03 |
| 14 | #define CURSOR_DEVICE_ID 0x06 | 26 | #define CURSOR_DEVICE_ID 0x06 |
| 15 | #define ERASER_DEVICE_ID 0x0A | 27 | #define ERASER_DEVICE_ID 0x0A |
| 16 | #define PAD_DEVICE_ID 0x0F | 28 | #define PAD_DEVICE_ID 0x0F |
| 17 | 29 | ||
| 30 | /* wacom data packet report IDs */ | ||
| 31 | #define WACOM_REPORT_PENABLED 2 | ||
| 32 | #define WACOM_REPORT_INTUOSREAD 5 | ||
| 33 | #define WACOM_REPORT_INTUOSWRITE 6 | ||
| 34 | #define WACOM_REPORT_INTUOSPAD 12 | ||
| 35 | #define WACOM_REPORT_TPC1FG 6 | ||
| 36 | #define WACOM_REPORT_TPC2FG 13 | ||
| 37 | |||
| 18 | enum { | 38 | enum { |
| 19 | PENPARTNER = 0, | 39 | PENPARTNER = 0, |
| 20 | GRAPHIRE, | 40 | GRAPHIRE, |
| @@ -32,27 +52,32 @@ enum { | |||
| 32 | WACOM_BEE, | 52 | WACOM_BEE, |
| 33 | WACOM_MO, | 53 | WACOM_MO, |
| 34 | TABLETPC, | 54 | TABLETPC, |
| 55 | TABLETPC2FG, | ||
| 35 | MAX_TYPE | 56 | MAX_TYPE |
| 36 | }; | 57 | }; |
| 37 | 58 | ||
| 38 | struct wacom_features { | 59 | struct wacom_features { |
| 39 | char *name; | 60 | const char *name; |
| 40 | int pktlen; | 61 | int pktlen; |
| 41 | int x_max; | 62 | int x_max; |
| 42 | int y_max; | 63 | int y_max; |
| 43 | int pressure_max; | 64 | int pressure_max; |
| 44 | int distance_max; | 65 | int distance_max; |
| 45 | int type; | 66 | int type; |
| 46 | int touch_x_max; | 67 | int device_type; |
| 47 | int touch_y_max; | 68 | int x_phy; |
| 69 | int y_phy; | ||
| 70 | unsigned char unit; | ||
| 71 | unsigned char unitExpo; | ||
| 48 | }; | 72 | }; |
| 49 | 73 | ||
| 50 | struct wacom_wac { | 74 | struct wacom_wac { |
| 75 | char name[64]; | ||
| 51 | unsigned char *data; | 76 | unsigned char *data; |
| 52 | int tool[2]; | 77 | int tool[2]; |
| 53 | int id[2]; | 78 | int id[2]; |
| 54 | __u32 serial[2]; | 79 | __u32 serial[2]; |
| 55 | struct wacom_features *features; | 80 | struct wacom_features features; |
| 56 | }; | 81 | }; |
| 57 | 82 | ||
| 58 | #endif | 83 | #endif |
diff --git a/drivers/input/touchscreen/88pm860x-ts.c b/drivers/input/touchscreen/88pm860x-ts.c new file mode 100644 index 000000000000..b3aebc2166ba --- /dev/null +++ b/drivers/input/touchscreen/88pm860x-ts.c | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | /* | ||
| 2 | * Touchscreen driver for Marvell 88PM860x | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Marvell International Ltd. | ||
| 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
| 6 | * | ||
| 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 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/i2c.h> | ||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/mfd/88pm860x.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | |||
| 19 | #define MEAS_LEN (8) | ||
| 20 | #define ACCURATE_BIT (12) | ||
| 21 | |||
| 22 | /* touch register */ | ||
| 23 | #define MEAS_EN3 (0x52) | ||
| 24 | |||
| 25 | #define MEAS_TSIX_1 (0x8D) | ||
| 26 | #define MEAS_TSIX_2 (0x8E) | ||
| 27 | #define MEAS_TSIY_1 (0x8F) | ||
| 28 | #define MEAS_TSIY_2 (0x90) | ||
| 29 | #define MEAS_TSIZ1_1 (0x91) | ||
| 30 | #define MEAS_TSIZ1_2 (0x92) | ||
| 31 | #define MEAS_TSIZ2_1 (0x93) | ||
| 32 | #define MEAS_TSIZ2_2 (0x94) | ||
| 33 | |||
| 34 | /* bit definitions of touch */ | ||
| 35 | #define MEAS_PD_EN (1 << 3) | ||
| 36 | #define MEAS_TSIX_EN (1 << 4) | ||
| 37 | #define MEAS_TSIY_EN (1 << 5) | ||
| 38 | #define MEAS_TSIZ1_EN (1 << 6) | ||
| 39 | #define MEAS_TSIZ2_EN (1 << 7) | ||
| 40 | |||
| 41 | struct pm860x_touch { | ||
| 42 | struct input_dev *idev; | ||
| 43 | struct i2c_client *i2c; | ||
| 44 | struct pm860x_chip *chip; | ||
| 45 | int irq; | ||
| 46 | int res_x; /* resistor of Xplate */ | ||
| 47 | }; | ||
| 48 | |||
| 49 | static irqreturn_t pm860x_touch_handler(int irq, void *data) | ||
| 50 | { | ||
| 51 | struct pm860x_touch *touch = data; | ||
| 52 | struct pm860x_chip *chip = touch->chip; | ||
| 53 | unsigned char buf[MEAS_LEN]; | ||
| 54 | int x, y, pen_down; | ||
| 55 | int z1, z2, rt = 0; | ||
| 56 | int ret; | ||
| 57 | |||
| 58 | ret = pm860x_bulk_read(touch->i2c, MEAS_TSIX_1, MEAS_LEN, buf); | ||
| 59 | if (ret < 0) | ||
| 60 | goto out; | ||
| 61 | |||
| 62 | pen_down = buf[1] & (1 << 6); | ||
| 63 | x = ((buf[0] & 0xFF) << 4) | (buf[1] & 0x0F); | ||
| 64 | y = ((buf[2] & 0xFF) << 4) | (buf[3] & 0x0F); | ||
| 65 | z1 = ((buf[4] & 0xFF) << 4) | (buf[5] & 0x0F); | ||
| 66 | z2 = ((buf[6] & 0xFF) << 4) | (buf[7] & 0x0F); | ||
| 67 | |||
| 68 | if (pen_down) { | ||
| 69 | if ((x != 0) && (z1 != 0) && (touch->res_x != 0)) { | ||
| 70 | rt = z2 / z1 - 1; | ||
| 71 | rt = (rt * touch->res_x * x) >> ACCURATE_BIT; | ||
| 72 | dev_dbg(chip->dev, "z1:%d, z2:%d, rt:%d\n", | ||
| 73 | z1, z2, rt); | ||
| 74 | } | ||
| 75 | input_report_abs(touch->idev, ABS_X, x); | ||
| 76 | input_report_abs(touch->idev, ABS_Y, y); | ||
| 77 | input_report_abs(touch->idev, ABS_PRESSURE, rt); | ||
| 78 | input_report_key(touch->idev, BTN_TOUCH, 1); | ||
| 79 | dev_dbg(chip->dev, "pen down at [%d, %d].\n", x, y); | ||
| 80 | } else { | ||
| 81 | input_report_abs(touch->idev, ABS_PRESSURE, 0); | ||
| 82 | input_report_key(touch->idev, BTN_TOUCH, 0); | ||
| 83 | dev_dbg(chip->dev, "pen release\n"); | ||
| 84 | } | ||
| 85 | input_sync(touch->idev); | ||
| 86 | |||
| 87 | out: | ||
| 88 | return IRQ_HANDLED; | ||
| 89 | } | ||
| 90 | |||
| 91 | static int pm860x_touch_open(struct input_dev *dev) | ||
| 92 | { | ||
| 93 | struct pm860x_touch *touch = input_get_drvdata(dev); | ||
| 94 | int data, ret; | ||
| 95 | |||
| 96 | data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN | ||
| 97 | | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN; | ||
| 98 | ret = pm860x_set_bits(touch->i2c, MEAS_EN3, data, data); | ||
| 99 | if (ret < 0) | ||
| 100 | goto out; | ||
| 101 | return 0; | ||
| 102 | out: | ||
| 103 | return ret; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void pm860x_touch_close(struct input_dev *dev) | ||
| 107 | { | ||
| 108 | struct pm860x_touch *touch = input_get_drvdata(dev); | ||
| 109 | int data; | ||
| 110 | |||
| 111 | data = MEAS_PD_EN | MEAS_TSIX_EN | MEAS_TSIY_EN | ||
| 112 | | MEAS_TSIZ1_EN | MEAS_TSIZ2_EN; | ||
| 113 | pm860x_set_bits(touch->i2c, MEAS_EN3, data, 0); | ||
| 114 | } | ||
| 115 | |||
| 116 | static int __devinit pm860x_touch_probe(struct platform_device *pdev) | ||
| 117 | { | ||
| 118 | struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
| 119 | struct pm860x_platform_data *pm860x_pdata = \ | ||
| 120 | pdev->dev.parent->platform_data; | ||
| 121 | struct pm860x_touch_pdata *pdata = NULL; | ||
| 122 | struct pm860x_touch *touch; | ||
| 123 | int irq, ret; | ||
| 124 | |||
| 125 | irq = platform_get_irq(pdev, 0); | ||
| 126 | if (irq < 0) { | ||
| 127 | dev_err(&pdev->dev, "No IRQ resource!\n"); | ||
| 128 | return -EINVAL; | ||
| 129 | } | ||
| 130 | |||
| 131 | if (!pm860x_pdata) { | ||
| 132 | dev_err(&pdev->dev, "platform data is missing\n"); | ||
| 133 | return -EINVAL; | ||
| 134 | } | ||
| 135 | |||
| 136 | pdata = pm860x_pdata->touch; | ||
| 137 | if (!pdata) { | ||
| 138 | dev_err(&pdev->dev, "touchscreen data is missing\n"); | ||
| 139 | return -EINVAL; | ||
| 140 | } | ||
| 141 | |||
| 142 | touch = kzalloc(sizeof(struct pm860x_touch), GFP_KERNEL); | ||
| 143 | if (touch == NULL) | ||
| 144 | return -ENOMEM; | ||
| 145 | dev_set_drvdata(&pdev->dev, touch); | ||
| 146 | |||
| 147 | touch->idev = input_allocate_device(); | ||
| 148 | if (touch->idev == NULL) { | ||
| 149 | dev_err(&pdev->dev, "Failed to allocate input device!\n"); | ||
| 150 | ret = -ENOMEM; | ||
| 151 | goto out; | ||
| 152 | } | ||
| 153 | |||
| 154 | touch->idev->name = "88pm860x-touch"; | ||
| 155 | touch->idev->phys = "88pm860x/input0"; | ||
| 156 | touch->idev->id.bustype = BUS_I2C; | ||
| 157 | touch->idev->dev.parent = &pdev->dev; | ||
| 158 | touch->idev->open = pm860x_touch_open; | ||
| 159 | touch->idev->close = pm860x_touch_close; | ||
| 160 | touch->chip = chip; | ||
| 161 | touch->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | ||
| 162 | touch->irq = irq + chip->irq_base; | ||
| 163 | touch->res_x = pdata->res_x; | ||
| 164 | input_set_drvdata(touch->idev, touch); | ||
| 165 | |||
| 166 | ret = request_threaded_irq(touch->irq, NULL, pm860x_touch_handler, | ||
| 167 | IRQF_ONESHOT, "touch", touch); | ||
| 168 | if (ret < 0) | ||
| 169 | goto out_irq; | ||
| 170 | |||
| 171 | __set_bit(EV_ABS, touch->idev->evbit); | ||
| 172 | __set_bit(ABS_X, touch->idev->absbit); | ||
| 173 | __set_bit(ABS_Y, touch->idev->absbit); | ||
| 174 | __set_bit(ABS_PRESSURE, touch->idev->absbit); | ||
| 175 | __set_bit(EV_SYN, touch->idev->evbit); | ||
| 176 | __set_bit(EV_KEY, touch->idev->evbit); | ||
| 177 | __set_bit(BTN_TOUCH, touch->idev->keybit); | ||
| 178 | |||
| 179 | input_set_abs_params(touch->idev, ABS_X, 0, 1 << ACCURATE_BIT, 0, 0); | ||
| 180 | input_set_abs_params(touch->idev, ABS_Y, 0, 1 << ACCURATE_BIT, 0, 0); | ||
| 181 | input_set_abs_params(touch->idev, ABS_PRESSURE, 0, 1 << ACCURATE_BIT, | ||
| 182 | 0, 0); | ||
| 183 | |||
| 184 | ret = input_register_device(touch->idev); | ||
| 185 | if (ret < 0) { | ||
| 186 | dev_err(chip->dev, "Failed to register touch!\n"); | ||
| 187 | goto out_rg; | ||
| 188 | } | ||
| 189 | |||
| 190 | platform_set_drvdata(pdev, touch); | ||
| 191 | return 0; | ||
| 192 | out_rg: | ||
| 193 | free_irq(touch->irq, touch); | ||
| 194 | out_irq: | ||
| 195 | input_free_device(touch->idev); | ||
| 196 | out: | ||
| 197 | kfree(touch); | ||
| 198 | return ret; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int __devexit pm860x_touch_remove(struct platform_device *pdev) | ||
| 202 | { | ||
| 203 | struct pm860x_touch *touch = platform_get_drvdata(pdev); | ||
| 204 | |||
| 205 | input_unregister_device(touch->idev); | ||
| 206 | free_irq(touch->irq, touch); | ||
| 207 | platform_set_drvdata(pdev, NULL); | ||
| 208 | kfree(touch); | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | static struct platform_driver pm860x_touch_driver = { | ||
| 213 | .driver = { | ||
| 214 | .name = "88pm860x-touch", | ||
| 215 | .owner = THIS_MODULE, | ||
| 216 | }, | ||
| 217 | .probe = pm860x_touch_probe, | ||
| 218 | .remove = __devexit_p(pm860x_touch_remove), | ||
| 219 | }; | ||
| 220 | |||
| 221 | static int __init pm860x_touch_init(void) | ||
| 222 | { | ||
| 223 | return platform_driver_register(&pm860x_touch_driver); | ||
| 224 | } | ||
| 225 | module_init(pm860x_touch_init); | ||
| 226 | |||
| 227 | static void __exit pm860x_touch_exit(void) | ||
| 228 | { | ||
| 229 | platform_driver_unregister(&pm860x_touch_driver); | ||
| 230 | } | ||
| 231 | module_exit(pm860x_touch_exit); | ||
| 232 | |||
| 233 | MODULE_DESCRIPTION("Touchscreen driver for Marvell Semiconductor 88PM860x"); | ||
| 234 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
| 235 | MODULE_LICENSE("GPL"); | ||
| 236 | MODULE_ALIAS("platform:88pm860x-touch"); | ||
| 237 | |||
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 8cc453c85ea7..8a8fa4d2d6a8 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -11,18 +11,31 @@ menuconfig INPUT_TOUCHSCREEN | |||
| 11 | 11 | ||
| 12 | if INPUT_TOUCHSCREEN | 12 | if INPUT_TOUCHSCREEN |
| 13 | 13 | ||
| 14 | config TOUCHSCREEN_88PM860X | ||
| 15 | tristate "Marvell 88PM860x touchscreen" | ||
| 16 | depends on MFD_88PM860X | ||
| 17 | help | ||
| 18 | Say Y here if you have a 88PM860x PMIC and want to enable | ||
| 19 | support for the built-in touchscreen. | ||
| 20 | |||
| 21 | If unsure, say N. | ||
| 22 | |||
| 23 | To compile this driver as a module, choose M here: the | ||
| 24 | module will be called 88pm860x-ts. | ||
| 25 | |||
| 14 | config TOUCHSCREEN_ADS7846 | 26 | config TOUCHSCREEN_ADS7846 |
| 15 | tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" | 27 | tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens" |
| 16 | depends on SPI_MASTER | 28 | depends on SPI_MASTER |
| 17 | depends on HWMON = n || HWMON | 29 | depends on HWMON = n || HWMON |
| 18 | help | 30 | help |
| 19 | Say Y here if you have a touchscreen interface using the | 31 | Say Y here if you have a touchscreen interface using the |
| 20 | ADS7846/TSC2046 or ADS7843 controller, and your board-specific | 32 | ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller, |
| 21 | setup code includes that in its table of SPI devices. | 33 | and your board-specific setup code includes that in its |
| 34 | table of SPI devices. | ||
| 22 | 35 | ||
| 23 | If HWMON is selected, and the driver is told the reference voltage | 36 | If HWMON is selected, and the driver is told the reference voltage |
| 24 | on your board, you will also get hwmon interfaces for the voltage | 37 | on your board, you will also get hwmon interfaces for the voltage |
| 25 | (and on ads7846/tsc2046, temperature) sensors of this chip. | 38 | (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip. |
| 26 | 39 | ||
| 27 | If unsure, say N (but it's safe to say "Y"). | 40 | If unsure, say N (but it's safe to say "Y"). |
| 28 | 41 | ||
| @@ -90,7 +103,6 @@ config TOUCHSCREEN_CORGI | |||
| 90 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" | 103 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" |
| 91 | depends on PXA_SHARPSL | 104 | depends on PXA_SHARPSL |
| 92 | select CORGI_SSP_DEPRECATED | 105 | select CORGI_SSP_DEPRECATED |
| 93 | default y | ||
| 94 | help | 106 | help |
| 95 | Say Y here to enable the driver for the touchscreen on the | 107 | Say Y here to enable the driver for the touchscreen on the |
| 96 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. | 108 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. |
| @@ -111,6 +123,18 @@ config TOUCHSCREEN_DA9034 | |||
| 111 | Say Y here to enable the support for the touchscreen found | 123 | Say Y here to enable the support for the touchscreen found |
| 112 | on Dialog Semiconductor DA9034 PMIC. | 124 | on Dialog Semiconductor DA9034 PMIC. |
| 113 | 125 | ||
| 126 | config TOUCHSCREEN_DYNAPRO | ||
| 127 | tristate "Dynapro serial touchscreen" | ||
| 128 | select SERIO | ||
| 129 | help | ||
| 130 | Say Y here if you have a Dynapro serial touchscreen connected to | ||
| 131 | your system. | ||
| 132 | |||
| 133 | If unsure, say N. | ||
| 134 | |||
| 135 | To compile this driver as a module, choose M here: the | ||
| 136 | module will be called dynapro. | ||
| 137 | |||
| 114 | config TOUCHSCREEN_EETI | 138 | config TOUCHSCREEN_EETI |
| 115 | tristate "EETI touchscreen panel support" | 139 | tristate "EETI touchscreen panel support" |
| 116 | depends on I2C | 140 | depends on I2C |
| @@ -133,6 +157,18 @@ config TOUCHSCREEN_FUJITSU | |||
| 133 | To compile this driver as a module, choose M here: the | 157 | To compile this driver as a module, choose M here: the |
| 134 | module will be called fujitsu-ts. | 158 | module will be called fujitsu-ts. |
| 135 | 159 | ||
| 160 | config TOUCHSCREEN_S3C2410 | ||
| 161 | tristate "Samsung S3C2410 touchscreen input driver" | ||
| 162 | depends on ARCH_S3C2410 | ||
| 163 | select S3C24XX_ADC | ||
| 164 | help | ||
| 165 | Say Y here if you have the s3c2410 touchscreen. | ||
| 166 | |||
| 167 | If unsure, say N. | ||
| 168 | |||
| 169 | To compile this driver as a module, choose M here: the | ||
| 170 | module will be called s3c2410_ts. | ||
| 171 | |||
| 136 | config TOUCHSCREEN_GUNZE | 172 | config TOUCHSCREEN_GUNZE |
| 137 | tristate "Gunze AHL-51S touchscreen" | 173 | tristate "Gunze AHL-51S touchscreen" |
| 138 | select SERIO | 174 | select SERIO |
| @@ -297,7 +333,7 @@ config TOUCHSCREEN_TOUCHWIN | |||
| 297 | 333 | ||
| 298 | config TOUCHSCREEN_ATMEL_TSADCC | 334 | config TOUCHSCREEN_ATMEL_TSADCC |
| 299 | tristate "Atmel Touchscreen Interface" | 335 | tristate "Atmel Touchscreen Interface" |
| 300 | depends on ARCH_AT91SAM9RL | 336 | depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 |
| 301 | help | 337 | help |
| 302 | Say Y here if you have a 4-wire touchscreen connected to the | 338 | Say Y here if you have a 4-wire touchscreen connected to the |
| 303 | ADC Controller on your Atmel SoC (such as the AT91SAM9RL). | 339 | ADC Controller on your Atmel SoC (such as the AT91SAM9RL). |
| @@ -418,6 +454,7 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 418 | - IdealTEK URTC1000 | 454 | - IdealTEK URTC1000 |
| 419 | - GoTop Super_Q2/GogoPen/PenPower tablets | 455 | - GoTop Super_Q2/GogoPen/PenPower tablets |
| 420 | - JASTEC USB Touch Controller/DigiTech DTR-02U | 456 | - JASTEC USB Touch Controller/DigiTech DTR-02U |
| 457 | - Zytronic controllers | ||
| 421 | 458 | ||
| 422 | Have a look at <http://linux.chapter7.ch/touchkit/> for | 459 | Have a look at <http://linux.chapter7.ch/touchkit/> for |
| 423 | a usage description and the required user-space stuff. | 460 | a usage description and the required user-space stuff. |
| @@ -425,6 +462,18 @@ config TOUCHSCREEN_USB_COMPOSITE | |||
| 425 | To compile this driver as a module, choose M here: the | 462 | To compile this driver as a module, choose M here: the |
| 426 | module will be called usbtouchscreen. | 463 | module will be called usbtouchscreen. |
| 427 | 464 | ||
| 465 | config TOUCHSCREEN_MC13783 | ||
| 466 | tristate "Freescale MC13783 touchscreen input driver" | ||
| 467 | depends on MFD_MC13783 | ||
| 468 | help | ||
| 469 | Say Y here if you have an Freescale MC13783 PMIC on your | ||
| 470 | board and want to use its touchscreen | ||
| 471 | |||
| 472 | If unsure, say N. | ||
| 473 | |||
| 474 | To compile this driver as a module, choose M here: the | ||
| 475 | module will be called mc13783_ts. | ||
| 476 | |||
| 428 | config TOUCHSCREEN_USB_EGALAX | 477 | config TOUCHSCREEN_USB_EGALAX |
| 429 | default y | 478 | default y |
| 430 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED | 479 | bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED |
| @@ -490,6 +539,21 @@ config TOUCHSCREEN_USB_E2I | |||
| 490 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" | 539 | bool "e2i Touchscreen controller (e.g. from Mimo 740)" |
| 491 | depends on TOUCHSCREEN_USB_COMPOSITE | 540 | depends on TOUCHSCREEN_USB_COMPOSITE |
| 492 | 541 | ||
| 542 | config TOUCHSCREEN_USB_ZYTRONIC | ||
| 543 | default y | ||
| 544 | bool "Zytronic controller" if EMBEDDED | ||
| 545 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 546 | |||
| 547 | config TOUCHSCREEN_USB_ETT_TC5UH | ||
| 548 | default y | ||
| 549 | bool "ET&T TC5UH touchscreen controler support" if EMBEDDED | ||
| 550 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 551 | |||
| 552 | config TOUCHSCREEN_USB_NEXIO | ||
| 553 | default y | ||
| 554 | bool "NEXIO/iNexio device support" if EMBEDDED | ||
| 555 | depends on TOUCHSCREEN_USB_COMPOSITE | ||
| 556 | |||
| 493 | config TOUCHSCREEN_TOUCHIT213 | 557 | config TOUCHSCREEN_TOUCHIT213 |
| 494 | tristate "Sahara TouchIT-213 touchscreen" | 558 | tristate "Sahara TouchIT-213 touchscreen" |
| 495 | select SERIO | 559 | select SERIO |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 15fa62cffc77..7fef7d5cca23 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -6,17 +6,20 @@ | |||
| 6 | 6 | ||
| 7 | wm97xx-ts-y := wm97xx-core.o | 7 | wm97xx-ts-y := wm97xx-core.o |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o | ||
| 9 | obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o | 10 | obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o |
| 10 | obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | 11 | obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o |
| 11 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
| 12 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
| 13 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 14 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 15 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
| 16 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | ||
| 15 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 16 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o | 19 | obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o |
| 18 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o | 20 | obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o |
| 19 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o | 21 | obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o |
| 22 | obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o | ||
| 20 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o | 23 | obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o |
| 21 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o | 24 | obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o |
| 22 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o | 25 | obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o |
| @@ -25,7 +28,9 @@ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o | |||
| 25 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o | 28 | obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o |
| 26 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o | 29 | obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o |
| 27 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o | 30 | obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o |
| 31 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | ||
| 28 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o | 32 | obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o |
| 33 | obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o | ||
| 29 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o | 34 | obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o |
| 30 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o | 35 | obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o |
| 31 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o | 36 | obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o |
| @@ -41,4 +46,3 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
| 41 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 46 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
| 42 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 47 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
| 43 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 48 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
| 44 | obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o | ||
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index eb83939c705e..e019d53d1ab4 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | #include <linux/spi/ad7877.h> | 46 | #include <linux/spi/ad7877.h> |
| 47 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
| 48 | 48 | ||
| 49 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) | 49 | #define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) |
| 50 | 50 | ||
| 51 | #define MAX_SPI_FREQ_HZ 20000000 | 51 | #define MAX_SPI_FREQ_HZ 20000000 |
| 52 | #define MAX_12BIT ((1<<12)-1) | 52 | #define MAX_12BIT ((1<<12)-1) |
diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index c21e6d3a8844..794d070c6900 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | #include <linux/workqueue.h> | 47 | #include <linux/workqueue.h> |
| 48 | #include <linux/spi/spi.h> | 48 | #include <linux/spi/spi.h> |
| 49 | #include <linux/i2c.h> | 49 | #include <linux/i2c.h> |
| 50 | #include <linux/gpio.h> | ||
| 50 | 51 | ||
| 51 | #include <linux/spi/ad7879.h> | 52 | #include <linux/spi/ad7879.h> |
| 52 | 53 | ||
| @@ -132,7 +133,9 @@ struct ad7879 { | |||
| 132 | struct input_dev *input; | 133 | struct input_dev *input; |
| 133 | struct work_struct work; | 134 | struct work_struct work; |
| 134 | struct timer_list timer; | 135 | struct timer_list timer; |
| 135 | 136 | #ifdef CONFIG_GPIOLIB | |
| 137 | struct gpio_chip gc; | ||
| 138 | #endif | ||
| 136 | struct mutex mutex; | 139 | struct mutex mutex; |
| 137 | unsigned disabled:1; /* P: mutex */ | 140 | unsigned disabled:1; /* P: mutex */ |
| 138 | 141 | ||
| @@ -150,11 +153,9 @@ struct ad7879 { | |||
| 150 | u8 median; | 153 | u8 median; |
| 151 | u16 x_plate_ohms; | 154 | u16 x_plate_ohms; |
| 152 | u16 pressure_max; | 155 | u16 pressure_max; |
| 153 | u16 gpio_init; | ||
| 154 | u16 cmd_crtl1; | 156 | u16 cmd_crtl1; |
| 155 | u16 cmd_crtl2; | 157 | u16 cmd_crtl2; |
| 156 | u16 cmd_crtl3; | 158 | u16 cmd_crtl3; |
| 157 | unsigned gpio:1; | ||
| 158 | }; | 159 | }; |
| 159 | 160 | ||
| 160 | static int ad7879_read(bus_device *, u8); | 161 | static int ad7879_read(bus_device *, u8); |
| @@ -237,24 +238,6 @@ static irqreturn_t ad7879_irq(int irq, void *handle) | |||
| 237 | 238 | ||
| 238 | static void ad7879_setup(struct ad7879 *ts) | 239 | static void ad7879_setup(struct ad7879 *ts) |
| 239 | { | 240 | { |
| 240 | ts->cmd_crtl3 = AD7879_YPLUS_BIT | | ||
| 241 | AD7879_XPLUS_BIT | | ||
| 242 | AD7879_Z2_BIT | | ||
| 243 | AD7879_Z1_BIT | | ||
| 244 | AD7879_TEMPMASK_BIT | | ||
| 245 | AD7879_AUXVBATMASK_BIT | | ||
| 246 | AD7879_GPIOALERTMASK_BIT; | ||
| 247 | |||
| 248 | ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR | | ||
| 249 | AD7879_AVG(ts->averaging) | | ||
| 250 | AD7879_MFS(ts->median) | | ||
| 251 | AD7879_FCD(ts->first_conversion_delay) | | ||
| 252 | ts->gpio_init; | ||
| 253 | |||
| 254 | ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 | | ||
| 255 | AD7879_ACQ(ts->acquisition_time) | | ||
| 256 | AD7879_TMR(ts->pen_down_acc_interval); | ||
| 257 | |||
| 258 | ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); | 241 | ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); |
| 259 | ad7879_write(ts->bus, AD7879_REG_CTRL3, ts->cmd_crtl3); | 242 | ad7879_write(ts->bus, AD7879_REG_CTRL3, ts->cmd_crtl3); |
| 260 | ad7879_write(ts->bus, AD7879_REG_CTRL1, ts->cmd_crtl1); | 243 | ad7879_write(ts->bus, AD7879_REG_CTRL1, ts->cmd_crtl1); |
| @@ -324,48 +307,132 @@ static ssize_t ad7879_disable_store(struct device *dev, | |||
| 324 | 307 | ||
| 325 | static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store); | 308 | static DEVICE_ATTR(disable, 0664, ad7879_disable_show, ad7879_disable_store); |
| 326 | 309 | ||
| 327 | static ssize_t ad7879_gpio_show(struct device *dev, | 310 | static struct attribute *ad7879_attributes[] = { |
| 328 | struct device_attribute *attr, char *buf) | 311 | &dev_attr_disable.attr, |
| 312 | NULL | ||
| 313 | }; | ||
| 314 | |||
| 315 | static const struct attribute_group ad7879_attr_group = { | ||
| 316 | .attrs = ad7879_attributes, | ||
| 317 | }; | ||
| 318 | |||
| 319 | #ifdef CONFIG_GPIOLIB | ||
| 320 | static int ad7879_gpio_direction_input(struct gpio_chip *chip, | ||
| 321 | unsigned gpio) | ||
| 329 | { | 322 | { |
| 330 | struct ad7879 *ts = dev_get_drvdata(dev); | 323 | struct ad7879 *ts = container_of(chip, struct ad7879, gc); |
| 324 | int err; | ||
| 331 | 325 | ||
| 332 | return sprintf(buf, "%u\n", ts->gpio); | 326 | mutex_lock(&ts->mutex); |
| 327 | ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIODIR | AD7879_GPIOPOL; | ||
| 328 | err = ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); | ||
| 329 | mutex_unlock(&ts->mutex); | ||
| 330 | |||
| 331 | return err; | ||
| 333 | } | 332 | } |
| 334 | 333 | ||
| 335 | static ssize_t ad7879_gpio_store(struct device *dev, | 334 | static int ad7879_gpio_direction_output(struct gpio_chip *chip, |
| 336 | struct device_attribute *attr, | 335 | unsigned gpio, int level) |
| 337 | const char *buf, size_t count) | ||
| 338 | { | 336 | { |
| 339 | struct ad7879 *ts = dev_get_drvdata(dev); | 337 | struct ad7879 *ts = container_of(chip, struct ad7879, gc); |
| 340 | unsigned long val; | 338 | int err; |
| 341 | int error; | ||
| 342 | 339 | ||
| 343 | error = strict_strtoul(buf, 10, &val); | 340 | mutex_lock(&ts->mutex); |
| 344 | if (error) | 341 | ts->cmd_crtl2 &= ~AD7879_GPIODIR; |
| 345 | return error; | 342 | ts->cmd_crtl2 |= AD7879_GPIO_EN | AD7879_GPIOPOL; |
| 343 | if (level) | ||
| 344 | ts->cmd_crtl2 |= AD7879_GPIO_DATA; | ||
| 345 | else | ||
| 346 | ts->cmd_crtl2 &= ~AD7879_GPIO_DATA; | ||
| 347 | |||
| 348 | err = ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); | ||
| 349 | mutex_unlock(&ts->mutex); | ||
| 350 | |||
| 351 | return err; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int ad7879_gpio_get_value(struct gpio_chip *chip, unsigned gpio) | ||
| 355 | { | ||
| 356 | struct ad7879 *ts = container_of(chip, struct ad7879, gc); | ||
| 357 | u16 val; | ||
| 346 | 358 | ||
| 347 | mutex_lock(&ts->mutex); | 359 | mutex_lock(&ts->mutex); |
| 348 | ts->gpio = !!val; | 360 | val = ad7879_read(ts->bus, AD7879_REG_CTRL2); |
| 349 | error = ad7879_write(ts->bus, AD7879_REG_CTRL2, | ||
| 350 | ts->gpio ? | ||
| 351 | ts->cmd_crtl2 & ~AD7879_GPIO_DATA : | ||
| 352 | ts->cmd_crtl2 | AD7879_GPIO_DATA); | ||
| 353 | mutex_unlock(&ts->mutex); | 361 | mutex_unlock(&ts->mutex); |
| 354 | 362 | ||
| 355 | return error ? : count; | 363 | return !!(val & AD7879_GPIO_DATA); |
| 356 | } | 364 | } |
| 357 | 365 | ||
| 358 | static DEVICE_ATTR(gpio, 0664, ad7879_gpio_show, ad7879_gpio_store); | 366 | static void ad7879_gpio_set_value(struct gpio_chip *chip, |
| 367 | unsigned gpio, int value) | ||
| 368 | { | ||
| 369 | struct ad7879 *ts = container_of(chip, struct ad7879, gc); | ||
| 359 | 370 | ||
| 360 | static struct attribute *ad7879_attributes[] = { | 371 | mutex_lock(&ts->mutex); |
| 361 | &dev_attr_disable.attr, | 372 | if (value) |
| 362 | &dev_attr_gpio.attr, | 373 | ts->cmd_crtl2 |= AD7879_GPIO_DATA; |
| 363 | NULL | 374 | else |
| 364 | }; | 375 | ts->cmd_crtl2 &= ~AD7879_GPIO_DATA; |
| 365 | 376 | ||
| 366 | static const struct attribute_group ad7879_attr_group = { | 377 | ad7879_write(ts->bus, AD7879_REG_CTRL2, ts->cmd_crtl2); |
| 367 | .attrs = ad7879_attributes, | 378 | mutex_unlock(&ts->mutex); |
| 368 | }; | 379 | } |
| 380 | |||
| 381 | static int __devinit ad7879_gpio_add(struct device *dev) | ||
| 382 | { | ||
| 383 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
| 384 | struct ad7879_platform_data *pdata = dev->platform_data; | ||
| 385 | int ret = 0; | ||
| 386 | |||
| 387 | if (pdata->gpio_export) { | ||
| 388 | ts->gc.direction_input = ad7879_gpio_direction_input; | ||
| 389 | ts->gc.direction_output = ad7879_gpio_direction_output; | ||
| 390 | ts->gc.get = ad7879_gpio_get_value; | ||
| 391 | ts->gc.set = ad7879_gpio_set_value; | ||
| 392 | ts->gc.can_sleep = 1; | ||
| 393 | ts->gc.base = pdata->gpio_base; | ||
| 394 | ts->gc.ngpio = 1; | ||
| 395 | ts->gc.label = "AD7879-GPIO"; | ||
| 396 | ts->gc.owner = THIS_MODULE; | ||
| 397 | ts->gc.dev = dev; | ||
| 398 | |||
| 399 | ret = gpiochip_add(&ts->gc); | ||
| 400 | if (ret) | ||
| 401 | dev_err(dev, "failed to register gpio %d\n", | ||
| 402 | ts->gc.base); | ||
| 403 | } | ||
| 404 | |||
| 405 | return ret; | ||
| 406 | } | ||
| 407 | |||
| 408 | /* | ||
| 409 | * We mark ad7879_gpio_remove inline so there is a chance the code | ||
| 410 | * gets discarded when not needed. We can't do __devinit/__devexit | ||
| 411 | * markup since it is used in both probe and remove methods. | ||
| 412 | */ | ||
| 413 | static inline void ad7879_gpio_remove(struct device *dev) | ||
| 414 | { | ||
| 415 | struct ad7879 *ts = dev_get_drvdata(dev); | ||
| 416 | struct ad7879_platform_data *pdata = dev->platform_data; | ||
| 417 | int ret; | ||
| 418 | |||
| 419 | if (pdata->gpio_export) { | ||
| 420 | ret = gpiochip_remove(&ts->gc); | ||
| 421 | if (ret) | ||
| 422 | dev_err(dev, "failed to remove gpio %d\n", | ||
| 423 | ts->gc.base); | ||
| 424 | } | ||
| 425 | } | ||
| 426 | #else | ||
| 427 | static inline int ad7879_gpio_add(struct device *dev) | ||
| 428 | { | ||
| 429 | return 0; | ||
| 430 | } | ||
| 431 | |||
| 432 | static inline void ad7879_gpio_remove(struct device *dev) | ||
| 433 | { | ||
| 434 | } | ||
| 435 | #endif | ||
| 369 | 436 | ||
| 370 | static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | 437 | static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) |
| 371 | { | 438 | { |
| @@ -403,12 +470,6 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | |||
| 403 | ts->pen_down_acc_interval = pdata->pen_down_acc_interval; | 470 | ts->pen_down_acc_interval = pdata->pen_down_acc_interval; |
| 404 | ts->median = pdata->median; | 471 | ts->median = pdata->median; |
| 405 | 472 | ||
| 406 | if (pdata->gpio_output) | ||
| 407 | ts->gpio_init = AD7879_GPIO_EN | | ||
| 408 | (pdata->gpio_default ? 0 : AD7879_GPIO_DATA); | ||
| 409 | else | ||
| 410 | ts->gpio_init = AD7879_GPIO_EN | AD7879_GPIODIR; | ||
| 411 | |||
| 412 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&bus->dev)); | 473 | snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&bus->dev)); |
| 413 | 474 | ||
| 414 | input_dev->name = "AD7879 Touchscreen"; | 475 | input_dev->name = "AD7879 Touchscreen"; |
| @@ -446,6 +507,23 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | |||
| 446 | goto err_free_mem; | 507 | goto err_free_mem; |
| 447 | } | 508 | } |
| 448 | 509 | ||
| 510 | ts->cmd_crtl3 = AD7879_YPLUS_BIT | | ||
| 511 | AD7879_XPLUS_BIT | | ||
| 512 | AD7879_Z2_BIT | | ||
| 513 | AD7879_Z1_BIT | | ||
| 514 | AD7879_TEMPMASK_BIT | | ||
| 515 | AD7879_AUXVBATMASK_BIT | | ||
| 516 | AD7879_GPIOALERTMASK_BIT; | ||
| 517 | |||
| 518 | ts->cmd_crtl2 = AD7879_PM(AD7879_PM_DYN) | AD7879_DFR | | ||
| 519 | AD7879_AVG(ts->averaging) | | ||
| 520 | AD7879_MFS(ts->median) | | ||
| 521 | AD7879_FCD(ts->first_conversion_delay); | ||
| 522 | |||
| 523 | ts->cmd_crtl1 = AD7879_MODE_INT | AD7879_MODE_SEQ1 | | ||
| 524 | AD7879_ACQ(ts->acquisition_time) | | ||
| 525 | AD7879_TMR(ts->pen_down_acc_interval); | ||
| 526 | |||
| 449 | ad7879_setup(ts); | 527 | ad7879_setup(ts); |
| 450 | 528 | ||
| 451 | err = request_irq(bus->irq, ad7879_irq, | 529 | err = request_irq(bus->irq, ad7879_irq, |
| @@ -460,15 +538,21 @@ static int __devinit ad7879_construct(bus_device *bus, struct ad7879 *ts) | |||
| 460 | if (err) | 538 | if (err) |
| 461 | goto err_free_irq; | 539 | goto err_free_irq; |
| 462 | 540 | ||
| 463 | err = input_register_device(input_dev); | 541 | err = ad7879_gpio_add(&bus->dev); |
| 464 | if (err) | 542 | if (err) |
| 465 | goto err_remove_attr; | 543 | goto err_remove_attr; |
| 466 | 544 | ||
| 545 | err = input_register_device(input_dev); | ||
| 546 | if (err) | ||
| 547 | goto err_remove_gpio; | ||
| 548 | |||
| 467 | dev_info(&bus->dev, "Rev.%d touchscreen, irq %d\n", | 549 | dev_info(&bus->dev, "Rev.%d touchscreen, irq %d\n", |
| 468 | revid >> 8, bus->irq); | 550 | revid >> 8, bus->irq); |
| 469 | 551 | ||
| 470 | return 0; | 552 | return 0; |
| 471 | 553 | ||
| 554 | err_remove_gpio: | ||
| 555 | ad7879_gpio_remove(&bus->dev); | ||
| 472 | err_remove_attr: | 556 | err_remove_attr: |
| 473 | sysfs_remove_group(&bus->dev.kobj, &ad7879_attr_group); | 557 | sysfs_remove_group(&bus->dev.kobj, &ad7879_attr_group); |
| 474 | err_free_irq: | 558 | err_free_irq: |
| @@ -481,6 +565,7 @@ err_free_mem: | |||
| 481 | 565 | ||
| 482 | static int __devexit ad7879_destroy(bus_device *bus, struct ad7879 *ts) | 566 | static int __devexit ad7879_destroy(bus_device *bus, struct ad7879 *ts) |
| 483 | { | 567 | { |
| 568 | ad7879_gpio_remove(&bus->dev); | ||
| 484 | ad7879_disable(ts); | 569 | ad7879_disable(ts); |
| 485 | sysfs_remove_group(&ts->bus->dev.kobj, &ad7879_attr_group); | 570 | sysfs_remove_group(&ts->bus->dev.kobj, &ad7879_attr_group); |
| 486 | free_irq(ts->bus->irq, ts); | 571 | free_irq(ts->bus->irq, ts); |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 09c810999b92..532279cda0e4 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
| @@ -27,15 +27,16 @@ | |||
| 27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
| 28 | #include <linux/spi/spi.h> | 28 | #include <linux/spi/spi.h> |
| 29 | #include <linux/spi/ads7846.h> | 29 | #include <linux/spi/ads7846.h> |
| 30 | #include <linux/regulator/consumer.h> | ||
| 30 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
| 31 | 32 | ||
| 32 | |||
| 33 | /* | 33 | /* |
| 34 | * This code has been heavily tested on a Nokia 770, and lightly | 34 | * This code has been heavily tested on a Nokia 770, and lightly |
| 35 | * tested on other ads7846 devices (OSK/Mistral, Lubbock). | 35 | * tested on other ads7846 devices (OSK/Mistral, Lubbock, Spitz). |
| 36 | * TSC2046 is just newer ads7846 silicon. | 36 | * TSC2046 is just newer ads7846 silicon. |
| 37 | * Support for ads7843 tested on Atmel at91sam926x-EK. | 37 | * Support for ads7843 tested on Atmel at91sam926x-EK. |
| 38 | * Support for ads7845 has only been stubbed in. | 38 | * Support for ads7845 has only been stubbed in. |
| 39 | * Support for Analog Devices AD7873 and AD7843 tested. | ||
| 39 | * | 40 | * |
| 40 | * IRQ handling needs a workaround because of a shortcoming in handling | 41 | * IRQ handling needs a workaround because of a shortcoming in handling |
| 41 | * edge triggered IRQs on some platforms like the OMAP1/2. These | 42 | * edge triggered IRQs on some platforms like the OMAP1/2. These |
| @@ -43,7 +44,7 @@ | |||
| 43 | * have to maintain our own SW IRQ disabled status. This should be | 44 | * have to maintain our own SW IRQ disabled status. This should be |
| 44 | * removed as soon as the affected platform's IRQ handling is fixed. | 45 | * removed as soon as the affected platform's IRQ handling is fixed. |
| 45 | * | 46 | * |
| 46 | * app note sbaa036 talks in more detail about accurate sampling... | 47 | * App note sbaa036 talks in more detail about accurate sampling... |
| 47 | * that ought to help in situations like LCDs inducing noise (which | 48 | * that ought to help in situations like LCDs inducing noise (which |
| 48 | * can also be helped by using synch signals) and more generally. | 49 | * can also be helped by using synch signals) and more generally. |
| 49 | * This driver tries to utilize the measures described in the app | 50 | * This driver tries to utilize the measures described in the app |
| @@ -86,6 +87,7 @@ struct ads7846 { | |||
| 86 | char name[32]; | 87 | char name[32]; |
| 87 | 88 | ||
| 88 | struct spi_device *spi; | 89 | struct spi_device *spi; |
| 90 | struct regulator *reg; | ||
| 89 | 91 | ||
| 90 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) | 92 | #if defined(CONFIG_HWMON) || defined(CONFIG_HWMON_MODULE) |
| 91 | struct attribute_group *attr_group; | 93 | struct attribute_group *attr_group; |
| @@ -566,10 +568,8 @@ static void ads7846_rx(void *ads) | |||
| 566 | * once more the measurement | 568 | * once more the measurement |
| 567 | */ | 569 | */ |
| 568 | if (packet->tc.ignore || Rt > ts->pressure_max) { | 570 | if (packet->tc.ignore || Rt > ts->pressure_max) { |
| 569 | #ifdef VERBOSE | 571 | dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n", |
| 570 | pr_debug("%s: ignored %d pressure %d\n", | 572 | packet->tc.ignore, Rt); |
| 571 | dev_name(&ts->spi->dev), packet->tc.ignore, Rt); | ||
| 572 | #endif | ||
| 573 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 573 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
| 574 | HRTIMER_MODE_REL); | 574 | HRTIMER_MODE_REL); |
| 575 | return; | 575 | return; |
| @@ -598,9 +598,7 @@ static void ads7846_rx(void *ads) | |||
| 598 | if (!ts->pendown) { | 598 | if (!ts->pendown) { |
| 599 | input_report_key(input, BTN_TOUCH, 1); | 599 | input_report_key(input, BTN_TOUCH, 1); |
| 600 | ts->pendown = 1; | 600 | ts->pendown = 1; |
| 601 | #ifdef VERBOSE | 601 | dev_vdbg(&ts->spi->dev, "DOWN\n"); |
| 602 | dev_dbg(&ts->spi->dev, "DOWN\n"); | ||
| 603 | #endif | ||
| 604 | } | 602 | } |
| 605 | 603 | ||
| 606 | if (ts->swap_xy) | 604 | if (ts->swap_xy) |
| @@ -608,12 +606,10 @@ static void ads7846_rx(void *ads) | |||
| 608 | 606 | ||
| 609 | input_report_abs(input, ABS_X, x); | 607 | input_report_abs(input, ABS_X, x); |
| 610 | input_report_abs(input, ABS_Y, y); | 608 | input_report_abs(input, ABS_Y, y); |
| 611 | input_report_abs(input, ABS_PRESSURE, Rt); | 609 | input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt); |
| 612 | 610 | ||
| 613 | input_sync(input); | 611 | input_sync(input); |
| 614 | #ifdef VERBOSE | 612 | dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); |
| 615 | dev_dbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt); | ||
| 616 | #endif | ||
| 617 | } | 613 | } |
| 618 | 614 | ||
| 619 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), | 615 | hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), |
| @@ -723,9 +719,7 @@ static enum hrtimer_restart ads7846_timer(struct hrtimer *handle) | |||
| 723 | input_sync(input); | 719 | input_sync(input); |
| 724 | 720 | ||
| 725 | ts->pendown = 0; | 721 | ts->pendown = 0; |
| 726 | #ifdef VERBOSE | 722 | dev_vdbg(&ts->spi->dev, "UP\n"); |
| 727 | dev_dbg(&ts->spi->dev, "UP\n"); | ||
| 728 | #endif | ||
| 729 | } | 723 | } |
| 730 | 724 | ||
| 731 | /* measurement cycle ended */ | 725 | /* measurement cycle ended */ |
| @@ -797,6 +791,8 @@ static void ads7846_disable(struct ads7846 *ts) | |||
| 797 | } | 791 | } |
| 798 | } | 792 | } |
| 799 | 793 | ||
| 794 | regulator_disable(ts->reg); | ||
| 795 | |||
| 800 | /* we know the chip's in lowpower mode since we always | 796 | /* we know the chip's in lowpower mode since we always |
| 801 | * leave it that way after every request | 797 | * leave it that way after every request |
| 802 | */ | 798 | */ |
| @@ -808,6 +804,8 @@ static void ads7846_enable(struct ads7846 *ts) | |||
| 808 | if (!ts->disabled) | 804 | if (!ts->disabled) |
| 809 | return; | 805 | return; |
| 810 | 806 | ||
| 807 | regulator_enable(ts->reg); | ||
| 808 | |||
| 811 | ts->disabled = 0; | 809 | ts->disabled = 0; |
| 812 | ts->irq_disabled = 0; | 810 | ts->irq_disabled = 0; |
| 813 | enable_irq(ts->spi->irq); | 811 | enable_irq(ts->spi->irq); |
| @@ -824,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) | |||
| 824 | 822 | ||
| 825 | spin_unlock_irq(&ts->lock); | 823 | spin_unlock_irq(&ts->lock); |
| 826 | 824 | ||
| 825 | if (device_may_wakeup(&ts->spi->dev)) | ||
| 826 | enable_irq_wake(ts->spi->irq); | ||
| 827 | |||
| 827 | return 0; | 828 | return 0; |
| 828 | 829 | ||
| 829 | } | 830 | } |
| @@ -832,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) | |||
| 832 | { | 833 | { |
| 833 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 834 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
| 834 | 835 | ||
| 836 | if (device_may_wakeup(&ts->spi->dev)) | ||
| 837 | disable_irq_wake(ts->spi->irq); | ||
| 838 | |||
| 835 | spin_lock_irq(&ts->lock); | 839 | spin_lock_irq(&ts->lock); |
| 836 | 840 | ||
| 837 | ts->is_suspended = 0; | 841 | ts->is_suspended = 0; |
| @@ -987,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 987 | 991 | ||
| 988 | vref = pdata->keep_vref_on; | 992 | vref = pdata->keep_vref_on; |
| 989 | 993 | ||
| 994 | if (ts->model == 7873) { | ||
| 995 | /* The AD7873 is almost identical to the ADS7846 | ||
| 996 | * keep VREF off during differential/ratiometric | ||
| 997 | * conversion modes | ||
| 998 | */ | ||
| 999 | ts->model = 7846; | ||
| 1000 | vref = 0; | ||
| 1001 | } | ||
| 1002 | |||
| 990 | /* set up the transfers to read touchscreen state; this assumes we | 1003 | /* set up the transfers to read touchscreen state; this assumes we |
| 991 | * use formula #2 for pressure, not #3. | 1004 | * use formula #2 for pressure, not #3. |
| 992 | */ | 1005 | */ |
| @@ -1148,6 +1161,19 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 1148 | 1161 | ||
| 1149 | ts->last_msg = m; | 1162 | ts->last_msg = m; |
| 1150 | 1163 | ||
| 1164 | ts->reg = regulator_get(&spi->dev, "vcc"); | ||
| 1165 | if (IS_ERR(ts->reg)) { | ||
| 1166 | dev_err(&spi->dev, "unable to get regulator: %ld\n", | ||
| 1167 | PTR_ERR(ts->reg)); | ||
| 1168 | goto err_free_gpio; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | err = regulator_enable(ts->reg); | ||
| 1172 | if (err) { | ||
| 1173 | dev_err(&spi->dev, "unable to enable regulator: %d\n", err); | ||
| 1174 | goto err_put_regulator; | ||
| 1175 | } | ||
| 1176 | |||
| 1151 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, | 1177 | if (request_irq(spi->irq, ads7846_irq, IRQF_TRIGGER_FALLING, |
| 1152 | spi->dev.driver->name, ts)) { | 1178 | spi->dev.driver->name, ts)) { |
| 1153 | dev_info(&spi->dev, | 1179 | dev_info(&spi->dev, |
| @@ -1157,7 +1183,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 1157 | spi->dev.driver->name, ts); | 1183 | spi->dev.driver->name, ts); |
| 1158 | if (err) { | 1184 | if (err) { |
| 1159 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | 1185 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); |
| 1160 | goto err_free_gpio; | 1186 | goto err_disable_regulator; |
| 1161 | } | 1187 | } |
| 1162 | } | 1188 | } |
| 1163 | 1189 | ||
| @@ -1181,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 1181 | if (err) | 1207 | if (err) |
| 1182 | goto err_remove_attr_group; | 1208 | goto err_remove_attr_group; |
| 1183 | 1209 | ||
| 1210 | device_init_wakeup(&spi->dev, pdata->wakeup); | ||
| 1211 | |||
| 1184 | return 0; | 1212 | return 0; |
| 1185 | 1213 | ||
| 1186 | err_remove_attr_group: | 1214 | err_remove_attr_group: |
| @@ -1189,6 +1217,10 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
| 1189 | ads784x_hwmon_unregister(spi, ts); | 1217 | ads784x_hwmon_unregister(spi, ts); |
| 1190 | err_free_irq: | 1218 | err_free_irq: |
| 1191 | free_irq(spi->irq, ts); | 1219 | free_irq(spi->irq, ts); |
| 1220 | err_disable_regulator: | ||
| 1221 | regulator_disable(ts->reg); | ||
| 1222 | err_put_regulator: | ||
| 1223 | regulator_put(ts->reg); | ||
| 1192 | err_free_gpio: | 1224 | err_free_gpio: |
| 1193 | if (ts->gpio_pendown != -1) | 1225 | if (ts->gpio_pendown != -1) |
| 1194 | gpio_free(ts->gpio_pendown); | 1226 | gpio_free(ts->gpio_pendown); |
| @@ -1206,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
| 1206 | { | 1238 | { |
| 1207 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | 1239 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); |
| 1208 | 1240 | ||
| 1241 | device_init_wakeup(&spi->dev, false); | ||
| 1242 | |||
| 1209 | ads784x_hwmon_unregister(spi, ts); | 1243 | ads784x_hwmon_unregister(spi, ts); |
| 1210 | input_unregister_device(ts->input); | 1244 | input_unregister_device(ts->input); |
| 1211 | 1245 | ||
| @@ -1217,6 +1251,9 @@ static int __devexit ads7846_remove(struct spi_device *spi) | |||
| 1217 | /* suspend left the IRQ disabled */ | 1251 | /* suspend left the IRQ disabled */ |
| 1218 | enable_irq(ts->spi->irq); | 1252 | enable_irq(ts->spi->irq); |
| 1219 | 1253 | ||
| 1254 | regulator_disable(ts->reg); | ||
| 1255 | regulator_put(ts->reg); | ||
| 1256 | |||
| 1220 | if (ts->gpio_pendown != -1) | 1257 | if (ts->gpio_pendown != -1) |
| 1221 | gpio_free(ts->gpio_pendown); | 1258 | gpio_free(ts->gpio_pendown); |
| 1222 | 1259 | ||
diff --git a/drivers/input/touchscreen/atmel-wm97xx.c b/drivers/input/touchscreen/atmel-wm97xx.c index 35377f583e28..fa8e56bd9094 100644 --- a/drivers/input/touchscreen/atmel-wm97xx.c +++ b/drivers/input/touchscreen/atmel-wm97xx.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/timer.h> | 19 | #include <linux/timer.h> |
| 20 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | 23 | ||
| 23 | #define AC97C_ICA 0x10 | 24 | #define AC97C_ICA 0x10 |
| 24 | #define AC97C_CBRHR 0x30 | 25 | #define AC97C_CBRHR 0x30 |
| @@ -59,7 +60,7 @@ | |||
| 59 | #define ATMEL_WM97XX_AC97C_IRQ (29) | 60 | #define ATMEL_WM97XX_AC97C_IRQ (29) |
| 60 | #define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */ | 61 | #define ATMEL_WM97XX_GPIO_DEFAULT (32+16) /* Pin 16 on port B. */ |
| 61 | #else | 62 | #else |
| 62 | #error Unkown CPU, this driver only supports AT32AP700X CPUs. | 63 | #error Unknown CPU, this driver only supports AT32AP700X CPUs. |
| 63 | #endif | 64 | #endif |
| 64 | 65 | ||
| 65 | struct continuous { | 66 | struct continuous { |
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c index 9c7fce4d74d0..3d9b5166ebe9 100644 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ b/drivers/input/touchscreen/atmel_tsadcc.c | |||
| @@ -22,6 +22,8 @@ | |||
| 22 | #include <linux/clk.h> | 22 | #include <linux/clk.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
| 25 | #include <mach/board.h> | ||
| 26 | #include <mach/cpu.h> | ||
| 25 | 27 | ||
| 26 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ | 28 | /* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ |
| 27 | 29 | ||
| @@ -36,7 +38,9 @@ | |||
| 36 | #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ | 38 | #define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ |
| 37 | #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ | 39 | #define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ |
| 38 | #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ | 40 | #define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ |
| 41 | #define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ | ||
| 39 | #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ | 42 | #define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ |
| 43 | #define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ | ||
| 40 | #define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ | 44 | #define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ |
| 41 | #define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ | 45 | #define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ |
| 42 | #define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ | 46 | #define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ |
| @@ -84,7 +88,13 @@ | |||
| 84 | #define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ | 88 | #define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ |
| 85 | #define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ | 89 | #define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ |
| 86 | 90 | ||
| 87 | #define ADC_CLOCK 1000000 | 91 | #define ATMEL_TSADCC_XPOS 0x50 |
| 92 | #define ATMEL_TSADCC_Z1DAT 0x54 | ||
| 93 | #define ATMEL_TSADCC_Z2DAT 0x58 | ||
| 94 | |||
| 95 | #define PRESCALER_VAL(x) ((x) >> 8) | ||
| 96 | |||
| 97 | #define ADC_DEFAULT_CLOCK 100000 | ||
| 88 | 98 | ||
| 89 | struct atmel_tsadcc { | 99 | struct atmel_tsadcc { |
| 90 | struct input_dev *input; | 100 | struct input_dev *input; |
| @@ -172,6 +182,7 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 172 | struct atmel_tsadcc *ts_dev; | 182 | struct atmel_tsadcc *ts_dev; |
| 173 | struct input_dev *input_dev; | 183 | struct input_dev *input_dev; |
| 174 | struct resource *res; | 184 | struct resource *res; |
| 185 | struct at91_tsadcc_data *pdata = pdev->dev.platform_data; | ||
| 175 | int err = 0; | 186 | int err = 0; |
| 176 | unsigned int prsc; | 187 | unsigned int prsc; |
| 177 | unsigned int reg; | 188 | unsigned int reg; |
| @@ -242,31 +253,49 @@ static int __devinit atmel_tsadcc_probe(struct platform_device *pdev) | |||
| 242 | input_dev->phys = ts_dev->phys; | 253 | input_dev->phys = ts_dev->phys; |
| 243 | input_dev->dev.parent = &pdev->dev; | 254 | input_dev->dev.parent = &pdev->dev; |
| 244 | 255 | ||
| 245 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | 256 | __set_bit(EV_ABS, input_dev->evbit); |
| 246 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 247 | |||
| 248 | input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); | 257 | input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); |
| 249 | input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); | 258 | input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); |
| 250 | 259 | ||
| 260 | input_set_capability(input_dev, EV_KEY, BTN_TOUCH); | ||
| 261 | |||
| 251 | /* clk_enable() always returns 0, no need to check it */ | 262 | /* clk_enable() always returns 0, no need to check it */ |
| 252 | clk_enable(ts_dev->clk); | 263 | clk_enable(ts_dev->clk); |
| 253 | 264 | ||
| 254 | prsc = clk_get_rate(ts_dev->clk); | 265 | prsc = clk_get_rate(ts_dev->clk); |
| 255 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); | 266 | dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); |
| 256 | 267 | ||
| 257 | prsc = prsc / ADC_CLOCK / 2 - 1; | 268 | if (!pdata) |
| 269 | goto err_fail; | ||
| 270 | |||
| 271 | if (!pdata->adc_clock) | ||
| 272 | pdata->adc_clock = ADC_DEFAULT_CLOCK; | ||
| 273 | |||
| 274 | prsc = (prsc / (2 * pdata->adc_clock)) - 1; | ||
| 275 | |||
| 276 | /* saturate if this value is too high */ | ||
| 277 | if (cpu_is_at91sam9rl()) { | ||
| 278 | if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL)) | ||
| 279 | prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL); | ||
| 280 | } else { | ||
| 281 | if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL)) | ||
| 282 | prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL); | ||
| 283 | } | ||
| 284 | |||
| 285 | dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc); | ||
| 258 | 286 | ||
| 259 | reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | | 287 | reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | |
| 260 | ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ | 288 | ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ |
| 261 | ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ | 289 | ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ |
| 262 | ((prsc << 8) & ATMEL_TSADCC_PRESCAL) | /* PRESCAL */ | 290 | (prsc << 8) | |
| 263 | ((0x13 << 16) & ATMEL_TSADCC_STARTUP) | /* STARTUP */ | 291 | ((0x26 << 16) & ATMEL_TSADCC_STARTUP) | |
| 264 | ((0x0F << 28) & ATMEL_TSADCC_PENDBC); /* PENDBC */ | 292 | ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); |
| 265 | 293 | ||
| 266 | atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); | 294 | atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); |
| 267 | atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); | 295 | atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); |
| 268 | atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); | 296 | atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); |
| 269 | atmel_tsadcc_write(ATMEL_TSADCC_TSR, (0x3 << 24) & ATMEL_TSADCC_TSSHTIM); | 297 | atmel_tsadcc_write(ATMEL_TSADCC_TSR, |
| 298 | (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); | ||
| 270 | 299 | ||
| 271 | atmel_tsadcc_read(ATMEL_TSADCC_SR); | 300 | atmel_tsadcc_read(ATMEL_TSADCC_SR); |
| 272 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); | 301 | atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); |
diff --git a/drivers/input/touchscreen/da9034-ts.c b/drivers/input/touchscreen/da9034-ts.c index 3ffd4c4b170c..2b72a5923c16 100644 --- a/drivers/input/touchscreen/da9034-ts.c +++ b/drivers/input/touchscreen/da9034-ts.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/input.h> | 19 | #include <linux/input.h> |
| 20 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
| 21 | #include <linux/mfd/da903x.h> | 21 | #include <linux/mfd/da903x.h> |
| 22 | #include <linux/slab.h> | ||
| 22 | 23 | ||
| 23 | #define DA9034_MANUAL_CTRL 0x50 | 24 | #define DA9034_MANUAL_CTRL 0x50 |
| 24 | #define DA9034_LDO_ADC_EN (1 << 4) | 25 | #define DA9034_LDO_ADC_EN (1 << 4) |
diff --git a/drivers/input/touchscreen/dynapro.c b/drivers/input/touchscreen/dynapro.c new file mode 100644 index 000000000000..455353908bdf --- /dev/null +++ b/drivers/input/touchscreen/dynapro.c | |||
| @@ -0,0 +1,206 @@ | |||
| 1 | /* | ||
| 2 | * Dynapro serial touchscreen driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 Tias Guns | ||
| 5 | * Based on the inexio driver (c) Vojtech Pavlik and Dan Streetman and | ||
| 6 | * Richard Lemon | ||
| 7 | * | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * This program is free software; you can redistribute it and/or modify it | ||
| 12 | * under the terms of the GNU General Public License version 2 as published by | ||
| 13 | * the Free Software Foundation. | ||
| 14 | */ | ||
| 15 | |||
| 16 | /* | ||
| 17 | * 2009/09/19 Tias Guns <tias@ulyssis.org> | ||
| 18 | * Copied inexio.c and edited for Dynapro protocol (from retired Xorg module) | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/errno.h> | ||
| 22 | #include <linux/kernel.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | #include <linux/input.h> | ||
| 26 | #include <linux/serio.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | |||
| 29 | #define DRIVER_DESC "Dynapro serial touchscreen driver" | ||
| 30 | |||
| 31 | MODULE_AUTHOR("Tias Guns <tias@ulyssis.org>"); | ||
| 32 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
| 33 | MODULE_LICENSE("GPL"); | ||
| 34 | |||
| 35 | /* | ||
| 36 | * Definitions & global arrays. | ||
| 37 | */ | ||
| 38 | |||
| 39 | #define DYNAPRO_FORMAT_TOUCH_BIT 0x40 | ||
| 40 | #define DYNAPRO_FORMAT_LENGTH 3 | ||
| 41 | #define DYNAPRO_RESPONSE_BEGIN_BYTE 0x80 | ||
| 42 | |||
| 43 | #define DYNAPRO_MIN_XC 0 | ||
| 44 | #define DYNAPRO_MAX_XC 0x3ff | ||
| 45 | #define DYNAPRO_MIN_YC 0 | ||
| 46 | #define DYNAPRO_MAX_YC 0x3ff | ||
| 47 | |||
| 48 | #define DYNAPRO_GET_XC(data) (data[1] | ((data[0] & 0x38) << 4)) | ||
| 49 | #define DYNAPRO_GET_YC(data) (data[2] | ((data[0] & 0x07) << 7)) | ||
| 50 | #define DYNAPRO_GET_TOUCHED(data) (DYNAPRO_FORMAT_TOUCH_BIT & data[0]) | ||
| 51 | |||
| 52 | /* | ||
| 53 | * Per-touchscreen data. | ||
| 54 | */ | ||
| 55 | |||
| 56 | struct dynapro { | ||
| 57 | struct input_dev *dev; | ||
| 58 | struct serio *serio; | ||
| 59 | int idx; | ||
| 60 | unsigned char data[DYNAPRO_FORMAT_LENGTH]; | ||
| 61 | char phys[32]; | ||
| 62 | }; | ||
| 63 | |||
| 64 | static void dynapro_process_data(struct dynapro *pdynapro) | ||
| 65 | { | ||
| 66 | struct input_dev *dev = pdynapro->dev; | ||
| 67 | |||
| 68 | if (DYNAPRO_FORMAT_LENGTH == ++pdynapro->idx) { | ||
| 69 | input_report_abs(dev, ABS_X, DYNAPRO_GET_XC(pdynapro->data)); | ||
| 70 | input_report_abs(dev, ABS_Y, DYNAPRO_GET_YC(pdynapro->data)); | ||
| 71 | input_report_key(dev, BTN_TOUCH, | ||
| 72 | DYNAPRO_GET_TOUCHED(pdynapro->data)); | ||
| 73 | input_sync(dev); | ||
| 74 | |||
| 75 | pdynapro->idx = 0; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | static irqreturn_t dynapro_interrupt(struct serio *serio, | ||
| 80 | unsigned char data, unsigned int flags) | ||
| 81 | { | ||
| 82 | struct dynapro *pdynapro = serio_get_drvdata(serio); | ||
| 83 | |||
| 84 | pdynapro->data[pdynapro->idx] = data; | ||
| 85 | |||
| 86 | if (DYNAPRO_RESPONSE_BEGIN_BYTE & pdynapro->data[0]) | ||
| 87 | dynapro_process_data(pdynapro); | ||
| 88 | else | ||
| 89 | dev_dbg(&serio->dev, "unknown/unsynchronized data: %x\n", | ||
| 90 | pdynapro->data[0]); | ||
| 91 | |||
| 92 | return IRQ_HANDLED; | ||
| 93 | } | ||
| 94 | |||
| 95 | static void dynapro_disconnect(struct serio *serio) | ||
| 96 | { | ||
| 97 | struct dynapro *pdynapro = serio_get_drvdata(serio); | ||
| 98 | |||
| 99 | input_get_device(pdynapro->dev); | ||
| 100 | input_unregister_device(pdynapro->dev); | ||
| 101 | serio_close(serio); | ||
| 102 | serio_set_drvdata(serio, NULL); | ||
| 103 | input_put_device(pdynapro->dev); | ||
| 104 | kfree(pdynapro); | ||
| 105 | } | ||
| 106 | |||
| 107 | /* | ||
| 108 | * dynapro_connect() is the routine that is called when someone adds a | ||
| 109 | * new serio device that supports dynapro protocol and registers it as | ||
| 110 | * an input device. This is usually accomplished using inputattach. | ||
| 111 | */ | ||
| 112 | |||
| 113 | static int dynapro_connect(struct serio *serio, struct serio_driver *drv) | ||
| 114 | { | ||
| 115 | struct dynapro *pdynapro; | ||
| 116 | struct input_dev *input_dev; | ||
| 117 | int err; | ||
| 118 | |||
| 119 | pdynapro = kzalloc(sizeof(struct dynapro), GFP_KERNEL); | ||
| 120 | input_dev = input_allocate_device(); | ||
| 121 | if (!pdynapro || !input_dev) { | ||
| 122 | err = -ENOMEM; | ||
| 123 | goto fail1; | ||
| 124 | } | ||
| 125 | |||
| 126 | pdynapro->serio = serio; | ||
| 127 | pdynapro->dev = input_dev; | ||
| 128 | snprintf(pdynapro->phys, sizeof(pdynapro->phys), | ||
| 129 | "%s/input0", serio->phys); | ||
| 130 | |||
| 131 | input_dev->name = "Dynapro Serial TouchScreen"; | ||
| 132 | input_dev->phys = pdynapro->phys; | ||
| 133 | input_dev->id.bustype = BUS_RS232; | ||
| 134 | input_dev->id.vendor = SERIO_DYNAPRO; | ||
| 135 | input_dev->id.product = 0; | ||
| 136 | input_dev->id.version = 0x0001; | ||
| 137 | input_dev->dev.parent = &serio->dev; | ||
| 138 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 139 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 140 | input_set_abs_params(pdynapro->dev, ABS_X, | ||
| 141 | DYNAPRO_MIN_XC, DYNAPRO_MAX_XC, 0, 0); | ||
| 142 | input_set_abs_params(pdynapro->dev, ABS_Y, | ||
| 143 | DYNAPRO_MIN_YC, DYNAPRO_MAX_YC, 0, 0); | ||
| 144 | |||
| 145 | serio_set_drvdata(serio, pdynapro); | ||
| 146 | |||
| 147 | err = serio_open(serio, drv); | ||
| 148 | if (err) | ||
| 149 | goto fail2; | ||
| 150 | |||
| 151 | err = input_register_device(pdynapro->dev); | ||
| 152 | if (err) | ||
| 153 | goto fail3; | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | |||
| 157 | fail3: serio_close(serio); | ||
| 158 | fail2: serio_set_drvdata(serio, NULL); | ||
| 159 | fail1: input_free_device(input_dev); | ||
| 160 | kfree(pdynapro); | ||
| 161 | return err; | ||
| 162 | } | ||
| 163 | |||
| 164 | /* | ||
| 165 | * The serio driver structure. | ||
| 166 | */ | ||
| 167 | |||
| 168 | static struct serio_device_id dynapro_serio_ids[] = { | ||
| 169 | { | ||
| 170 | .type = SERIO_RS232, | ||
| 171 | .proto = SERIO_DYNAPRO, | ||
| 172 | .id = SERIO_ANY, | ||
| 173 | .extra = SERIO_ANY, | ||
| 174 | }, | ||
| 175 | { 0 } | ||
| 176 | }; | ||
| 177 | |||
| 178 | MODULE_DEVICE_TABLE(serio, dynapro_serio_ids); | ||
| 179 | |||
| 180 | static struct serio_driver dynapro_drv = { | ||
| 181 | .driver = { | ||
| 182 | .name = "dynapro", | ||
| 183 | }, | ||
| 184 | .description = DRIVER_DESC, | ||
| 185 | .id_table = dynapro_serio_ids, | ||
| 186 | .interrupt = dynapro_interrupt, | ||
| 187 | .connect = dynapro_connect, | ||
| 188 | .disconnect = dynapro_disconnect, | ||
| 189 | }; | ||
| 190 | |||
| 191 | /* | ||
| 192 | * The functions for inserting/removing us as a module. | ||
| 193 | */ | ||
| 194 | |||
| 195 | static int __init dynapro_init(void) | ||
| 196 | { | ||
| 197 | return serio_register_driver(&dynapro_drv); | ||
| 198 | } | ||
| 199 | |||
| 200 | static void __exit dynapro_exit(void) | ||
| 201 | { | ||
| 202 | serio_unregister_driver(&dynapro_drv); | ||
| 203 | } | ||
| 204 | |||
| 205 | module_init(dynapro_init); | ||
| 206 | module_exit(dynapro_exit); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 9029bd3f34e5..204b8a1a601c 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
| 34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
| 35 | #include <linux/input/eeti_ts.h> | 35 | #include <linux/input/eeti_ts.h> |
| 36 | #include <linux/slab.h> | ||
| 36 | 37 | ||
| 37 | static int flip_x; | 38 | static int flip_x; |
| 38 | module_param(flip_x, bool, 0644); | 39 | module_param(flip_x, bool, 0644); |
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 8f38c5e55ce6..486d31ba9c09 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -72,45 +72,49 @@ static void elo_process_data_10(struct elo *elo, unsigned char data) | |||
| 72 | struct input_dev *dev = elo->dev; | 72 | struct input_dev *dev = elo->dev; |
| 73 | 73 | ||
| 74 | elo->data[elo->idx] = data; | 74 | elo->data[elo->idx] = data; |
| 75 | switch (elo->idx++) { | ||
| 76 | case 0: | ||
| 77 | elo->csum = 0xaa; | ||
| 78 | if (data != ELO10_LEAD_BYTE) { | ||
| 79 | pr_debug("elo: unsynchronized data: 0x%02x\n", data); | ||
| 80 | elo->idx = 0; | ||
| 81 | } | ||
| 82 | break; | ||
| 83 | 75 | ||
| 84 | case 9: | 76 | switch (elo->idx++) { |
| 77 | case 0: | ||
| 78 | elo->csum = 0xaa; | ||
| 79 | if (data != ELO10_LEAD_BYTE) { | ||
| 80 | dev_dbg(&elo->serio->dev, | ||
| 81 | "unsynchronized data: 0x%02x\n", data); | ||
| 85 | elo->idx = 0; | 82 | elo->idx = 0; |
| 86 | if (data != elo->csum) { | 83 | } |
| 87 | pr_debug("elo: bad checksum: 0x%02x, expected 0x%02x\n", | 84 | break; |
| 88 | data, elo->csum); | 85 | |
| 89 | break; | 86 | case 9: |
| 90 | } | 87 | elo->idx = 0; |
| 91 | if (elo->data[1] != elo->expected_packet) { | 88 | if (data != elo->csum) { |
| 92 | if (elo->data[1] != ELO10_TOUCH_PACKET) | 89 | dev_dbg(&elo->serio->dev, |
| 93 | pr_debug("elo: unexpected packet: 0x%02x\n", | 90 | "bad checksum: 0x%02x, expected 0x%02x\n", |
| 94 | elo->data[1]); | 91 | data, elo->csum); |
| 95 | break; | 92 | break; |
| 96 | } | 93 | } |
| 97 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { | 94 | if (elo->data[1] != elo->expected_packet) { |
| 98 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | 95 | if (elo->data[1] != ELO10_TOUCH_PACKET) |
| 99 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | 96 | dev_dbg(&elo->serio->dev, |
| 100 | if (elo->data[2] & ELO10_PRESSURE) | 97 | "unexpected packet: 0x%02x\n", |
| 101 | input_report_abs(dev, ABS_PRESSURE, | 98 | elo->data[1]); |
| 102 | (elo->data[8] << 8) | elo->data[7]); | ||
| 103 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
| 104 | input_sync(dev); | ||
| 105 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
| 106 | if (elo->data[2] == '0') | ||
| 107 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 108 | complete(&elo->cmd_done); | ||
| 109 | } else { | ||
| 110 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
| 111 | elo->expected_packet = ELO10_ACK_PACKET; | ||
| 112 | } | ||
| 113 | break; | 99 | break; |
| 100 | } | ||
| 101 | if (likely(elo->data[1] == ELO10_TOUCH_PACKET)) { | ||
| 102 | input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]); | ||
| 103 | input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]); | ||
| 104 | if (elo->data[2] & ELO10_PRESSURE) | ||
| 105 | input_report_abs(dev, ABS_PRESSURE, | ||
| 106 | (elo->data[8] << 8) | elo->data[7]); | ||
| 107 | input_report_key(dev, BTN_TOUCH, elo->data[2] & ELO10_TOUCH); | ||
| 108 | input_sync(dev); | ||
| 109 | } else if (elo->data[1] == ELO10_ACK_PACKET) { | ||
| 110 | if (elo->data[2] == '0') | ||
| 111 | elo->expected_packet = ELO10_TOUCH_PACKET; | ||
| 112 | complete(&elo->cmd_done); | ||
| 113 | } else { | ||
| 114 | memcpy(elo->response, &elo->data[1], ELO10_PACKET_LEN); | ||
| 115 | elo->expected_packet = ELO10_ACK_PACKET; | ||
| 116 | } | ||
| 117 | break; | ||
| 114 | } | 118 | } |
| 115 | elo->csum += data; | 119 | elo->csum += data; |
| 116 | } | 120 | } |
| @@ -123,42 +127,53 @@ static void elo_process_data_6(struct elo *elo, unsigned char data) | |||
| 123 | 127 | ||
| 124 | switch (elo->idx++) { | 128 | switch (elo->idx++) { |
| 125 | 129 | ||
| 126 | case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break; | 130 | case 0: |
| 127 | case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break; | 131 | if ((data & 0xc0) != 0xc0) |
| 128 | case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break; | 132 | elo->idx = 0; |
| 129 | 133 | break; | |
| 130 | case 3: | ||
| 131 | if (data & 0xc0) { | ||
| 132 | elo->idx = 0; | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | 134 | ||
| 136 | input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); | 135 | case 1: |
| 137 | input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); | 136 | if ((data & 0xc0) != 0x80) |
| 137 | elo->idx = 0; | ||
| 138 | break; | ||
| 138 | 139 | ||
| 139 | if (elo->id == 2) { | 140 | case 2: |
| 140 | input_report_key(dev, BTN_TOUCH, 1); | 141 | if ((data & 0xc0) != 0x40) |
| 141 | input_sync(dev); | 142 | elo->idx = 0; |
| 142 | elo->idx = 0; | 143 | break; |
| 143 | } | ||
| 144 | 144 | ||
| 145 | case 3: | ||
| 146 | if (data & 0xc0) { | ||
| 147 | elo->idx = 0; | ||
| 145 | break; | 148 | break; |
| 149 | } | ||
| 146 | 150 | ||
| 147 | case 4: | 151 | input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f)); |
| 148 | if (data) { | 152 | input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f)); |
| 149 | input_sync(dev); | ||
| 150 | elo->idx = 0; | ||
| 151 | } | ||
| 152 | break; | ||
| 153 | 153 | ||
| 154 | case 5: | 154 | if (elo->id == 2) { |
| 155 | if ((data & 0xf0) == 0) { | 155 | input_report_key(dev, BTN_TOUCH, 1); |
| 156 | input_report_abs(dev, ABS_PRESSURE, elo->data[5]); | ||
| 157 | input_report_key(dev, BTN_TOUCH, !!elo->data[5]); | ||
| 158 | } | ||
| 159 | input_sync(dev); | 156 | input_sync(dev); |
| 160 | elo->idx = 0; | 157 | elo->idx = 0; |
| 161 | break; | 158 | } |
| 159 | |||
| 160 | break; | ||
| 161 | |||
| 162 | case 4: | ||
| 163 | if (data) { | ||
| 164 | input_sync(dev); | ||
| 165 | elo->idx = 0; | ||
| 166 | } | ||
| 167 | break; | ||
| 168 | |||
| 169 | case 5: | ||
| 170 | if ((data & 0xf0) == 0) { | ||
| 171 | input_report_abs(dev, ABS_PRESSURE, elo->data[5]); | ||
| 172 | input_report_key(dev, BTN_TOUCH, !!elo->data[5]); | ||
| 173 | } | ||
| 174 | input_sync(dev); | ||
| 175 | elo->idx = 0; | ||
| 176 | break; | ||
| 162 | } | 177 | } |
| 163 | } | 178 | } |
| 164 | 179 | ||
| @@ -170,17 +185,17 @@ static void elo_process_data_3(struct elo *elo, unsigned char data) | |||
| 170 | 185 | ||
| 171 | switch (elo->idx++) { | 186 | switch (elo->idx++) { |
| 172 | 187 | ||
| 173 | case 0: | 188 | case 0: |
| 174 | if ((data & 0x7f) != 0x01) | 189 | if ((data & 0x7f) != 0x01) |
| 175 | elo->idx = 0; | ||
| 176 | break; | ||
| 177 | case 2: | ||
| 178 | input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); | ||
| 179 | input_report_abs(dev, ABS_X, elo->data[1]); | ||
| 180 | input_report_abs(dev, ABS_Y, elo->data[2]); | ||
| 181 | input_sync(dev); | ||
| 182 | elo->idx = 0; | 190 | elo->idx = 0; |
| 183 | break; | 191 | break; |
| 192 | case 2: | ||
| 193 | input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80)); | ||
| 194 | input_report_abs(dev, ABS_X, elo->data[1]); | ||
| 195 | input_report_abs(dev, ABS_Y, elo->data[2]); | ||
| 196 | input_sync(dev); | ||
| 197 | elo->idx = 0; | ||
| 198 | break; | ||
| 184 | } | 199 | } |
| 185 | } | 200 | } |
| 186 | 201 | ||
| @@ -189,19 +204,19 @@ static irqreturn_t elo_interrupt(struct serio *serio, | |||
| 189 | { | 204 | { |
| 190 | struct elo *elo = serio_get_drvdata(serio); | 205 | struct elo *elo = serio_get_drvdata(serio); |
| 191 | 206 | ||
| 192 | switch(elo->id) { | 207 | switch (elo->id) { |
| 193 | case 0: | 208 | case 0: |
| 194 | elo_process_data_10(elo, data); | 209 | elo_process_data_10(elo, data); |
| 195 | break; | 210 | break; |
| 196 | 211 | ||
| 197 | case 1: | 212 | case 1: |
| 198 | case 2: | 213 | case 2: |
| 199 | elo_process_data_6(elo, data); | 214 | elo_process_data_6(elo, data); |
| 200 | break; | 215 | break; |
| 201 | 216 | ||
| 202 | case 3: | 217 | case 3: |
| 203 | elo_process_data_3(elo, data); | 218 | elo_process_data_3(elo, data); |
| 204 | break; | 219 | break; |
| 205 | } | 220 | } |
| 206 | 221 | ||
| 207 | return IRQ_HANDLED; | 222 | return IRQ_HANDLED; |
| @@ -261,10 +276,10 @@ static int elo_setup_10(struct elo *elo) | |||
| 261 | if (packet[3] & ELO10_PRESSURE) | 276 | if (packet[3] & ELO10_PRESSURE) |
| 262 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); | 277 | input_set_abs_params(dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 263 | 278 | ||
| 264 | printk(KERN_INFO "elo: %sTouch touchscreen, fw: %02x.%02x, " | 279 | dev_info(&elo->serio->dev, |
| 265 | "features: 0x%02x, controller: 0x%02x\n", | 280 | "%sTouch touchscreen, fw: %02x.%02x, features: 0x%02x, controller: 0x%02x\n", |
| 266 | elo_types[(packet[1] -'0') & 0x03], | 281 | elo_types[(packet[1] -'0') & 0x03], |
| 267 | packet[5], packet[4], packet[3], packet[7]); | 282 | packet[5], packet[4], packet[3], packet[7]); |
| 268 | 283 | ||
| 269 | return 0; | 284 | return 0; |
| 270 | } | 285 | } |
| @@ -330,24 +345,24 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 330 | 345 | ||
| 331 | switch (elo->id) { | 346 | switch (elo->id) { |
| 332 | 347 | ||
| 333 | case 0: /* 10-byte protocol */ | 348 | case 0: /* 10-byte protocol */ |
| 334 | if (elo_setup_10(elo)) | 349 | if (elo_setup_10(elo)) |
| 335 | goto fail3; | 350 | goto fail3; |
| 336 | 351 | ||
| 337 | break; | 352 | break; |
| 338 | 353 | ||
| 339 | case 1: /* 6-byte protocol */ | 354 | case 1: /* 6-byte protocol */ |
| 340 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); | 355 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, 15, 0, 0); |
| 341 | 356 | ||
| 342 | case 2: /* 4-byte protocol */ | 357 | case 2: /* 4-byte protocol */ |
| 343 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); | 358 | input_set_abs_params(input_dev, ABS_X, 96, 4000, 0, 0); |
| 344 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); | 359 | input_set_abs_params(input_dev, ABS_Y, 96, 4000, 0, 0); |
| 345 | break; | 360 | break; |
| 346 | 361 | ||
| 347 | case 3: /* 3-byte protocol */ | 362 | case 3: /* 3-byte protocol */ |
| 348 | input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); | 363 | input_set_abs_params(input_dev, ABS_X, 0, 255, 0, 0); |
| 349 | input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); | 364 | input_set_abs_params(input_dev, ABS_Y, 0, 255, 0, 0); |
| 350 | break; | 365 | break; |
| 351 | } | 366 | } |
| 352 | 367 | ||
| 353 | err = input_register_device(elo->dev); | 368 | err = input_register_device(elo->dev); |
diff --git a/drivers/input/touchscreen/jornada720_ts.c b/drivers/input/touchscreen/jornada720_ts.c index c8b7e8a45c4d..4b0a061811ff 100644 --- a/drivers/input/touchscreen/jornada720_ts.c +++ b/drivers/input/touchscreen/jornada720_ts.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/input.h> | 18 | #include <linux/input.h> |
| 19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/slab.h> | ||
| 21 | 22 | ||
| 22 | #include <mach/hardware.h> | 23 | #include <mach/hardware.h> |
| 23 | #include <mach/jornada720.h> | 24 | #include <mach/jornada720.h> |
diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 8fc3b08deb3b..b6b8b1c7ecea 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | * | 14 | * |
| 15 | * Notes: | 15 | * Notes: |
| 16 | * This is a wm97xx extended touch driver to capture touch | 16 | * This is a wm97xx extended touch driver to capture touch |
| 17 | * data in a continuous manner on the Intel XScale archictecture | 17 | * data in a continuous manner on the Intel XScale architecture |
| 18 | * | 18 | * |
| 19 | * Features: | 19 | * Features: |
| 20 | * - codecs supported:- WM9705, WM9712, WM9713 | 20 | * - codecs supported:- WM9705, WM9712, WM9713 |
| @@ -131,7 +131,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) | |||
| 131 | /* When the AC97 queue has been drained we need to allow time | 131 | /* When the AC97 queue has been drained we need to allow time |
| 132 | * to buffer up samples otherwise we end up spinning polling | 132 | * to buffer up samples otherwise we end up spinning polling |
| 133 | * for samples. The controller can't have a suitably low | 133 | * for samples. The controller can't have a suitably low |
| 134 | * threashold set to use the notifications it gives. | 134 | * threshold set to use the notifications it gives. |
| 135 | */ | 135 | */ |
| 136 | schedule_timeout_uninterruptible(1); | 136 | schedule_timeout_uninterruptible(1); |
| 137 | 137 | ||
| @@ -153,6 +153,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) | |||
| 153 | if (pressure) | 153 | if (pressure) |
| 154 | p = MODR; | 154 | p = MODR; |
| 155 | 155 | ||
| 156 | dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", | ||
| 157 | x, y, p); | ||
| 158 | |||
| 156 | /* are samples valid */ | 159 | /* are samples valid */ |
| 157 | if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || | 160 | if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || |
| 158 | (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || | 161 | (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || |
diff --git a/drivers/input/touchscreen/mc13783_ts.c b/drivers/input/touchscreen/mc13783_ts.c new file mode 100644 index 000000000000..c5bc62d85bb6 --- /dev/null +++ b/drivers/input/touchscreen/mc13783_ts.c | |||
| @@ -0,0 +1,259 @@ | |||
| 1 | /* | ||
| 2 | * Driver for the Freescale Semiconductor MC13783 touchscreen. | ||
| 3 | * | ||
| 4 | * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. | ||
| 5 | * Copyright (C) 2009 Sascha Hauer, Pengutronix | ||
| 6 | * | ||
| 7 | * Initial development of this code was funded by | ||
| 8 | * Phytec Messtechnik GmbH, http://www.phytec.de/ | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License version 2 as published by | ||
| 12 | * the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/mfd/mc13783.h> | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/init.h> | ||
| 22 | |||
| 23 | #define MC13783_TS_NAME "mc13783-ts" | ||
| 24 | |||
| 25 | #define DEFAULT_SAMPLE_TOLERANCE 300 | ||
| 26 | |||
| 27 | static unsigned int sample_tolerance = DEFAULT_SAMPLE_TOLERANCE; | ||
| 28 | module_param(sample_tolerance, uint, S_IRUGO | S_IWUSR); | ||
| 29 | MODULE_PARM_DESC(sample_tolerance, | ||
| 30 | "If the minimal and maximal value read out for one axis (out " | ||
| 31 | "of three) differ by this value (default: " | ||
| 32 | __stringify(DEFAULT_SAMPLE_TOLERANCE) ") or more, the reading " | ||
| 33 | "is supposed to be wrong and is discarded. Set to 0 to " | ||
| 34 | "disable this check."); | ||
| 35 | |||
| 36 | struct mc13783_ts_priv { | ||
| 37 | struct input_dev *idev; | ||
| 38 | struct mc13783 *mc13783; | ||
| 39 | struct delayed_work work; | ||
| 40 | struct workqueue_struct *workq; | ||
| 41 | unsigned int sample[4]; | ||
| 42 | }; | ||
| 43 | |||
| 44 | static irqreturn_t mc13783_ts_handler(int irq, void *data) | ||
| 45 | { | ||
| 46 | struct mc13783_ts_priv *priv = data; | ||
| 47 | |||
| 48 | mc13783_irq_ack(priv->mc13783, irq); | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Kick off reading coordinates. Note that if work happens already | ||
| 52 | * be queued for future execution (it rearms itself) it will not | ||
| 53 | * be rescheduled for immediate execution here. However the rearm | ||
| 54 | * delay is HZ / 50 which is acceptable. | ||
| 55 | */ | ||
| 56 | queue_delayed_work(priv->workq, &priv->work, 0); | ||
| 57 | |||
| 58 | return IRQ_HANDLED; | ||
| 59 | } | ||
| 60 | |||
| 61 | #define sort3(a0, a1, a2) ({ \ | ||
| 62 | if (a0 > a1) \ | ||
| 63 | swap(a0, a1); \ | ||
| 64 | if (a1 > a2) \ | ||
| 65 | swap(a1, a2); \ | ||
| 66 | if (a0 > a1) \ | ||
| 67 | swap(a0, a1); \ | ||
| 68 | }) | ||
| 69 | |||
| 70 | static void mc13783_ts_report_sample(struct mc13783_ts_priv *priv) | ||
| 71 | { | ||
| 72 | struct input_dev *idev = priv->idev; | ||
| 73 | int x0, x1, x2, y0, y1, y2; | ||
| 74 | int cr0, cr1; | ||
| 75 | |||
| 76 | /* | ||
| 77 | * the values are 10-bit wide only, but the two least significant | ||
| 78 | * bits are for future 12 bit use and reading yields 0 | ||
| 79 | */ | ||
| 80 | x0 = priv->sample[0] & 0xfff; | ||
| 81 | x1 = priv->sample[1] & 0xfff; | ||
| 82 | x2 = priv->sample[2] & 0xfff; | ||
| 83 | y0 = priv->sample[3] & 0xfff; | ||
| 84 | y1 = (priv->sample[0] >> 12) & 0xfff; | ||
| 85 | y2 = (priv->sample[1] >> 12) & 0xfff; | ||
| 86 | cr0 = (priv->sample[2] >> 12) & 0xfff; | ||
| 87 | cr1 = (priv->sample[3] >> 12) & 0xfff; | ||
| 88 | |||
| 89 | dev_dbg(&idev->dev, | ||
| 90 | "x: (% 4d,% 4d,% 4d) y: (% 4d, % 4d,% 4d) cr: (% 4d, % 4d)\n", | ||
| 91 | x0, x1, x2, y0, y1, y2, cr0, cr1); | ||
| 92 | |||
| 93 | sort3(x0, x1, x2); | ||
| 94 | sort3(y0, y1, y2); | ||
| 95 | |||
| 96 | cr0 = (cr0 + cr1) / 2; | ||
| 97 | |||
| 98 | if (!cr0 || !sample_tolerance || | ||
| 99 | (x2 - x0 < sample_tolerance && | ||
| 100 | y2 - y0 < sample_tolerance)) { | ||
| 101 | /* report the median coordinate and average pressure */ | ||
| 102 | if (cr0) { | ||
| 103 | input_report_abs(idev, ABS_X, x1); | ||
| 104 | input_report_abs(idev, ABS_Y, y1); | ||
| 105 | |||
| 106 | dev_dbg(&idev->dev, "report (%d, %d, %d)\n", | ||
| 107 | x1, y1, 0x1000 - cr0); | ||
| 108 | queue_delayed_work(priv->workq, &priv->work, HZ / 50); | ||
| 109 | } else | ||
| 110 | dev_dbg(&idev->dev, "report release\n"); | ||
| 111 | |||
| 112 | input_report_abs(idev, ABS_PRESSURE, | ||
| 113 | cr0 ? 0x1000 - cr0 : cr0); | ||
| 114 | input_report_key(idev, BTN_TOUCH, cr0); | ||
| 115 | input_sync(idev); | ||
| 116 | } else | ||
| 117 | dev_dbg(&idev->dev, "discard event\n"); | ||
| 118 | } | ||
| 119 | |||
| 120 | static void mc13783_ts_work(struct work_struct *work) | ||
| 121 | { | ||
| 122 | struct mc13783_ts_priv *priv = | ||
| 123 | container_of(work, struct mc13783_ts_priv, work.work); | ||
| 124 | unsigned int mode = MC13783_ADC_MODE_TS; | ||
| 125 | unsigned int channel = 12; | ||
| 126 | |||
| 127 | if (mc13783_adc_do_conversion(priv->mc13783, | ||
| 128 | mode, channel, priv->sample) == 0) | ||
| 129 | mc13783_ts_report_sample(priv); | ||
| 130 | } | ||
| 131 | |||
| 132 | static int mc13783_ts_open(struct input_dev *dev) | ||
| 133 | { | ||
| 134 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | ||
| 135 | int ret; | ||
| 136 | |||
| 137 | mc13783_lock(priv->mc13783); | ||
| 138 | |||
| 139 | mc13783_irq_ack(priv->mc13783, MC13783_IRQ_TS); | ||
| 140 | |||
| 141 | ret = mc13783_irq_request(priv->mc13783, MC13783_IRQ_TS, | ||
| 142 | mc13783_ts_handler, MC13783_TS_NAME, priv); | ||
| 143 | if (ret) | ||
| 144 | goto out; | ||
| 145 | |||
| 146 | ret = mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, | ||
| 147 | MC13783_ADC0_TSMOD_MASK, MC13783_ADC0_TSMOD0); | ||
| 148 | if (ret) | ||
| 149 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); | ||
| 150 | out: | ||
| 151 | mc13783_unlock(priv->mc13783); | ||
| 152 | return ret; | ||
| 153 | } | ||
| 154 | |||
| 155 | static void mc13783_ts_close(struct input_dev *dev) | ||
| 156 | { | ||
| 157 | struct mc13783_ts_priv *priv = input_get_drvdata(dev); | ||
| 158 | |||
| 159 | mc13783_lock(priv->mc13783); | ||
| 160 | mc13783_reg_rmw(priv->mc13783, MC13783_ADC0, | ||
| 161 | MC13783_ADC0_TSMOD_MASK, 0); | ||
| 162 | mc13783_irq_free(priv->mc13783, MC13783_IRQ_TS, priv); | ||
| 163 | mc13783_unlock(priv->mc13783); | ||
| 164 | |||
| 165 | cancel_delayed_work_sync(&priv->work); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int __init mc13783_ts_probe(struct platform_device *pdev) | ||
| 169 | { | ||
| 170 | struct mc13783_ts_priv *priv; | ||
| 171 | struct input_dev *idev; | ||
| 172 | int ret = -ENOMEM; | ||
| 173 | |||
| 174 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 175 | idev = input_allocate_device(); | ||
| 176 | if (!priv || !idev) | ||
| 177 | goto err_free_mem; | ||
| 178 | |||
| 179 | INIT_DELAYED_WORK(&priv->work, mc13783_ts_work); | ||
| 180 | priv->mc13783 = dev_get_drvdata(pdev->dev.parent); | ||
| 181 | priv->idev = idev; | ||
| 182 | |||
| 183 | /* | ||
| 184 | * We need separate workqueue because mc13783_adc_do_conversion | ||
| 185 | * uses keventd and thus would deadlock. | ||
| 186 | */ | ||
| 187 | priv->workq = create_singlethread_workqueue("mc13783_ts"); | ||
| 188 | if (!priv->workq) | ||
| 189 | goto err_free_mem; | ||
| 190 | |||
| 191 | idev->name = MC13783_TS_NAME; | ||
| 192 | idev->dev.parent = &pdev->dev; | ||
| 193 | |||
| 194 | idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 195 | idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 196 | input_set_abs_params(idev, ABS_X, 0, 0xfff, 0, 0); | ||
| 197 | input_set_abs_params(idev, ABS_Y, 0, 0xfff, 0, 0); | ||
| 198 | input_set_abs_params(idev, ABS_PRESSURE, 0, 0xfff, 0, 0); | ||
| 199 | |||
| 200 | idev->open = mc13783_ts_open; | ||
| 201 | idev->close = mc13783_ts_close; | ||
| 202 | |||
| 203 | input_set_drvdata(idev, priv); | ||
| 204 | |||
| 205 | ret = input_register_device(priv->idev); | ||
| 206 | if (ret) { | ||
| 207 | dev_err(&pdev->dev, | ||
| 208 | "register input device failed with %d\n", ret); | ||
| 209 | goto err_destroy_wq; | ||
| 210 | } | ||
| 211 | |||
| 212 | platform_set_drvdata(pdev, priv); | ||
| 213 | return 0; | ||
| 214 | |||
| 215 | err_destroy_wq: | ||
| 216 | destroy_workqueue(priv->workq); | ||
| 217 | err_free_mem: | ||
| 218 | input_free_device(idev); | ||
| 219 | kfree(priv); | ||
| 220 | return ret; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int __devexit mc13783_ts_remove(struct platform_device *pdev) | ||
| 224 | { | ||
| 225 | struct mc13783_ts_priv *priv = platform_get_drvdata(pdev); | ||
| 226 | |||
| 227 | platform_set_drvdata(pdev, NULL); | ||
| 228 | |||
| 229 | destroy_workqueue(priv->workq); | ||
| 230 | input_unregister_device(priv->idev); | ||
| 231 | kfree(priv); | ||
| 232 | |||
| 233 | return 0; | ||
| 234 | } | ||
| 235 | |||
| 236 | static struct platform_driver mc13783_ts_driver = { | ||
| 237 | .remove = __devexit_p(mc13783_ts_remove), | ||
| 238 | .driver = { | ||
| 239 | .owner = THIS_MODULE, | ||
| 240 | .name = MC13783_TS_NAME, | ||
| 241 | }, | ||
| 242 | }; | ||
| 243 | |||
| 244 | static int __init mc13783_ts_init(void) | ||
| 245 | { | ||
| 246 | return platform_driver_probe(&mc13783_ts_driver, &mc13783_ts_probe); | ||
| 247 | } | ||
| 248 | module_init(mc13783_ts_init); | ||
| 249 | |||
| 250 | static void __exit mc13783_ts_exit(void) | ||
| 251 | { | ||
| 252 | platform_driver_unregister(&mc13783_ts_driver); | ||
| 253 | } | ||
| 254 | module_exit(mc13783_ts_exit); | ||
| 255 | |||
| 256 | MODULE_DESCRIPTION("MC13783 input touchscreen driver"); | ||
| 257 | MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); | ||
| 258 | MODULE_LICENSE("GPL v2"); | ||
| 259 | MODULE_ALIAS("platform:" MC13783_TS_NAME); | ||
diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index 4c28b89757f9..ce8ab0269f6f 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/input.h> | 21 | #include <linux/input.h> |
| 22 | #include <linux/irq.h> | 22 | #include <linux/irq.h> |
| 23 | #include <linux/slab.h> | ||
| 23 | 24 | ||
| 24 | /* Registers */ | 25 | /* Registers */ |
| 25 | #define MCS5000_TS_STATUS 0x00 | 26 | #define MCS5000_TS_STATUS 0x00 |
diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 141dd584330e..defe5dd3627c 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| 24 | #include <linux/input.h> | 24 | #include <linux/input.h> |
| 25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 26 | #include <linux/slab.h> | ||
| 26 | #include <asm/io.h> | 27 | #include <asm/io.h> |
| 27 | #include <linux/i2c.h> | 28 | #include <linux/i2c.h> |
| 28 | #include <linux/timer.h> | 29 | #include <linux/timer.h> |
diff --git a/drivers/input/touchscreen/pcap_ts.c b/drivers/input/touchscreen/pcap_ts.c index 67fcd33595de..ea6ef16e59b4 100644 --- a/drivers/input/touchscreen/pcap_ts.c +++ b/drivers/input/touchscreen/pcap_ts.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
| 16 | #include <linux/string.h> | 16 | #include <linux/string.h> |
| 17 | #include <linux/slab.h> | ||
| 17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
| 18 | #include <linux/timer.h> | 19 | #include <linux/timer.h> |
| 19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| @@ -233,7 +234,7 @@ static int pcap_ts_resume(struct device *dev) | |||
| 233 | return 0; | 234 | return 0; |
| 234 | } | 235 | } |
| 235 | 236 | ||
| 236 | static struct dev_pm_ops pcap_ts_pm_ops = { | 237 | static const struct dev_pm_ops pcap_ts_pm_ops = { |
| 237 | .suspend = pcap_ts_suspend, | 238 | .suspend = pcap_ts_suspend, |
| 238 | .resume = pcap_ts_resume, | 239 | .resume = pcap_ts_resume, |
| 239 | }; | 240 | }; |
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c new file mode 100644 index 000000000000..98a7d1279486 --- /dev/null +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
| @@ -0,0 +1,459 @@ | |||
| 1 | /* | ||
| 2 | * Samsung S3C24XX touchscreen driver | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the term of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 17 | * | ||
| 18 | * Copyright 2004 Arnaud Patard <arnaud.patard@rtp-net.org> | ||
| 19 | * Copyright 2008 Ben Dooks <ben-linux@fluff.org> | ||
| 20 | * Copyright 2009 Simtec Electronics <linux@simtec.co.uk> | ||
| 21 | * | ||
| 22 | * Additional work by Herbert Pötzl <herbert@13thfloor.at> and | ||
| 23 | * Harald Welte <laforge@openmoko.org> | ||
| 24 | */ | ||
| 25 | |||
| 26 | #include <linux/errno.h> | ||
| 27 | #include <linux/kernel.h> | ||
| 28 | #include <linux/module.h> | ||
| 29 | #include <linux/gpio.h> | ||
| 30 | #include <linux/input.h> | ||
| 31 | #include <linux/init.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/interrupt.h> | ||
| 34 | #include <linux/platform_device.h> | ||
| 35 | #include <linux/clk.h> | ||
| 36 | #include <linux/io.h> | ||
| 37 | |||
| 38 | #include <plat/adc.h> | ||
| 39 | #include <plat/regs-adc.h> | ||
| 40 | |||
| 41 | #include <mach/regs-gpio.h> | ||
| 42 | #include <mach/ts.h> | ||
| 43 | |||
| 44 | #define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0)) | ||
| 45 | |||
| 46 | #define INT_DOWN (0) | ||
| 47 | #define INT_UP (1 << 8) | ||
| 48 | |||
| 49 | #define WAIT4INT (S3C2410_ADCTSC_YM_SEN | \ | ||
| 50 | S3C2410_ADCTSC_YP_SEN | \ | ||
| 51 | S3C2410_ADCTSC_XP_SEN | \ | ||
| 52 | S3C2410_ADCTSC_XY_PST(3)) | ||
| 53 | |||
| 54 | #define AUTOPST (S3C2410_ADCTSC_YM_SEN | \ | ||
| 55 | S3C2410_ADCTSC_YP_SEN | \ | ||
| 56 | S3C2410_ADCTSC_XP_SEN | \ | ||
| 57 | S3C2410_ADCTSC_AUTO_PST | \ | ||
| 58 | S3C2410_ADCTSC_XY_PST(0)) | ||
| 59 | |||
| 60 | /* Per-touchscreen data. */ | ||
| 61 | |||
| 62 | /** | ||
| 63 | * struct s3c2410ts - driver touchscreen state. | ||
| 64 | * @client: The ADC client we registered with the core driver. | ||
| 65 | * @dev: The device we are bound to. | ||
| 66 | * @input: The input device we registered with the input subsystem. | ||
| 67 | * @clock: The clock for the adc. | ||
| 68 | * @io: Pointer to the IO base. | ||
| 69 | * @xp: The accumulated X position data. | ||
| 70 | * @yp: The accumulated Y position data. | ||
| 71 | * @irq_tc: The interrupt number for pen up/down interrupt | ||
| 72 | * @count: The number of samples collected. | ||
| 73 | * @shift: The log2 of the maximum count to read in one go. | ||
| 74 | */ | ||
| 75 | struct s3c2410ts { | ||
| 76 | struct s3c_adc_client *client; | ||
| 77 | struct device *dev; | ||
| 78 | struct input_dev *input; | ||
| 79 | struct clk *clock; | ||
| 80 | void __iomem *io; | ||
| 81 | unsigned long xp; | ||
| 82 | unsigned long yp; | ||
| 83 | int irq_tc; | ||
| 84 | int count; | ||
| 85 | int shift; | ||
| 86 | }; | ||
| 87 | |||
| 88 | static struct s3c2410ts ts; | ||
| 89 | |||
| 90 | /** | ||
| 91 | * s3c2410_ts_connect - configure gpio for s3c2410 systems | ||
| 92 | * | ||
| 93 | * Configure the GPIO for the S3C2410 system, where we have external FETs | ||
| 94 | * connected to the device (later systems such as the S3C2440 integrate | ||
| 95 | * these into the device). | ||
| 96 | */ | ||
| 97 | static inline void s3c2410_ts_connect(void) | ||
| 98 | { | ||
| 99 | s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON); | ||
| 100 | s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON); | ||
| 101 | s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON); | ||
| 102 | s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON); | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * get_down - return the down state of the pen | ||
| 107 | * @data0: The data read from ADCDAT0 register. | ||
| 108 | * @data1: The data read from ADCDAT1 register. | ||
| 109 | * | ||
| 110 | * Return non-zero if both readings show that the pen is down. | ||
| 111 | */ | ||
| 112 | static inline bool get_down(unsigned long data0, unsigned long data1) | ||
| 113 | { | ||
| 114 | /* returns true if both data values show stylus down */ | ||
| 115 | return (!(data0 & S3C2410_ADCDAT0_UPDOWN) && | ||
| 116 | !(data1 & S3C2410_ADCDAT0_UPDOWN)); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void touch_timer_fire(unsigned long data) | ||
| 120 | { | ||
| 121 | unsigned long data0; | ||
| 122 | unsigned long data1; | ||
| 123 | bool down; | ||
| 124 | |||
| 125 | data0 = readl(ts.io + S3C2410_ADCDAT0); | ||
| 126 | data1 = readl(ts.io + S3C2410_ADCDAT1); | ||
| 127 | |||
| 128 | down = get_down(data0, data1); | ||
| 129 | |||
| 130 | if (down) { | ||
| 131 | if (ts.count == (1 << ts.shift)) { | ||
| 132 | ts.xp >>= ts.shift; | ||
| 133 | ts.yp >>= ts.shift; | ||
| 134 | |||
| 135 | dev_dbg(ts.dev, "%s: X=%lu, Y=%lu, count=%d\n", | ||
| 136 | __func__, ts.xp, ts.yp, ts.count); | ||
| 137 | |||
| 138 | input_report_abs(ts.input, ABS_X, ts.xp); | ||
| 139 | input_report_abs(ts.input, ABS_Y, ts.yp); | ||
| 140 | |||
| 141 | input_report_key(ts.input, BTN_TOUCH, 1); | ||
| 142 | input_sync(ts.input); | ||
| 143 | |||
| 144 | ts.xp = 0; | ||
| 145 | ts.yp = 0; | ||
| 146 | ts.count = 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | s3c_adc_start(ts.client, 0, 1 << ts.shift); | ||
| 150 | } else { | ||
| 151 | ts.xp = 0; | ||
| 152 | ts.yp = 0; | ||
| 153 | ts.count = 0; | ||
| 154 | |||
| 155 | input_report_key(ts.input, BTN_TOUCH, 0); | ||
| 156 | input_sync(ts.input); | ||
| 157 | |||
| 158 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | static DEFINE_TIMER(touch_timer, touch_timer_fire, 0, 0); | ||
| 163 | |||
| 164 | /** | ||
| 165 | * stylus_irq - touchscreen stylus event interrupt | ||
| 166 | * @irq: The interrupt number | ||
| 167 | * @dev_id: The device ID. | ||
| 168 | * | ||
| 169 | * Called when the IRQ_TC is fired for a pen up or down event. | ||
| 170 | */ | ||
| 171 | static irqreturn_t stylus_irq(int irq, void *dev_id) | ||
| 172 | { | ||
| 173 | unsigned long data0; | ||
| 174 | unsigned long data1; | ||
| 175 | bool down; | ||
| 176 | |||
| 177 | data0 = readl(ts.io + S3C2410_ADCDAT0); | ||
| 178 | data1 = readl(ts.io + S3C2410_ADCDAT1); | ||
| 179 | |||
| 180 | down = get_down(data0, data1); | ||
| 181 | |||
| 182 | /* TODO we should never get an interrupt with down set while | ||
| 183 | * the timer is running, but maybe we ought to verify that the | ||
| 184 | * timer isn't running anyways. */ | ||
| 185 | |||
| 186 | if (down) | ||
| 187 | s3c_adc_start(ts.client, 0, 1 << ts.shift); | ||
| 188 | else | ||
| 189 | dev_info(ts.dev, "%s: count=%d\n", __func__, ts.count); | ||
| 190 | |||
| 191 | return IRQ_HANDLED; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * s3c24xx_ts_conversion - ADC conversion callback | ||
| 196 | * @client: The client that was registered with the ADC core. | ||
| 197 | * @data0: The reading from ADCDAT0. | ||
| 198 | * @data1: The reading from ADCDAT1. | ||
| 199 | * @left: The number of samples left. | ||
| 200 | * | ||
| 201 | * Called when a conversion has finished. | ||
| 202 | */ | ||
| 203 | static void s3c24xx_ts_conversion(struct s3c_adc_client *client, | ||
| 204 | unsigned data0, unsigned data1, | ||
| 205 | unsigned *left) | ||
| 206 | { | ||
| 207 | dev_dbg(ts.dev, "%s: %d,%d\n", __func__, data0, data1); | ||
| 208 | |||
| 209 | ts.xp += data0; | ||
| 210 | ts.yp += data1; | ||
| 211 | |||
| 212 | ts.count++; | ||
| 213 | |||
| 214 | /* From tests, it seems that it is unlikely to get a pen-up | ||
| 215 | * event during the conversion process which means we can | ||
| 216 | * ignore any pen-up events with less than the requisite | ||
| 217 | * count done. | ||
| 218 | * | ||
| 219 | * In several thousand conversions, no pen-ups where detected | ||
| 220 | * before count completed. | ||
| 221 | */ | ||
| 222 | } | ||
| 223 | |||
| 224 | /** | ||
| 225 | * s3c24xx_ts_select - ADC selection callback. | ||
| 226 | * @client: The client that was registered with the ADC core. | ||
| 227 | * @select: The reason for select. | ||
| 228 | * | ||
| 229 | * Called when the ADC core selects (or deslects) us as a client. | ||
| 230 | */ | ||
| 231 | static void s3c24xx_ts_select(struct s3c_adc_client *client, unsigned select) | ||
| 232 | { | ||
| 233 | if (select) { | ||
| 234 | writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST, | ||
| 235 | ts.io + S3C2410_ADCTSC); | ||
| 236 | } else { | ||
| 237 | mod_timer(&touch_timer, jiffies+1); | ||
| 238 | writel(WAIT4INT | INT_UP, ts.io + S3C2410_ADCTSC); | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | /** | ||
| 243 | * s3c2410ts_probe - device core probe entry point | ||
| 244 | * @pdev: The device we are being bound to. | ||
| 245 | * | ||
| 246 | * Initialise, find and allocate any resources we need to run and then | ||
| 247 | * register with the ADC and input systems. | ||
| 248 | */ | ||
| 249 | static int __devinit s3c2410ts_probe(struct platform_device *pdev) | ||
| 250 | { | ||
| 251 | struct s3c2410_ts_mach_info *info; | ||
| 252 | struct device *dev = &pdev->dev; | ||
| 253 | struct input_dev *input_dev; | ||
| 254 | struct resource *res; | ||
| 255 | int ret = -EINVAL; | ||
| 256 | |||
| 257 | /* Initialise input stuff */ | ||
| 258 | memset(&ts, 0, sizeof(struct s3c2410ts)); | ||
| 259 | |||
| 260 | ts.dev = dev; | ||
| 261 | |||
| 262 | info = pdev->dev.platform_data; | ||
| 263 | if (!info) { | ||
| 264 | dev_err(dev, "no platform data, cannot attach\n"); | ||
| 265 | return -EINVAL; | ||
| 266 | } | ||
| 267 | |||
| 268 | dev_dbg(dev, "initialising touchscreen\n"); | ||
| 269 | |||
| 270 | ts.clock = clk_get(dev, "adc"); | ||
| 271 | if (IS_ERR(ts.clock)) { | ||
| 272 | dev_err(dev, "cannot get adc clock source\n"); | ||
| 273 | return -ENOENT; | ||
| 274 | } | ||
| 275 | |||
| 276 | clk_enable(ts.clock); | ||
| 277 | dev_dbg(dev, "got and enabled clocks\n"); | ||
| 278 | |||
| 279 | ts.irq_tc = ret = platform_get_irq(pdev, 0); | ||
| 280 | if (ret < 0) { | ||
| 281 | dev_err(dev, "no resource for interrupt\n"); | ||
| 282 | goto err_clk; | ||
| 283 | } | ||
| 284 | |||
| 285 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 286 | if (!res) { | ||
| 287 | dev_err(dev, "no resource for registers\n"); | ||
| 288 | ret = -ENOENT; | ||
| 289 | goto err_clk; | ||
| 290 | } | ||
| 291 | |||
| 292 | ts.io = ioremap(res->start, resource_size(res)); | ||
| 293 | if (ts.io == NULL) { | ||
| 294 | dev_err(dev, "cannot map registers\n"); | ||
| 295 | ret = -ENOMEM; | ||
| 296 | goto err_clk; | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Configure the touchscreen external FETs on the S3C2410 */ | ||
| 300 | if (!platform_get_device_id(pdev)->driver_data) | ||
| 301 | s3c2410_ts_connect(); | ||
| 302 | |||
| 303 | ts.client = s3c_adc_register(pdev, s3c24xx_ts_select, | ||
| 304 | s3c24xx_ts_conversion, 1); | ||
| 305 | if (IS_ERR(ts.client)) { | ||
| 306 | dev_err(dev, "failed to register adc client\n"); | ||
| 307 | ret = PTR_ERR(ts.client); | ||
| 308 | goto err_iomap; | ||
| 309 | } | ||
| 310 | |||
| 311 | /* Initialise registers */ | ||
| 312 | if ((info->delay & 0xffff) > 0) | ||
| 313 | writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); | ||
| 314 | |||
| 315 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 316 | |||
| 317 | input_dev = input_allocate_device(); | ||
| 318 | if (!input_dev) { | ||
| 319 | dev_err(dev, "Unable to allocate the input device !!\n"); | ||
| 320 | ret = -ENOMEM; | ||
| 321 | goto err_iomap; | ||
| 322 | } | ||
| 323 | |||
| 324 | ts.input = input_dev; | ||
| 325 | ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 326 | ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 327 | input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0); | ||
| 328 | input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0); | ||
| 329 | |||
| 330 | ts.input->name = "S3C24XX TouchScreen"; | ||
| 331 | ts.input->id.bustype = BUS_HOST; | ||
| 332 | ts.input->id.vendor = 0xDEAD; | ||
| 333 | ts.input->id.product = 0xBEEF; | ||
| 334 | ts.input->id.version = 0x0102; | ||
| 335 | |||
| 336 | ts.shift = info->oversampling_shift; | ||
| 337 | |||
| 338 | ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED, | ||
| 339 | "s3c2410_ts_pen", ts.input); | ||
| 340 | if (ret) { | ||
| 341 | dev_err(dev, "cannot get TC interrupt\n"); | ||
| 342 | goto err_inputdev; | ||
| 343 | } | ||
| 344 | |||
| 345 | dev_info(dev, "driver attached, registering input device\n"); | ||
| 346 | |||
| 347 | /* All went ok, so register to the input system */ | ||
| 348 | ret = input_register_device(ts.input); | ||
| 349 | if (ret < 0) { | ||
| 350 | dev_err(dev, "failed to register input device\n"); | ||
| 351 | ret = -EIO; | ||
| 352 | goto err_tcirq; | ||
| 353 | } | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | |||
| 357 | err_tcirq: | ||
| 358 | free_irq(ts.irq_tc, ts.input); | ||
| 359 | err_inputdev: | ||
| 360 | input_unregister_device(ts.input); | ||
| 361 | err_iomap: | ||
| 362 | iounmap(ts.io); | ||
| 363 | err_clk: | ||
| 364 | del_timer_sync(&touch_timer); | ||
| 365 | clk_put(ts.clock); | ||
| 366 | return ret; | ||
| 367 | } | ||
| 368 | |||
| 369 | /** | ||
| 370 | * s3c2410ts_remove - device core removal entry point | ||
| 371 | * @pdev: The device we are being removed from. | ||
| 372 | * | ||
| 373 | * Free up our state ready to be removed. | ||
| 374 | */ | ||
| 375 | static int __devexit s3c2410ts_remove(struct platform_device *pdev) | ||
| 376 | { | ||
| 377 | free_irq(ts.irq_tc, ts.input); | ||
| 378 | del_timer_sync(&touch_timer); | ||
| 379 | |||
| 380 | clk_disable(ts.clock); | ||
| 381 | clk_put(ts.clock); | ||
| 382 | |||
| 383 | input_unregister_device(ts.input); | ||
| 384 | iounmap(ts.io); | ||
| 385 | |||
| 386 | return 0; | ||
| 387 | } | ||
| 388 | |||
| 389 | #ifdef CONFIG_PM | ||
| 390 | static int s3c2410ts_suspend(struct device *dev) | ||
| 391 | { | ||
| 392 | writel(TSC_SLEEP, ts.io + S3C2410_ADCTSC); | ||
| 393 | disable_irq(ts.irq_tc); | ||
| 394 | clk_disable(ts.clock); | ||
| 395 | |||
| 396 | return 0; | ||
| 397 | } | ||
| 398 | |||
| 399 | static int s3c2410ts_resume(struct device *dev) | ||
| 400 | { | ||
| 401 | struct platform_device *pdev = to_platform_device(dev); | ||
| 402 | struct s3c2410_ts_mach_info *info = pdev->dev.platform_data; | ||
| 403 | |||
| 404 | clk_enable(ts.clock); | ||
| 405 | enable_irq(ts.irq_tc); | ||
| 406 | |||
| 407 | /* Initialise registers */ | ||
| 408 | if ((info->delay & 0xffff) > 0) | ||
| 409 | writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY); | ||
| 410 | |||
| 411 | writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC); | ||
| 412 | |||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | static struct dev_pm_ops s3c_ts_pmops = { | ||
| 417 | .suspend = s3c2410ts_suspend, | ||
| 418 | .resume = s3c2410ts_resume, | ||
| 419 | }; | ||
| 420 | #endif | ||
| 421 | |||
| 422 | static struct platform_device_id s3cts_driver_ids[] = { | ||
| 423 | { "s3c2410-ts", 0 }, | ||
| 424 | { "s3c2440-ts", 1 }, | ||
| 425 | { } | ||
| 426 | }; | ||
| 427 | MODULE_DEVICE_TABLE(platform, s3cts_driver_ids); | ||
| 428 | |||
| 429 | static struct platform_driver s3c_ts_driver = { | ||
| 430 | .driver = { | ||
| 431 | .name = "s3c24xx-ts", | ||
| 432 | .owner = THIS_MODULE, | ||
| 433 | #ifdef CONFIG_PM | ||
| 434 | .pm = &s3c_ts_pmops, | ||
| 435 | #endif | ||
| 436 | }, | ||
| 437 | .id_table = s3cts_driver_ids, | ||
| 438 | .probe = s3c2410ts_probe, | ||
| 439 | .remove = __devexit_p(s3c2410ts_remove), | ||
| 440 | }; | ||
| 441 | |||
| 442 | static int __init s3c2410ts_init(void) | ||
| 443 | { | ||
| 444 | return platform_driver_register(&s3c_ts_driver); | ||
| 445 | } | ||
| 446 | |||
| 447 | static void __exit s3c2410ts_exit(void) | ||
| 448 | { | ||
| 449 | platform_driver_unregister(&s3c_ts_driver); | ||
| 450 | } | ||
| 451 | |||
| 452 | module_init(s3c2410ts_init); | ||
| 453 | module_exit(s3c2410ts_exit); | ||
| 454 | |||
| 455 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>, " | ||
| 456 | "Ben Dooks <ben@simtec.co.uk>, " | ||
| 457 | "Simtec Electronics <linux@simtec.co.uk>"); | ||
| 458 | MODULE_DESCRIPTION("S3C24XX Touchscreen driver"); | ||
| 459 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 7ef0d1420d3c..be23780e8a3e 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c | |||
| @@ -358,7 +358,7 @@ static int __devexit tsc2007_remove(struct i2c_client *client) | |||
| 358 | return 0; | 358 | return 0; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | static struct i2c_device_id tsc2007_idtable[] = { | 361 | static const struct i2c_device_id tsc2007_idtable[] = { |
| 362 | { "tsc2007", 0 }, | 362 | { "tsc2007", 0 }, |
| 363 | { } | 363 | { } |
| 364 | }; | 364 | }; |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index 095f84b1f56e..028a5363eea1 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
| 27 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
| 28 | #include <linux/suspend.h> | 28 | #include <linux/suspend.h> |
| 29 | #include <linux/slab.h> | ||
| 30 | #include <linux/kthread.h> | 29 | #include <linux/kthread.h> |
| 31 | #include <linux/freezer.h> | 30 | #include <linux/freezer.h> |
| 32 | #include <linux/ucb1400.h> | 31 | #include <linux/ucb1400.h> |
| @@ -355,10 +354,13 @@ static int ucb1400_ts_probe(struct platform_device *dev) | |||
| 355 | goto err; | 354 | goto err; |
| 356 | } | 355 | } |
| 357 | 356 | ||
| 358 | error = ucb1400_ts_detect_irq(ucb); | 357 | /* Only in case the IRQ line wasn't supplied, try detecting it */ |
| 359 | if (error) { | 358 | if (ucb->irq < 0) { |
| 360 | printk(KERN_ERR "UCB1400: IRQ probe failed\n"); | 359 | error = ucb1400_ts_detect_irq(ucb); |
| 361 | goto err_free_devs; | 360 | if (error) { |
| 361 | printk(KERN_ERR "UCB1400: IRQ probe failed\n"); | ||
| 362 | goto err_free_devs; | ||
| 363 | } | ||
| 362 | } | 364 | } |
| 363 | 365 | ||
| 364 | init_waitqueue_head(&ucb->ts_wait); | 366 | init_waitqueue_head(&ucb->ts_wait); |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 68ece5801a58..99330bbdbac7 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
| @@ -14,6 +14,8 @@ | |||
| 14 | * - General Touch | 14 | * - General Touch |
| 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets | 15 | * - GoTop Super_Q2/GogoPen/PenPower tablets |
| 16 | * - JASTEC USB touch controller/DigiTech DTR-02U | 16 | * - JASTEC USB touch controller/DigiTech DTR-02U |
| 17 | * - Zytronic capacitive touchscreen | ||
| 18 | * - NEXIO/iNexio | ||
| 17 | * | 19 | * |
| 18 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> | 20 | * Copyright (C) 2004-2007 by Daniel Ritz <daniel.ritz@gmx.ch> |
| 19 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) | 21 | * Copyright (C) by Todd E. Johnson (mtouchusb.c) |
| @@ -73,6 +75,15 @@ struct usbtouch_device_info { | |||
| 73 | int min_press, max_press; | 75 | int min_press, max_press; |
| 74 | int rept_size; | 76 | int rept_size; |
| 75 | 77 | ||
| 78 | /* | ||
| 79 | * Always service the USB devices irq not just when the input device is | ||
| 80 | * open. This is useful when devices have a watchdog which prevents us | ||
| 81 | * from periodically polling the device. Leave this unset unless your | ||
| 82 | * touchscreen device requires it, as it does consume more of the USB | ||
| 83 | * bandwidth. | ||
| 84 | */ | ||
| 85 | bool irq_always; | ||
| 86 | |||
| 76 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); | 87 | void (*process_pkt) (struct usbtouch_usb *usbtouch, unsigned char *pkt, int len); |
| 77 | 88 | ||
| 78 | /* | 89 | /* |
| @@ -85,6 +96,7 @@ struct usbtouch_device_info { | |||
| 85 | 96 | ||
| 86 | int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); | 97 | int (*read_data) (struct usbtouch_usb *usbtouch, unsigned char *pkt); |
| 87 | int (*init) (struct usbtouch_usb *usbtouch); | 98 | int (*init) (struct usbtouch_usb *usbtouch); |
| 99 | void (*exit) (struct usbtouch_usb *usbtouch); | ||
| 88 | }; | 100 | }; |
| 89 | 101 | ||
| 90 | /* a usbtouch device */ | 102 | /* a usbtouch device */ |
| @@ -94,11 +106,12 @@ struct usbtouch_usb { | |||
| 94 | unsigned char *buffer; | 106 | unsigned char *buffer; |
| 95 | int buf_len; | 107 | int buf_len; |
| 96 | struct urb *irq; | 108 | struct urb *irq; |
| 97 | struct usb_device *udev; | 109 | struct usb_interface *interface; |
| 98 | struct input_dev *input; | 110 | struct input_dev *input; |
| 99 | struct usbtouch_device_info *type; | 111 | struct usbtouch_device_info *type; |
| 100 | char name[128]; | 112 | char name[128]; |
| 101 | char phys[64]; | 113 | char phys[64]; |
| 114 | void *priv; | ||
| 102 | 115 | ||
| 103 | int x, y; | 116 | int x, y; |
| 104 | int touch, press; | 117 | int touch, press; |
| @@ -121,6 +134,9 @@ enum { | |||
| 121 | DEVTYPE_GOTOP, | 134 | DEVTYPE_GOTOP, |
| 122 | DEVTYPE_JASTEC, | 135 | DEVTYPE_JASTEC, |
| 123 | DEVTYPE_E2I, | 136 | DEVTYPE_E2I, |
| 137 | DEVTYPE_ZYTRONIC, | ||
| 138 | DEVTYPE_TC5UH, | ||
| 139 | DEVTYPE_NEXIO, | ||
| 124 | }; | 140 | }; |
| 125 | 141 | ||
| 126 | #define USB_DEVICE_HID_CLASS(vend, prod) \ | 142 | #define USB_DEVICE_HID_CLASS(vend, prod) \ |
| @@ -132,7 +148,7 @@ enum { | |||
| 132 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ | 148 | .bInterfaceClass = USB_INTERFACE_CLASS_HID, \ |
| 133 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE | 149 | .bInterfaceProtocol = USB_INTERFACE_PROTOCOL_MOUSE |
| 134 | 150 | ||
| 135 | static struct usb_device_id usbtouch_devices[] = { | 151 | static const struct usb_device_id usbtouch_devices[] = { |
| 136 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX | 152 | #ifdef CONFIG_TOUCHSCREEN_USB_EGALAX |
| 137 | /* ignore the HID capable devices, handled by usbhid */ | 153 | /* ignore the HID capable devices, handled by usbhid */ |
| 138 | {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, | 154 | {USB_DEVICE_HID_CLASS(0x0eef, 0x0001), .driver_info = DEVTYPE_IGNORE}, |
| @@ -201,6 +217,23 @@ static struct usb_device_id usbtouch_devices[] = { | |||
| 201 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I | 217 | #ifdef CONFIG_TOUCHSCREEN_USB_E2I |
| 202 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, | 218 | {USB_DEVICE(0x1ac7, 0x0001), .driver_info = DEVTYPE_E2I}, |
| 203 | #endif | 219 | #endif |
| 220 | |||
| 221 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 222 | {USB_DEVICE(0x14c8, 0x0003), .driver_info = DEVTYPE_ZYTRONIC}, | ||
| 223 | #endif | ||
| 224 | |||
| 225 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 226 | {USB_DEVICE(0x0664, 0x0309), .driver_info = DEVTYPE_TC5UH}, | ||
| 227 | #endif | ||
| 228 | |||
| 229 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | ||
| 230 | /* data interface only */ | ||
| 231 | {USB_DEVICE_AND_INTERFACE_INFO(0x10f0, 0x2002, 0x0a, 0x00, 0x00), | ||
| 232 | .driver_info = DEVTYPE_NEXIO}, | ||
| 233 | {USB_DEVICE_AND_INTERFACE_INFO(0x1870, 0x0001, 0x0a, 0x00, 0x00), | ||
| 234 | .driver_info = DEVTYPE_NEXIO}, | ||
| 235 | #endif | ||
| 236 | |||
| 204 | {} | 237 | {} |
| 205 | }; | 238 | }; |
| 206 | 239 | ||
| @@ -213,8 +246,9 @@ static struct usb_device_id usbtouch_devices[] = { | |||
| 213 | static int e2i_init(struct usbtouch_usb *usbtouch) | 246 | static int e2i_init(struct usbtouch_usb *usbtouch) |
| 214 | { | 247 | { |
| 215 | int ret; | 248 | int ret; |
| 249 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | ||
| 216 | 250 | ||
| 217 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 251 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 218 | 0x01, 0x02, 0x0000, 0x0081, | 252 | 0x01, 0x02, 0x0000, 0x0081, |
| 219 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 253 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 220 | 254 | ||
| @@ -323,8 +357,9 @@ static int mtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 323 | static int mtouch_init(struct usbtouch_usb *usbtouch) | 357 | static int mtouch_init(struct usbtouch_usb *usbtouch) |
| 324 | { | 358 | { |
| 325 | int ret, i; | 359 | int ret, i; |
| 360 | struct usb_device *udev = interface_to_usbdev(usbtouch->interface); | ||
| 326 | 361 | ||
| 327 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 362 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 328 | MTOUCHUSB_RESET, | 363 | MTOUCHUSB_RESET, |
| 329 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 364 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 330 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); | 365 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| @@ -335,7 +370,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) | |||
| 335 | msleep(150); | 370 | msleep(150); |
| 336 | 371 | ||
| 337 | for (i = 0; i < 3; i++) { | 372 | for (i = 0; i < 3; i++) { |
| 338 | ret = usb_control_msg(usbtouch->udev, usb_rcvctrlpipe(usbtouch->udev, 0), | 373 | ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), |
| 339 | MTOUCHUSB_ASYNC_REPORT, | 374 | MTOUCHUSB_ASYNC_REPORT, |
| 340 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 375 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 341 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); | 376 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| @@ -468,7 +503,7 @@ static int gunze_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 468 | 503 | ||
| 469 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) | 504 | static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) |
| 470 | { | 505 | { |
| 471 | struct usb_device *dev = usbtouch->udev; | 506 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); |
| 472 | int ret = -ENOMEM; | 507 | int ret = -ENOMEM; |
| 473 | unsigned char *buf; | 508 | unsigned char *buf; |
| 474 | 509 | ||
| @@ -538,6 +573,19 @@ static int irtouch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 538 | } | 573 | } |
| 539 | #endif | 574 | #endif |
| 540 | 575 | ||
| 576 | /***************************************************************************** | ||
| 577 | * ET&T TC5UH part | ||
| 578 | */ | ||
| 579 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 580 | static int tc5uh_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 581 | { | ||
| 582 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1]; | ||
| 583 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3]; | ||
| 584 | dev->touch = pkt[0] & 0x01; | ||
| 585 | |||
| 586 | return 1; | ||
| 587 | } | ||
| 588 | #endif | ||
| 541 | 589 | ||
| 542 | /***************************************************************************** | 590 | /***************************************************************************** |
| 543 | * IdealTEK URTC1000 Part | 591 | * IdealTEK URTC1000 Part |
| @@ -584,8 +632,8 @@ static int idealtek_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 584 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 632 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH |
| 585 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | 633 | static int general_touch_read_data(struct usbtouch_usb *dev, unsigned char *pkt) |
| 586 | { | 634 | { |
| 587 | dev->x = ((pkt[2] & 0x0F) << 8) | pkt[1] ; | 635 | dev->x = (pkt[2] << 8) | pkt[1]; |
| 588 | dev->y = ((pkt[4] & 0x0F) << 8) | pkt[3] ; | 636 | dev->y = (pkt[4] << 8) | pkt[3]; |
| 589 | dev->press = pkt[5] & 0xff; | 637 | dev->press = pkt[5] & 0xff; |
| 590 | dev->touch = pkt[0] & 0x01; | 638 | dev->touch = pkt[0] & 0x01; |
| 591 | 639 | ||
| @@ -621,6 +669,262 @@ static int jastec_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | |||
| 621 | } | 669 | } |
| 622 | #endif | 670 | #endif |
| 623 | 671 | ||
| 672 | /***************************************************************************** | ||
| 673 | * Zytronic Part | ||
| 674 | */ | ||
| 675 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 676 | static int zytronic_read_data(struct usbtouch_usb *dev, unsigned char *pkt) | ||
| 677 | { | ||
| 678 | switch (pkt[0]) { | ||
| 679 | case 0x3A: /* command response */ | ||
| 680 | dbg("%s: Command response %d", __func__, pkt[1]); | ||
| 681 | break; | ||
| 682 | |||
| 683 | case 0xC0: /* down */ | ||
| 684 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | ||
| 685 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | ||
| 686 | dev->touch = 1; | ||
| 687 | dbg("%s: down %d,%d", __func__, dev->x, dev->y); | ||
| 688 | return 1; | ||
| 689 | |||
| 690 | case 0x80: /* up */ | ||
| 691 | dev->x = (pkt[1] & 0x7f) | ((pkt[2] & 0x07) << 7); | ||
| 692 | dev->y = (pkt[3] & 0x7f) | ((pkt[4] & 0x07) << 7); | ||
| 693 | dev->touch = 0; | ||
| 694 | dbg("%s: up %d,%d", __func__, dev->x, dev->y); | ||
| 695 | return 1; | ||
| 696 | |||
| 697 | default: | ||
| 698 | dbg("%s: Unknown return %d", __func__, pkt[0]); | ||
| 699 | break; | ||
| 700 | } | ||
| 701 | |||
| 702 | return 0; | ||
| 703 | } | ||
| 704 | #endif | ||
| 705 | |||
| 706 | /***************************************************************************** | ||
| 707 | * NEXIO Part | ||
| 708 | */ | ||
| 709 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | ||
| 710 | |||
| 711 | #define NEXIO_TIMEOUT 5000 | ||
| 712 | #define NEXIO_BUFSIZE 1024 | ||
| 713 | #define NEXIO_THRESHOLD 50 | ||
| 714 | |||
| 715 | struct nexio_priv { | ||
| 716 | struct urb *ack; | ||
| 717 | unsigned char *ack_buf; | ||
| 718 | }; | ||
| 719 | |||
| 720 | struct nexio_touch_packet { | ||
| 721 | u8 flags; /* 0xe1 = touch, 0xe1 = release */ | ||
| 722 | __be16 data_len; /* total bytes of touch data */ | ||
| 723 | __be16 x_len; /* bytes for X axis */ | ||
| 724 | __be16 y_len; /* bytes for Y axis */ | ||
| 725 | u8 data[]; | ||
| 726 | } __attribute__ ((packed)); | ||
| 727 | |||
| 728 | static unsigned char nexio_ack_pkt[2] = { 0xaa, 0x02 }; | ||
| 729 | static unsigned char nexio_init_pkt[4] = { 0x82, 0x04, 0x0a, 0x0f }; | ||
| 730 | |||
| 731 | static void nexio_ack_complete(struct urb *urb) | ||
| 732 | { | ||
| 733 | } | ||
| 734 | |||
| 735 | static int nexio_init(struct usbtouch_usb *usbtouch) | ||
| 736 | { | ||
| 737 | struct usb_device *dev = interface_to_usbdev(usbtouch->interface); | ||
| 738 | struct usb_host_interface *interface = usbtouch->interface->cur_altsetting; | ||
| 739 | struct nexio_priv *priv; | ||
| 740 | int ret = -ENOMEM; | ||
| 741 | int actual_len, i; | ||
| 742 | unsigned char *buf; | ||
| 743 | char *firmware_ver = NULL, *device_name = NULL; | ||
| 744 | int input_ep = 0, output_ep = 0; | ||
| 745 | |||
| 746 | /* find first input and output endpoint */ | ||
| 747 | for (i = 0; i < interface->desc.bNumEndpoints; i++) { | ||
| 748 | if (!input_ep && | ||
| 749 | usb_endpoint_dir_in(&interface->endpoint[i].desc)) | ||
| 750 | input_ep = interface->endpoint[i].desc.bEndpointAddress; | ||
| 751 | if (!output_ep && | ||
| 752 | usb_endpoint_dir_out(&interface->endpoint[i].desc)) | ||
| 753 | output_ep = interface->endpoint[i].desc.bEndpointAddress; | ||
| 754 | } | ||
| 755 | if (!input_ep || !output_ep) | ||
| 756 | return -ENXIO; | ||
| 757 | |||
| 758 | buf = kmalloc(NEXIO_BUFSIZE, GFP_KERNEL); | ||
| 759 | if (!buf) | ||
| 760 | goto out_buf; | ||
| 761 | |||
| 762 | /* two empty reads */ | ||
| 763 | for (i = 0; i < 2; i++) { | ||
| 764 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | ||
| 765 | buf, NEXIO_BUFSIZE, &actual_len, | ||
| 766 | NEXIO_TIMEOUT); | ||
| 767 | if (ret < 0) | ||
| 768 | goto out_buf; | ||
| 769 | } | ||
| 770 | |||
| 771 | /* send init command */ | ||
| 772 | memcpy(buf, nexio_init_pkt, sizeof(nexio_init_pkt)); | ||
| 773 | ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, output_ep), | ||
| 774 | buf, sizeof(nexio_init_pkt), &actual_len, | ||
| 775 | NEXIO_TIMEOUT); | ||
| 776 | if (ret < 0) | ||
| 777 | goto out_buf; | ||
| 778 | |||
| 779 | /* read replies */ | ||
| 780 | for (i = 0; i < 3; i++) { | ||
| 781 | memset(buf, 0, NEXIO_BUFSIZE); | ||
| 782 | ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, input_ep), | ||
| 783 | buf, NEXIO_BUFSIZE, &actual_len, | ||
| 784 | NEXIO_TIMEOUT); | ||
| 785 | if (ret < 0 || actual_len < 1 || buf[1] != actual_len) | ||
| 786 | continue; | ||
| 787 | switch (buf[0]) { | ||
| 788 | case 0x83: /* firmware version */ | ||
| 789 | if (!firmware_ver) | ||
| 790 | firmware_ver = kstrdup(&buf[2], GFP_KERNEL); | ||
| 791 | break; | ||
| 792 | case 0x84: /* device name */ | ||
| 793 | if (!device_name) | ||
| 794 | device_name = kstrdup(&buf[2], GFP_KERNEL); | ||
| 795 | break; | ||
| 796 | } | ||
| 797 | } | ||
| 798 | |||
| 799 | printk(KERN_INFO "Nexio device: %s, firmware version: %s\n", | ||
| 800 | device_name, firmware_ver); | ||
| 801 | |||
| 802 | kfree(firmware_ver); | ||
| 803 | kfree(device_name); | ||
| 804 | |||
| 805 | /* prepare ACK URB */ | ||
| 806 | ret = -ENOMEM; | ||
| 807 | |||
| 808 | usbtouch->priv = kmalloc(sizeof(struct nexio_priv), GFP_KERNEL); | ||
| 809 | if (!usbtouch->priv) | ||
| 810 | goto out_buf; | ||
| 811 | |||
| 812 | priv = usbtouch->priv; | ||
| 813 | |||
| 814 | priv->ack_buf = kmalloc(sizeof(nexio_ack_pkt), GFP_KERNEL); | ||
| 815 | if (!priv->ack_buf) | ||
| 816 | goto err_priv; | ||
| 817 | |||
| 818 | memcpy(priv->ack_buf, nexio_ack_pkt, sizeof(nexio_ack_pkt)); | ||
| 819 | |||
| 820 | priv->ack = usb_alloc_urb(0, GFP_KERNEL); | ||
| 821 | if (!priv->ack) { | ||
| 822 | dbg("%s - usb_alloc_urb failed: usbtouch->ack", __func__); | ||
| 823 | goto err_ack_buf; | ||
| 824 | } | ||
| 825 | |||
| 826 | usb_fill_bulk_urb(priv->ack, dev, usb_sndbulkpipe(dev, output_ep), | ||
| 827 | priv->ack_buf, sizeof(nexio_ack_pkt), | ||
| 828 | nexio_ack_complete, usbtouch); | ||
| 829 | ret = 0; | ||
| 830 | goto out_buf; | ||
| 831 | |||
| 832 | err_ack_buf: | ||
| 833 | kfree(priv->ack_buf); | ||
| 834 | err_priv: | ||
| 835 | kfree(priv); | ||
| 836 | out_buf: | ||
| 837 | kfree(buf); | ||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | |||
| 841 | static void nexio_exit(struct usbtouch_usb *usbtouch) | ||
| 842 | { | ||
| 843 | struct nexio_priv *priv = usbtouch->priv; | ||
| 844 | |||
| 845 | usb_kill_urb(priv->ack); | ||
| 846 | usb_free_urb(priv->ack); | ||
| 847 | kfree(priv->ack_buf); | ||
| 848 | kfree(priv); | ||
| 849 | } | ||
| 850 | |||
| 851 | static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | ||
| 852 | { | ||
| 853 | int x, y, begin_x, begin_y, end_x, end_y, w, h, ret; | ||
| 854 | struct nexio_touch_packet *packet = (void *) pkt; | ||
| 855 | struct nexio_priv *priv = usbtouch->priv; | ||
| 856 | |||
| 857 | /* got touch data? */ | ||
| 858 | if ((pkt[0] & 0xe0) != 0xe0) | ||
| 859 | return 0; | ||
| 860 | |||
| 861 | /* send ACK */ | ||
| 862 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); | ||
| 863 | |||
| 864 | if (!usbtouch->type->max_xc) { | ||
| 865 | usbtouch->type->max_xc = 2 * be16_to_cpu(packet->x_len); | ||
| 866 | input_set_abs_params(usbtouch->input, ABS_X, 0, | ||
| 867 | 2 * be16_to_cpu(packet->x_len), 0, 0); | ||
| 868 | usbtouch->type->max_yc = 2 * be16_to_cpu(packet->y_len); | ||
| 869 | input_set_abs_params(usbtouch->input, ABS_Y, 0, | ||
| 870 | 2 * be16_to_cpu(packet->y_len), 0, 0); | ||
| 871 | } | ||
| 872 | /* | ||
| 873 | * The device reports state of IR sensors on X and Y axes. | ||
| 874 | * Each byte represents "darkness" percentage (0-100) of one element. | ||
| 875 | * 17" touchscreen reports only 64 x 52 bytes so the resolution is low. | ||
| 876 | * This also means that there's a limited multi-touch capability but | ||
| 877 | * it's disabled (and untested) here as there's no X driver for that. | ||
| 878 | */ | ||
| 879 | begin_x = end_x = begin_y = end_y = -1; | ||
| 880 | for (x = 0; x < be16_to_cpu(packet->x_len); x++) { | ||
| 881 | if (begin_x == -1 && packet->data[x] > NEXIO_THRESHOLD) { | ||
| 882 | begin_x = x; | ||
| 883 | continue; | ||
| 884 | } | ||
| 885 | if (end_x == -1 && begin_x != -1 && packet->data[x] < NEXIO_THRESHOLD) { | ||
| 886 | end_x = x - 1; | ||
| 887 | for (y = be16_to_cpu(packet->x_len); | ||
| 888 | y < be16_to_cpu(packet->data_len); y++) { | ||
| 889 | if (begin_y == -1 && packet->data[y] > NEXIO_THRESHOLD) { | ||
| 890 | begin_y = y - be16_to_cpu(packet->x_len); | ||
| 891 | continue; | ||
| 892 | } | ||
| 893 | if (end_y == -1 && | ||
| 894 | begin_y != -1 && packet->data[y] < NEXIO_THRESHOLD) { | ||
| 895 | end_y = y - 1 - be16_to_cpu(packet->x_len); | ||
| 896 | w = end_x - begin_x; | ||
| 897 | h = end_y - begin_y; | ||
| 898 | #if 0 | ||
| 899 | /* multi-touch */ | ||
| 900 | input_report_abs(usbtouch->input, | ||
| 901 | ABS_MT_TOUCH_MAJOR, max(w,h)); | ||
| 902 | input_report_abs(usbtouch->input, | ||
| 903 | ABS_MT_TOUCH_MINOR, min(x,h)); | ||
| 904 | input_report_abs(usbtouch->input, | ||
| 905 | ABS_MT_POSITION_X, 2*begin_x+w); | ||
| 906 | input_report_abs(usbtouch->input, | ||
| 907 | ABS_MT_POSITION_Y, 2*begin_y+h); | ||
| 908 | input_report_abs(usbtouch->input, | ||
| 909 | ABS_MT_ORIENTATION, w > h); | ||
| 910 | input_mt_sync(usbtouch->input); | ||
| 911 | #endif | ||
| 912 | /* single touch */ | ||
| 913 | usbtouch->x = 2 * begin_x + w; | ||
| 914 | usbtouch->y = 2 * begin_y + h; | ||
| 915 | usbtouch->touch = packet->flags & 0x01; | ||
| 916 | begin_y = end_y = -1; | ||
| 917 | return 1; | ||
| 918 | } | ||
| 919 | } | ||
| 920 | begin_x = end_x = -1; | ||
| 921 | } | ||
| 922 | |||
| 923 | } | ||
| 924 | return 0; | ||
| 925 | } | ||
| 926 | #endif | ||
| 927 | |||
| 624 | 928 | ||
| 625 | /***************************************************************************** | 929 | /***************************************************************************** |
| 626 | * the different device descriptors | 930 | * the different device descriptors |
| @@ -742,9 +1046,9 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 742 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH | 1046 | #ifdef CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH |
| 743 | [DEVTYPE_GENERAL_TOUCH] = { | 1047 | [DEVTYPE_GENERAL_TOUCH] = { |
| 744 | .min_xc = 0x0, | 1048 | .min_xc = 0x0, |
| 745 | .max_xc = 0x0500, | 1049 | .max_xc = 0x7fff, |
| 746 | .min_yc = 0x0, | 1050 | .min_yc = 0x0, |
| 747 | .max_yc = 0x0500, | 1051 | .max_yc = 0x7fff, |
| 748 | .rept_size = 7, | 1052 | .rept_size = 7, |
| 749 | .read_data = general_touch_read_data, | 1053 | .read_data = general_touch_read_data, |
| 750 | }, | 1054 | }, |
| @@ -783,6 +1087,39 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
| 783 | .read_data = e2i_read_data, | 1087 | .read_data = e2i_read_data, |
| 784 | }, | 1088 | }, |
| 785 | #endif | 1089 | #endif |
| 1090 | |||
| 1091 | #ifdef CONFIG_TOUCHSCREEN_USB_ZYTRONIC | ||
| 1092 | [DEVTYPE_ZYTRONIC] = { | ||
| 1093 | .min_xc = 0x0, | ||
| 1094 | .max_xc = 0x03ff, | ||
| 1095 | .min_yc = 0x0, | ||
| 1096 | .max_yc = 0x03ff, | ||
| 1097 | .rept_size = 5, | ||
| 1098 | .read_data = zytronic_read_data, | ||
| 1099 | .irq_always = true, | ||
| 1100 | }, | ||
| 1101 | #endif | ||
| 1102 | |||
| 1103 | #ifdef CONFIG_TOUCHSCREEN_USB_ETT_TC5UH | ||
| 1104 | [DEVTYPE_TC5UH] = { | ||
| 1105 | .min_xc = 0x0, | ||
| 1106 | .max_xc = 0x0fff, | ||
| 1107 | .min_yc = 0x0, | ||
| 1108 | .max_yc = 0x0fff, | ||
| 1109 | .rept_size = 5, | ||
| 1110 | .read_data = tc5uh_read_data, | ||
| 1111 | }, | ||
| 1112 | #endif | ||
| 1113 | |||
| 1114 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | ||
| 1115 | [DEVTYPE_NEXIO] = { | ||
| 1116 | .rept_size = 128, | ||
| 1117 | .irq_always = true, | ||
| 1118 | .read_data = nexio_read_data, | ||
| 1119 | .init = nexio_init, | ||
| 1120 | .exit = nexio_exit, | ||
| 1121 | }, | ||
| 1122 | #endif | ||
| 786 | }; | 1123 | }; |
| 787 | 1124 | ||
| 788 | 1125 | ||
| @@ -908,6 +1245,7 @@ static void usbtouch_irq(struct urb *urb) | |||
| 908 | case -ECONNRESET: | 1245 | case -ECONNRESET: |
| 909 | case -ENOENT: | 1246 | case -ENOENT: |
| 910 | case -ESHUTDOWN: | 1247 | case -ESHUTDOWN: |
| 1248 | case -EPIPE: | ||
| 911 | /* this urb is terminated, clean up */ | 1249 | /* this urb is terminated, clean up */ |
| 912 | dbg("%s - urb shutting down with status: %d", | 1250 | dbg("%s - urb shutting down with status: %d", |
| 913 | __func__, urb->status); | 1251 | __func__, urb->status); |
| @@ -931,10 +1269,12 @@ static int usbtouch_open(struct input_dev *input) | |||
| 931 | { | 1269 | { |
| 932 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 1270 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
| 933 | 1271 | ||
| 934 | usbtouch->irq->dev = usbtouch->udev; | 1272 | usbtouch->irq->dev = interface_to_usbdev(usbtouch->interface); |
| 935 | 1273 | ||
| 936 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) | 1274 | if (!usbtouch->type->irq_always) { |
| 937 | return -EIO; | 1275 | if (usb_submit_urb(usbtouch->irq, GFP_KERNEL)) |
| 1276 | return -EIO; | ||
| 1277 | } | ||
| 938 | 1278 | ||
| 939 | return 0; | 1279 | return 0; |
| 940 | } | 1280 | } |
| @@ -943,7 +1283,8 @@ static void usbtouch_close(struct input_dev *input) | |||
| 943 | { | 1283 | { |
| 944 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); | 1284 | struct usbtouch_usb *usbtouch = input_get_drvdata(input); |
| 945 | 1285 | ||
| 946 | usb_kill_urb(usbtouch->irq); | 1286 | if (!usbtouch->type->irq_always) |
| 1287 | usb_kill_urb(usbtouch->irq); | ||
| 947 | } | 1288 | } |
| 948 | 1289 | ||
| 949 | 1290 | ||
| @@ -955,13 +1296,23 @@ static void usbtouch_free_buffers(struct usb_device *udev, | |||
| 955 | kfree(usbtouch->buffer); | 1296 | kfree(usbtouch->buffer); |
| 956 | } | 1297 | } |
| 957 | 1298 | ||
| 1299 | static struct usb_endpoint_descriptor * | ||
| 1300 | usbtouch_get_input_endpoint(struct usb_host_interface *interface) | ||
| 1301 | { | ||
| 1302 | int i; | ||
| 1303 | |||
| 1304 | for (i = 0; i < interface->desc.bNumEndpoints; i++) | ||
| 1305 | if (usb_endpoint_dir_in(&interface->endpoint[i].desc)) | ||
| 1306 | return &interface->endpoint[i].desc; | ||
| 1307 | |||
| 1308 | return NULL; | ||
| 1309 | } | ||
| 958 | 1310 | ||
| 959 | static int usbtouch_probe(struct usb_interface *intf, | 1311 | static int usbtouch_probe(struct usb_interface *intf, |
| 960 | const struct usb_device_id *id) | 1312 | const struct usb_device_id *id) |
| 961 | { | 1313 | { |
| 962 | struct usbtouch_usb *usbtouch; | 1314 | struct usbtouch_usb *usbtouch; |
| 963 | struct input_dev *input_dev; | 1315 | struct input_dev *input_dev; |
| 964 | struct usb_host_interface *interface; | ||
| 965 | struct usb_endpoint_descriptor *endpoint; | 1316 | struct usb_endpoint_descriptor *endpoint; |
| 966 | struct usb_device *udev = interface_to_usbdev(intf); | 1317 | struct usb_device *udev = interface_to_usbdev(intf); |
| 967 | struct usbtouch_device_info *type; | 1318 | struct usbtouch_device_info *type; |
| @@ -971,8 +1322,9 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 971 | if (id->driver_info == DEVTYPE_IGNORE) | 1322 | if (id->driver_info == DEVTYPE_IGNORE) |
| 972 | return -ENODEV; | 1323 | return -ENODEV; |
| 973 | 1324 | ||
| 974 | interface = intf->cur_altsetting; | 1325 | endpoint = usbtouch_get_input_endpoint(intf->cur_altsetting); |
| 975 | endpoint = &interface->endpoint[0].desc; | 1326 | if (!endpoint) |
| 1327 | return -ENXIO; | ||
| 976 | 1328 | ||
| 977 | usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); | 1329 | usbtouch = kzalloc(sizeof(struct usbtouch_usb), GFP_KERNEL); |
| 978 | input_dev = input_allocate_device(); | 1330 | input_dev = input_allocate_device(); |
| @@ -1001,7 +1353,7 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1001 | goto out_free_buffers; | 1353 | goto out_free_buffers; |
| 1002 | } | 1354 | } |
| 1003 | 1355 | ||
| 1004 | usbtouch->udev = udev; | 1356 | usbtouch->interface = intf; |
| 1005 | usbtouch->input = input_dev; | 1357 | usbtouch->input = input_dev; |
| 1006 | 1358 | ||
| 1007 | if (udev->manufacturer) | 1359 | if (udev->manufacturer) |
| @@ -1040,12 +1392,18 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1040 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, | 1392 | input_set_abs_params(input_dev, ABS_PRESSURE, type->min_press, |
| 1041 | type->max_press, 0, 0); | 1393 | type->max_press, 0, 0); |
| 1042 | 1394 | ||
| 1043 | usb_fill_int_urb(usbtouch->irq, usbtouch->udev, | 1395 | if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) |
| 1044 | usb_rcvintpipe(usbtouch->udev, endpoint->bEndpointAddress), | 1396 | usb_fill_int_urb(usbtouch->irq, udev, |
| 1397 | usb_rcvintpipe(udev, endpoint->bEndpointAddress), | ||
| 1045 | usbtouch->data, type->rept_size, | 1398 | usbtouch->data, type->rept_size, |
| 1046 | usbtouch_irq, usbtouch, endpoint->bInterval); | 1399 | usbtouch_irq, usbtouch, endpoint->bInterval); |
| 1400 | else | ||
| 1401 | usb_fill_bulk_urb(usbtouch->irq, udev, | ||
| 1402 | usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), | ||
| 1403 | usbtouch->data, type->rept_size, | ||
| 1404 | usbtouch_irq, usbtouch); | ||
| 1047 | 1405 | ||
| 1048 | usbtouch->irq->dev = usbtouch->udev; | 1406 | usbtouch->irq->dev = udev; |
| 1049 | usbtouch->irq->transfer_dma = usbtouch->data_dma; | 1407 | usbtouch->irq->transfer_dma = usbtouch->data_dma; |
| 1050 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1408 | usbtouch->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 1051 | 1409 | ||
| @@ -1054,20 +1412,37 @@ static int usbtouch_probe(struct usb_interface *intf, | |||
| 1054 | err = type->init(usbtouch); | 1412 | err = type->init(usbtouch); |
| 1055 | if (err) { | 1413 | if (err) { |
| 1056 | dbg("%s - type->init() failed, err: %d", __func__, err); | 1414 | dbg("%s - type->init() failed, err: %d", __func__, err); |
| 1057 | goto out_free_buffers; | 1415 | goto out_free_urb; |
| 1058 | } | 1416 | } |
| 1059 | } | 1417 | } |
| 1060 | 1418 | ||
| 1061 | err = input_register_device(usbtouch->input); | 1419 | err = input_register_device(usbtouch->input); |
| 1062 | if (err) { | 1420 | if (err) { |
| 1063 | dbg("%s - input_register_device failed, err: %d", __func__, err); | 1421 | dbg("%s - input_register_device failed, err: %d", __func__, err); |
| 1064 | goto out_free_buffers; | 1422 | goto out_do_exit; |
| 1065 | } | 1423 | } |
| 1066 | 1424 | ||
| 1067 | usb_set_intfdata(intf, usbtouch); | 1425 | usb_set_intfdata(intf, usbtouch); |
| 1068 | 1426 | ||
| 1427 | if (usbtouch->type->irq_always) { | ||
| 1428 | err = usb_submit_urb(usbtouch->irq, GFP_KERNEL); | ||
| 1429 | if (err) { | ||
| 1430 | err("%s - usb_submit_urb failed with result: %d", | ||
| 1431 | __func__, err); | ||
| 1432 | goto out_unregister_input; | ||
| 1433 | } | ||
| 1434 | } | ||
| 1435 | |||
| 1069 | return 0; | 1436 | return 0; |
| 1070 | 1437 | ||
| 1438 | out_unregister_input: | ||
| 1439 | input_unregister_device(input_dev); | ||
| 1440 | input_dev = NULL; | ||
| 1441 | out_do_exit: | ||
| 1442 | if (type->exit) | ||
| 1443 | type->exit(usbtouch); | ||
| 1444 | out_free_urb: | ||
| 1445 | usb_free_urb(usbtouch->irq); | ||
| 1071 | out_free_buffers: | 1446 | out_free_buffers: |
| 1072 | usbtouch_free_buffers(udev, usbtouch); | 1447 | usbtouch_free_buffers(udev, usbtouch); |
| 1073 | out_free: | 1448 | out_free: |
| @@ -1087,9 +1462,11 @@ static void usbtouch_disconnect(struct usb_interface *intf) | |||
| 1087 | 1462 | ||
| 1088 | dbg("%s - usbtouch is initialized, cleaning up", __func__); | 1463 | dbg("%s - usbtouch is initialized, cleaning up", __func__); |
| 1089 | usb_set_intfdata(intf, NULL); | 1464 | usb_set_intfdata(intf, NULL); |
| 1090 | usb_kill_urb(usbtouch->irq); | 1465 | /* this will stop IO via close */ |
| 1091 | input_unregister_device(usbtouch->input); | 1466 | input_unregister_device(usbtouch->input); |
| 1092 | usb_free_urb(usbtouch->irq); | 1467 | usb_free_urb(usbtouch->irq); |
| 1468 | if (usbtouch->type->exit) | ||
| 1469 | usbtouch->type->exit(usbtouch); | ||
| 1093 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); | 1470 | usbtouch_free_buffers(interface_to_usbdev(intf), usbtouch); |
| 1094 | kfree(usbtouch); | 1471 | kfree(usbtouch); |
| 1095 | } | 1472 | } |
diff --git a/drivers/input/touchscreen/w90p910_ts.c b/drivers/input/touchscreen/w90p910_ts.c index 6ccbdbbf33fe..cc18265be1a8 100644 --- a/drivers/input/touchscreen/w90p910_ts.c +++ b/drivers/input/touchscreen/w90p910_ts.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
| 17 | #include <linux/input.h> | 17 | #include <linux/input.h> |
| 18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
| 19 | #include <linux/slab.h> | ||
| 19 | 20 | ||
| 20 | /* ADC controller bit defines */ | 21 | /* ADC controller bit defines */ |
| 21 | #define ADC_DELAY 0xf00 | 22 | #define ADC_DELAY 0xf00 |
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index f944918466e5..5109bf3dd858 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | #include <linux/wm97xx.h> | 48 | #include <linux/wm97xx.h> |
| 49 | #include <linux/uaccess.h> | 49 | #include <linux/uaccess.h> |
| 50 | #include <linux/io.h> | 50 | #include <linux/io.h> |
| 51 | #include <linux/slab.h> | ||
| 51 | 52 | ||
| 52 | #define TS_NAME "wm97xx" | 53 | #define TS_NAME "wm97xx" |
| 53 | #define WM_CORE_VERSION "1.00" | 54 | #define WM_CORE_VERSION "1.00" |
diff --git a/drivers/input/touchscreen/zylonite-wm97xx.c b/drivers/input/touchscreen/zylonite-wm97xx.c index 41e4359c277c..048849867643 100644 --- a/drivers/input/touchscreen/zylonite-wm97xx.c +++ b/drivers/input/touchscreen/zylonite-wm97xx.c | |||
| @@ -96,7 +96,7 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) | |||
| 96 | /* When the AC97 queue has been drained we need to allow time | 96 | /* When the AC97 queue has been drained we need to allow time |
| 97 | * to buffer up samples otherwise we end up spinning polling | 97 | * to buffer up samples otherwise we end up spinning polling |
| 98 | * for samples. The controller can't have a suitably low | 98 | * for samples. The controller can't have a suitably low |
| 99 | * threashold set to use the notifications it gives. | 99 | * threshold set to use the notifications it gives. |
| 100 | */ | 100 | */ |
| 101 | msleep(1); | 101 | msleep(1); |
| 102 | 102 | ||
| @@ -118,6 +118,9 @@ static int wm97xx_acc_pen_down(struct wm97xx *wm) | |||
| 118 | if (pressure) | 118 | if (pressure) |
| 119 | p = MODR; | 119 | p = MODR; |
| 120 | 120 | ||
| 121 | dev_dbg(wm->dev, "Raw coordinates: x=%x, y=%x, p=%x\n", | ||
| 122 | x, y, p); | ||
| 123 | |||
| 121 | /* are samples valid */ | 124 | /* are samples valid */ |
| 122 | if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || | 125 | if ((x & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_X || |
| 123 | (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || | 126 | (y & WM97XX_ADCSRC_MASK) != WM97XX_ADCSEL_Y || |
diff --git a/drivers/input/xen-kbdfront.c b/drivers/input/xen-kbdfront.c index b115726dc088..e14081675bb2 100644 --- a/drivers/input/xen-kbdfront.c +++ b/drivers/input/xen-kbdfront.c | |||
| @@ -21,7 +21,11 @@ | |||
| 21 | #include <linux/errno.h> | 21 | #include <linux/errno.h> |
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/input.h> | 23 | #include <linux/input.h> |
| 24 | #include <linux/slab.h> | ||
| 25 | |||
| 24 | #include <asm/xen/hypervisor.h> | 26 | #include <asm/xen/hypervisor.h> |
| 27 | |||
| 28 | #include <xen/xen.h> | ||
| 25 | #include <xen/events.h> | 29 | #include <xen/events.h> |
| 26 | #include <xen/page.h> | 30 | #include <xen/page.h> |
| 27 | #include <xen/interface/io/fbif.h> | 31 | #include <xen/interface/io/fbif.h> |
| @@ -318,7 +322,7 @@ InitWait: | |||
| 318 | } | 322 | } |
| 319 | } | 323 | } |
| 320 | 324 | ||
| 321 | static struct xenbus_device_id xenkbd_ids[] = { | 325 | static const struct xenbus_device_id xenkbd_ids[] = { |
| 322 | { "vkbd" }, | 326 | { "vkbd" }, |
| 323 | { "" } | 327 | { "" } |
| 324 | }; | 328 | }; |
