diff options
Diffstat (limited to 'drivers/input')
45 files changed, 1315 insertions, 1059 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 556264b43425..374f404e81da 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/smp_lock.h> | 21 | #include <linux/smp_lock.h> |
| 22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 23 | #include <linux/devfs_fs_kernel.h> | 23 | #include <linux/devfs_fs_kernel.h> |
| 24 | #include <linux/compat.h> | ||
| 24 | 25 | ||
| 25 | struct evdev { | 26 | struct evdev { |
| 26 | int exist; | 27 | int exist; |
| @@ -145,6 +146,41 @@ static int evdev_open(struct inode * inode, struct file * file) | |||
| 145 | return 0; | 146 | return 0; |
| 146 | } | 147 | } |
| 147 | 148 | ||
| 149 | #ifdef CONFIG_COMPAT | ||
| 150 | struct input_event_compat { | ||
| 151 | struct compat_timeval time; | ||
| 152 | __u16 type; | ||
| 153 | __u16 code; | ||
| 154 | __s32 value; | ||
| 155 | }; | ||
| 156 | |||
| 157 | #ifdef CONFIG_X86_64 | ||
| 158 | # define COMPAT_TEST test_thread_flag(TIF_IA32) | ||
| 159 | #elif defined(CONFIG_IA64) | ||
| 160 | # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) | ||
| 161 | #elif defined(CONFIG_ARCH_S390) | ||
| 162 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) | ||
| 163 | #else | ||
| 164 | # define COMPAT_TEST test_thread_flag(TIF_32BIT) | ||
| 165 | #endif | ||
| 166 | |||
| 167 | static ssize_t evdev_write_compat(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | ||
| 168 | { | ||
| 169 | struct evdev_list *list = file->private_data; | ||
| 170 | struct input_event_compat event; | ||
| 171 | int retval = 0; | ||
| 172 | |||
| 173 | while (retval < count) { | ||
| 174 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event_compat))) | ||
| 175 | return -EFAULT; | ||
| 176 | input_event(list->evdev->handle.dev, event.type, event.code, event.value); | ||
| 177 | retval += sizeof(struct input_event_compat); | ||
| 178 | } | ||
| 179 | |||
| 180 | return retval; | ||
| 181 | } | ||
| 182 | #endif | ||
| 183 | |||
| 148 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) | 184 | static ssize_t evdev_write(struct file * file, const char __user * buffer, size_t count, loff_t *ppos) |
| 149 | { | 185 | { |
| 150 | struct evdev_list *list = file->private_data; | 186 | struct evdev_list *list = file->private_data; |
| @@ -153,6 +189,11 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
| 153 | 189 | ||
| 154 | if (!list->evdev->exist) return -ENODEV; | 190 | if (!list->evdev->exist) return -ENODEV; |
| 155 | 191 | ||
| 192 | #ifdef CONFIG_COMPAT | ||
| 193 | if (COMPAT_TEST) | ||
| 194 | return evdev_write_compat(file, buffer, count, ppos); | ||
| 195 | #endif | ||
| 196 | |||
| 156 | while (retval < count) { | 197 | while (retval < count) { |
| 157 | 198 | ||
| 158 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) | 199 | if (copy_from_user(&event, buffer + retval, sizeof(struct input_event))) |
| @@ -164,11 +205,56 @@ static ssize_t evdev_write(struct file * file, const char __user * buffer, size_ | |||
| 164 | return retval; | 205 | return retval; |
| 165 | } | 206 | } |
| 166 | 207 | ||
| 208 | #ifdef CONFIG_COMPAT | ||
| 209 | static ssize_t evdev_read_compat(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | ||
| 210 | { | ||
| 211 | struct evdev_list *list = file->private_data; | ||
| 212 | int retval; | ||
| 213 | |||
| 214 | if (count < sizeof(struct input_event_compat)) | ||
| 215 | return -EINVAL; | ||
| 216 | |||
| 217 | if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK)) | ||
| 218 | return -EAGAIN; | ||
| 219 | |||
| 220 | retval = wait_event_interruptible(list->evdev->wait, | ||
| 221 | list->head != list->tail || (!list->evdev->exist)); | ||
| 222 | |||
| 223 | if (retval) | ||
| 224 | return retval; | ||
| 225 | |||
| 226 | if (!list->evdev->exist) | ||
| 227 | return -ENODEV; | ||
| 228 | |||
| 229 | while (list->head != list->tail && retval + sizeof(struct input_event_compat) <= count) { | ||
| 230 | struct input_event *event = (struct input_event *) list->buffer + list->tail; | ||
| 231 | struct input_event_compat event_compat; | ||
| 232 | event_compat.time.tv_sec = event->time.tv_sec; | ||
| 233 | event_compat.time.tv_usec = event->time.tv_usec; | ||
| 234 | event_compat.type = event->type; | ||
| 235 | event_compat.code = event->code; | ||
| 236 | event_compat.value = event->value; | ||
| 237 | |||
| 238 | if (copy_to_user(buffer + retval, &event_compat, | ||
| 239 | sizeof(struct input_event_compat))) return -EFAULT; | ||
| 240 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | ||
| 241 | retval += sizeof(struct input_event_compat); | ||
| 242 | } | ||
| 243 | |||
| 244 | return retval; | ||
| 245 | } | ||
| 246 | #endif | ||
| 247 | |||
| 167 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) | 248 | static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) |
| 168 | { | 249 | { |
| 169 | struct evdev_list *list = file->private_data; | 250 | struct evdev_list *list = file->private_data; |
| 170 | int retval; | 251 | int retval; |
| 171 | 252 | ||
| 253 | #ifdef CONFIG_COMPAT | ||
| 254 | if (COMPAT_TEST) | ||
| 255 | return evdev_read_compat(file, buffer, count, ppos); | ||
| 256 | #endif | ||
| 257 | |||
| 172 | if (count < sizeof(struct input_event)) | 258 | if (count < sizeof(struct input_event)) |
| 173 | return -EINVAL; | 259 | return -EINVAL; |
| 174 | 260 | ||
| @@ -186,7 +272,7 @@ static ssize_t evdev_read(struct file * file, char __user * buffer, size_t count | |||
| 186 | 272 | ||
| 187 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { | 273 | while (list->head != list->tail && retval + sizeof(struct input_event) <= count) { |
| 188 | if (copy_to_user(buffer + retval, list->buffer + list->tail, | 274 | if (copy_to_user(buffer + retval, list->buffer + list->tail, |
| 189 | sizeof(struct input_event))) return -EFAULT; | 275 | sizeof(struct input_event))) return -EFAULT; |
| 190 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); | 276 | list->tail = (list->tail + 1) & (EVDEV_BUFFER_SIZE - 1); |
| 191 | retval += sizeof(struct input_event); | 277 | retval += sizeof(struct input_event); |
| 192 | } | 278 | } |
| @@ -203,7 +289,7 @@ static unsigned int evdev_poll(struct file *file, poll_table *wait) | |||
| 203 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); | 289 | (list->evdev->exist ? 0 : (POLLHUP | POLLERR)); |
| 204 | } | 290 | } |
| 205 | 291 | ||
| 206 | static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 292 | static long evdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 207 | { | 293 | { |
| 208 | struct evdev_list *list = file->private_data; | 294 | struct evdev_list *list = file->private_data; |
| 209 | struct evdev *evdev = list->evdev; | 295 | struct evdev *evdev = list->evdev; |
| @@ -285,109 +371,267 @@ static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
| 285 | 371 | ||
| 286 | default: | 372 | default: |
| 287 | 373 | ||
| 288 | if (_IOC_TYPE(cmd) != 'E' || _IOC_DIR(cmd) != _IOC_READ) | 374 | if (_IOC_TYPE(cmd) != 'E') |
| 289 | return -EINVAL; | 375 | return -EINVAL; |
| 290 | 376 | ||
| 291 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | 377 | if (_IOC_DIR(cmd) == _IOC_READ) { |
| 292 | 378 | ||
| 293 | long *bits; | 379 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { |
| 294 | int len; | 380 | |
| 295 | 381 | long *bits; | |
| 296 | switch (_IOC_NR(cmd) & EV_MAX) { | 382 | int len; |
| 297 | case 0: bits = dev->evbit; len = EV_MAX; break; | 383 | |
| 298 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | 384 | switch (_IOC_NR(cmd) & EV_MAX) { |
| 299 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | 385 | case 0: bits = dev->evbit; len = EV_MAX; break; |
| 300 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | 386 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; |
| 301 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | 387 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; |
| 302 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | 388 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; |
| 303 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | 389 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; |
| 304 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | 390 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; |
| 305 | default: return -EINVAL; | 391 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; |
| 392 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
| 393 | default: return -EINVAL; | ||
| 394 | } | ||
| 395 | len = NBITS(len) * sizeof(long); | ||
| 396 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 397 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
| 306 | } | 398 | } |
| 307 | len = NBITS(len) * sizeof(long); | ||
| 308 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 309 | return copy_to_user(p, bits, len) ? -EFAULT : len; | ||
| 310 | } | ||
| 311 | 399 | ||
| 312 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { | 400 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) { |
| 313 | int len; | 401 | int len; |
| 314 | len = NBITS(KEY_MAX) * sizeof(long); | 402 | len = NBITS(KEY_MAX) * sizeof(long); |
| 315 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 403 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
| 316 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; | 404 | return copy_to_user(p, dev->key, len) ? -EFAULT : len; |
| 317 | } | 405 | } |
| 318 | 406 | ||
| 319 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { | 407 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) { |
| 320 | int len; | 408 | int len; |
| 321 | len = NBITS(LED_MAX) * sizeof(long); | 409 | len = NBITS(LED_MAX) * sizeof(long); |
| 322 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 410 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
| 323 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; | 411 | return copy_to_user(p, dev->led, len) ? -EFAULT : len; |
| 324 | } | 412 | } |
| 325 | 413 | ||
| 326 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { | 414 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) { |
| 327 | int len; | 415 | int len; |
| 328 | len = NBITS(SND_MAX) * sizeof(long); | 416 | len = NBITS(SND_MAX) * sizeof(long); |
| 329 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 417 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
| 330 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; | 418 | return copy_to_user(p, dev->snd, len) ? -EFAULT : len; |
| 331 | } | 419 | } |
| 332 | 420 | ||
| 333 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | 421 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { |
| 334 | int len; | 422 | int len; |
| 335 | if (!dev->name) return -ENOENT; | 423 | if (!dev->name) return -ENOENT; |
| 336 | len = strlen(dev->name) + 1; | 424 | len = strlen(dev->name) + 1; |
| 337 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 425 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); |
| 338 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | 426 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; |
| 339 | } | 427 | } |
| 428 | |||
| 429 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
| 430 | int len; | ||
| 431 | if (!dev->phys) return -ENOENT; | ||
| 432 | len = strlen(dev->phys) + 1; | ||
| 433 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 434 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
| 435 | } | ||
| 436 | |||
| 437 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
| 438 | int len; | ||
| 439 | if (!dev->uniq) return -ENOENT; | ||
| 440 | len = strlen(dev->uniq) + 1; | ||
| 441 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 442 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
| 443 | } | ||
| 444 | |||
| 445 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
| 446 | |||
| 447 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
| 448 | |||
| 449 | abs.value = dev->abs[t]; | ||
| 450 | abs.minimum = dev->absmin[t]; | ||
| 451 | abs.maximum = dev->absmax[t]; | ||
| 452 | abs.fuzz = dev->absfuzz[t]; | ||
| 453 | abs.flat = dev->absflat[t]; | ||
| 454 | |||
| 455 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
| 456 | return -EFAULT; | ||
| 457 | |||
| 458 | return 0; | ||
| 459 | } | ||
| 340 | 460 | ||
| 341 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
| 342 | int len; | ||
| 343 | if (!dev->phys) return -ENOENT; | ||
| 344 | len = strlen(dev->phys) + 1; | ||
| 345 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 346 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
| 347 | } | 461 | } |
| 348 | 462 | ||
| 349 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | 463 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
| 350 | int len; | 464 | |
| 351 | if (!dev->uniq) return -ENOENT; | 465 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
| 352 | len = strlen(dev->uniq) + 1; | 466 | |
| 353 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | 467 | int t = _IOC_NR(cmd) & ABS_MAX; |
| 354 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | 468 | |
| 469 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | ||
| 470 | return -EFAULT; | ||
| 471 | |||
| 472 | dev->abs[t] = abs.value; | ||
| 473 | dev->absmin[t] = abs.minimum; | ||
| 474 | dev->absmax[t] = abs.maximum; | ||
| 475 | dev->absfuzz[t] = abs.fuzz; | ||
| 476 | dev->absflat[t] = abs.flat; | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 355 | } | 480 | } |
| 481 | } | ||
| 482 | return -EINVAL; | ||
| 483 | } | ||
| 356 | 484 | ||
| 357 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | 485 | #ifdef CONFIG_COMPAT |
| 486 | |||
| 487 | #define BITS_PER_LONG_COMPAT (sizeof(compat_long_t) * 8) | ||
| 488 | #define NBITS_COMPAT(x) ((((x)-1)/BITS_PER_LONG_COMPAT)+1) | ||
| 489 | #define OFF_COMPAT(x) ((x)%BITS_PER_LONG_COMPAT) | ||
| 490 | #define BIT_COMPAT(x) (1UL<<OFF_COMPAT(x)) | ||
| 491 | #define LONG_COMPAT(x) ((x)/BITS_PER_LONG_COMPAT) | ||
| 492 | #define test_bit_compat(bit, array) ((array[LONG_COMPAT(bit)] >> OFF_COMPAT(bit)) & 1) | ||
| 493 | |||
| 494 | #ifdef __BIG_ENDIAN | ||
| 495 | #define bit_to_user(bit, max) \ | ||
| 496 | do { \ | ||
| 497 | int i; \ | ||
| 498 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
| 499 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
| 500 | for (i = 0; i < len / sizeof(compat_long_t); i++) \ | ||
| 501 | if (copy_to_user((compat_long_t*) p + i, \ | ||
| 502 | (compat_long_t*) (bit) + i + 1 - ((i % 2) << 1), \ | ||
| 503 | sizeof(compat_long_t))) \ | ||
| 504 | return -EFAULT; \ | ||
| 505 | return len; \ | ||
| 506 | } while (0) | ||
| 507 | #else | ||
| 508 | #define bit_to_user(bit, max) \ | ||
| 509 | do { \ | ||
| 510 | int len = NBITS_COMPAT((max)) * sizeof(compat_long_t); \ | ||
| 511 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); \ | ||
| 512 | return copy_to_user(p, (bit), len) ? -EFAULT : len; \ | ||
| 513 | } while (0) | ||
| 514 | #endif | ||
| 515 | |||
| 516 | static long evdev_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 517 | { | ||
| 518 | struct evdev_list *list = file->private_data; | ||
| 519 | struct evdev *evdev = list->evdev; | ||
| 520 | struct input_dev *dev = evdev->handle.dev; | ||
| 521 | struct input_absinfo abs; | ||
| 522 | void __user *p = compat_ptr(arg); | ||
| 358 | 523 | ||
| 359 | int t = _IOC_NR(cmd) & ABS_MAX; | 524 | if (!evdev->exist) return -ENODEV; |
| 360 | 525 | ||
| 361 | abs.value = dev->abs[t]; | 526 | switch (cmd) { |
| 362 | abs.minimum = dev->absmin[t]; | ||
| 363 | abs.maximum = dev->absmax[t]; | ||
| 364 | abs.fuzz = dev->absfuzz[t]; | ||
| 365 | abs.flat = dev->absflat[t]; | ||
| 366 | 527 | ||
| 367 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | 528 | case EVIOCGVERSION: |
| 368 | return -EFAULT; | 529 | case EVIOCGID: |
| 530 | case EVIOCGKEYCODE: | ||
| 531 | case EVIOCSKEYCODE: | ||
| 532 | case EVIOCSFF: | ||
| 533 | case EVIOCRMFF: | ||
| 534 | case EVIOCGEFFECTS: | ||
| 535 | case EVIOCGRAB: | ||
| 536 | return evdev_ioctl(file, cmd, (unsigned long) p); | ||
| 369 | 537 | ||
| 370 | return 0; | 538 | default: |
| 539 | |||
| 540 | if (_IOC_TYPE(cmd) != 'E') | ||
| 541 | return -EINVAL; | ||
| 542 | |||
| 543 | if (_IOC_DIR(cmd) == _IOC_READ) { | ||
| 544 | |||
| 545 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0,0))) { | ||
| 546 | long *bits; | ||
| 547 | int max; | ||
| 548 | |||
| 549 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
| 550 | case 0: bits = dev->evbit; max = EV_MAX; break; | ||
| 551 | case EV_KEY: bits = dev->keybit; max = KEY_MAX; break; | ||
| 552 | case EV_REL: bits = dev->relbit; max = REL_MAX; break; | ||
| 553 | case EV_ABS: bits = dev->absbit; max = ABS_MAX; break; | ||
| 554 | case EV_MSC: bits = dev->mscbit; max = MSC_MAX; break; | ||
| 555 | case EV_LED: bits = dev->ledbit; max = LED_MAX; break; | ||
| 556 | case EV_SND: bits = dev->sndbit; max = SND_MAX; break; | ||
| 557 | case EV_FF: bits = dev->ffbit; max = FF_MAX; break; | ||
| 558 | default: return -EINVAL; | ||
| 559 | } | ||
| 560 | bit_to_user(bits, max); | ||
| 561 | } | ||
| 562 | |||
| 563 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | ||
| 564 | bit_to_user(dev->key, KEY_MAX); | ||
| 565 | |||
| 566 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGLED(0))) | ||
| 567 | bit_to_user(dev->led, LED_MAX); | ||
| 568 | |||
| 569 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGSND(0))) | ||
| 570 | bit_to_user(dev->snd, SND_MAX); | ||
| 571 | |||
| 572 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGNAME(0))) { | ||
| 573 | int len; | ||
| 574 | if (!dev->name) return -ENOENT; | ||
| 575 | len = strlen(dev->name) + 1; | ||
| 576 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 577 | return copy_to_user(p, dev->name, len) ? -EFAULT : len; | ||
| 578 | } | ||
| 579 | |||
| 580 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGPHYS(0))) { | ||
| 581 | int len; | ||
| 582 | if (!dev->phys) return -ENOENT; | ||
| 583 | len = strlen(dev->phys) + 1; | ||
| 584 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 585 | return copy_to_user(p, dev->phys, len) ? -EFAULT : len; | ||
| 586 | } | ||
| 587 | |||
| 588 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGUNIQ(0))) { | ||
| 589 | int len; | ||
| 590 | if (!dev->uniq) return -ENOENT; | ||
| 591 | len = strlen(dev->uniq) + 1; | ||
| 592 | if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd); | ||
| 593 | return copy_to_user(p, dev->uniq, len) ? -EFAULT : len; | ||
| 594 | } | ||
| 595 | |||
| 596 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCGABS(0))) { | ||
| 597 | |||
| 598 | int t = _IOC_NR(cmd) & ABS_MAX; | ||
| 599 | |||
| 600 | abs.value = dev->abs[t]; | ||
| 601 | abs.minimum = dev->absmin[t]; | ||
| 602 | abs.maximum = dev->absmax[t]; | ||
| 603 | abs.fuzz = dev->absfuzz[t]; | ||
| 604 | abs.flat = dev->absflat[t]; | ||
| 605 | |||
| 606 | if (copy_to_user(p, &abs, sizeof(struct input_absinfo))) | ||
| 607 | return -EFAULT; | ||
| 608 | |||
| 609 | return 0; | ||
| 610 | } | ||
| 371 | } | 611 | } |
| 372 | 612 | ||
| 373 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { | 613 | if (_IOC_DIR(cmd) == _IOC_WRITE) { |
| 374 | 614 | ||
| 375 | int t = _IOC_NR(cmd) & ABS_MAX; | 615 | if ((_IOC_NR(cmd) & ~ABS_MAX) == _IOC_NR(EVIOCSABS(0))) { |
| 376 | 616 | ||
| 377 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) | 617 | int t = _IOC_NR(cmd) & ABS_MAX; |
| 378 | return -EFAULT; | ||
| 379 | 618 | ||
| 380 | dev->abs[t] = abs.value; | 619 | if (copy_from_user(&abs, p, sizeof(struct input_absinfo))) |
| 381 | dev->absmin[t] = abs.minimum; | 620 | return -EFAULT; |
| 382 | dev->absmax[t] = abs.maximum; | ||
| 383 | dev->absfuzz[t] = abs.fuzz; | ||
| 384 | dev->absflat[t] = abs.flat; | ||
| 385 | 621 | ||
| 386 | return 0; | 622 | dev->abs[t] = abs.value; |
| 623 | dev->absmin[t] = abs.minimum; | ||
| 624 | dev->absmax[t] = abs.maximum; | ||
| 625 | dev->absfuzz[t] = abs.fuzz; | ||
| 626 | dev->absflat[t] = abs.flat; | ||
| 627 | |||
| 628 | return 0; | ||
| 629 | } | ||
| 387 | } | 630 | } |
| 388 | } | 631 | } |
| 389 | return -EINVAL; | 632 | return -EINVAL; |
| 390 | } | 633 | } |
| 634 | #endif | ||
| 391 | 635 | ||
| 392 | static struct file_operations evdev_fops = { | 636 | static struct file_operations evdev_fops = { |
| 393 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
| @@ -396,7 +640,10 @@ static struct file_operations evdev_fops = { | |||
| 396 | .poll = evdev_poll, | 640 | .poll = evdev_poll, |
| 397 | .open = evdev_open, | 641 | .open = evdev_open, |
| 398 | .release = evdev_release, | 642 | .release = evdev_release, |
| 399 | .ioctl = evdev_ioctl, | 643 | .unlocked_ioctl = evdev_ioctl, |
| 644 | #ifdef CONFIG_COMPAT | ||
| 645 | .compat_ioctl = evdev_ioctl_compat, | ||
| 646 | #endif | ||
| 400 | .fasync = evdev_fasync, | 647 | .fasync = evdev_fasync, |
| 401 | .flush = evdev_flush | 648 | .flush = evdev_flush |
| 402 | }; | 649 | }; |
diff --git a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig index 1d93f5092904..7524bd7d8b8f 100644 --- a/drivers/input/gameport/Kconfig +++ b/drivers/input/gameport/Kconfig | |||
| @@ -49,22 +49,8 @@ config GAMEPORT_EMU10K1 | |||
| 49 | To compile this driver as a module, choose M here: the | 49 | To compile this driver as a module, choose M here: the |
| 50 | module will be called emu10k1-gp. | 50 | module will be called emu10k1-gp. |
| 51 | 51 | ||
| 52 | config GAMEPORT_VORTEX | ||
| 53 | tristate "Aureal Vortex, Vortex 2 gameport support" | ||
| 54 | depends on PCI | ||
| 55 | help | ||
| 56 | Say Y here if you have an Aureal Vortex 1 or 2 card and want | ||
| 57 | to use its gameport. | ||
| 58 | |||
| 59 | To compile this driver as a module, choose M here: the | ||
| 60 | module will be called vortex. | ||
| 61 | |||
| 62 | config GAMEPORT_FM801 | 52 | config GAMEPORT_FM801 |
| 63 | tristate "ForteMedia FM801 gameport support" | 53 | tristate "ForteMedia FM801 gameport support" |
| 64 | depends on PCI | 54 | depends on PCI |
| 65 | 55 | ||
| 66 | config GAMEPORT_CS461X | ||
| 67 | tristate "Crystal SoundFusion gameport support" | ||
| 68 | depends on PCI | ||
| 69 | |||
| 70 | endif | 56 | endif |
diff --git a/drivers/input/gameport/Makefile b/drivers/input/gameport/Makefile index 5367b4267adf..b6f6097bd8c4 100644 --- a/drivers/input/gameport/Makefile +++ b/drivers/input/gameport/Makefile | |||
| @@ -5,9 +5,7 @@ | |||
| 5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
| 6 | 6 | ||
| 7 | obj-$(CONFIG_GAMEPORT) += gameport.o | 7 | obj-$(CONFIG_GAMEPORT) += gameport.o |
| 8 | obj-$(CONFIG_GAMEPORT_CS461X) += cs461x.o | ||
| 9 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o | 8 | obj-$(CONFIG_GAMEPORT_EMU10K1) += emu10k1-gp.o |
| 10 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o | 9 | obj-$(CONFIG_GAMEPORT_FM801) += fm801-gp.o |
| 11 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o | 10 | obj-$(CONFIG_GAMEPORT_L4) += lightning.o |
| 12 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o | 11 | obj-$(CONFIG_GAMEPORT_NS558) += ns558.o |
| 13 | obj-$(CONFIG_GAMEPORT_VORTEX) += vortex.o | ||
diff --git a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c deleted file mode 100644 index d4013ff98623..000000000000 --- a/drivers/input/gameport/cs461x.c +++ /dev/null | |||
| @@ -1,322 +0,0 @@ | |||
| 1 | /* | ||
| 2 | The all defines and part of code (such as cs461x_*) are | ||
| 3 | contributed from ALSA 0.5.8 sources. | ||
| 4 | See http://www.alsa-project.org/ for sources | ||
| 5 | |||
| 6 | Tested on Linux 686 2.4.0-test9, ALSA 0.5.8a and CS4610 | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <asm/io.h> | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/ioport.h> | ||
| 13 | #include <linux/config.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/gameport.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | #include <linux/pci.h> | ||
| 18 | |||
| 19 | MODULE_AUTHOR("Victor Krapivin"); | ||
| 20 | MODULE_LICENSE("GPL"); | ||
| 21 | |||
| 22 | /* | ||
| 23 | These options are experimental | ||
| 24 | |||
| 25 | #define CS461X_FULL_MAP | ||
| 26 | */ | ||
| 27 | |||
| 28 | |||
| 29 | #ifndef PCI_VENDOR_ID_CIRRUS | ||
| 30 | #define PCI_VENDOR_ID_CIRRUS 0x1013 | ||
| 31 | #endif | ||
| 32 | #ifndef PCI_DEVICE_ID_CIRRUS_4610 | ||
| 33 | #define PCI_DEVICE_ID_CIRRUS_4610 0x6001 | ||
| 34 | #endif | ||
| 35 | #ifndef PCI_DEVICE_ID_CIRRUS_4612 | ||
| 36 | #define PCI_DEVICE_ID_CIRRUS_4612 0x6003 | ||
| 37 | #endif | ||
| 38 | #ifndef PCI_DEVICE_ID_CIRRUS_4615 | ||
| 39 | #define PCI_DEVICE_ID_CIRRUS_4615 0x6004 | ||
| 40 | #endif | ||
| 41 | |||
| 42 | /* Registers */ | ||
| 43 | |||
| 44 | #define BA0_JSPT 0x00000480 | ||
| 45 | #define BA0_JSCTL 0x00000484 | ||
| 46 | #define BA0_JSC1 0x00000488 | ||
| 47 | #define BA0_JSC2 0x0000048C | ||
| 48 | #define BA0_JSIO 0x000004A0 | ||
| 49 | |||
| 50 | /* Bits for JSPT */ | ||
| 51 | |||
| 52 | #define JSPT_CAX 0x00000001 | ||
| 53 | #define JSPT_CAY 0x00000002 | ||
| 54 | #define JSPT_CBX 0x00000004 | ||
| 55 | #define JSPT_CBY 0x00000008 | ||
| 56 | #define JSPT_BA1 0x00000010 | ||
| 57 | #define JSPT_BA2 0x00000020 | ||
| 58 | #define JSPT_BB1 0x00000040 | ||
| 59 | #define JSPT_BB2 0x00000080 | ||
| 60 | |||
| 61 | /* Bits for JSCTL */ | ||
| 62 | |||
| 63 | #define JSCTL_SP_MASK 0x00000003 | ||
| 64 | #define JSCTL_SP_SLOW 0x00000000 | ||
| 65 | #define JSCTL_SP_MEDIUM_SLOW 0x00000001 | ||
| 66 | #define JSCTL_SP_MEDIUM_FAST 0x00000002 | ||
| 67 | #define JSCTL_SP_FAST 0x00000003 | ||
| 68 | #define JSCTL_ARE 0x00000004 | ||
| 69 | |||
| 70 | /* Data register pairs masks */ | ||
| 71 | |||
| 72 | #define JSC1_Y1V_MASK 0x0000FFFF | ||
| 73 | #define JSC1_X1V_MASK 0xFFFF0000 | ||
| 74 | #define JSC1_Y1V_SHIFT 0 | ||
| 75 | #define JSC1_X1V_SHIFT 16 | ||
| 76 | #define JSC2_Y2V_MASK 0x0000FFFF | ||
| 77 | #define JSC2_X2V_MASK 0xFFFF0000 | ||
| 78 | #define JSC2_Y2V_SHIFT 0 | ||
| 79 | #define JSC2_X2V_SHIFT 16 | ||
| 80 | |||
| 81 | /* JS GPIO */ | ||
| 82 | |||
| 83 | #define JSIO_DAX 0x00000001 | ||
| 84 | #define JSIO_DAY 0x00000002 | ||
| 85 | #define JSIO_DBX 0x00000004 | ||
| 86 | #define JSIO_DBY 0x00000008 | ||
| 87 | #define JSIO_AXOE 0x00000010 | ||
| 88 | #define JSIO_AYOE 0x00000020 | ||
| 89 | #define JSIO_BXOE 0x00000040 | ||
| 90 | #define JSIO_BYOE 0x00000080 | ||
| 91 | |||
| 92 | /* | ||
| 93 | The card initialization code is obfuscated; the module cs461x | ||
| 94 | need to be loaded after ALSA modules initialized and something | ||
| 95 | played on the CS 4610 chip (see sources for details of CS4610 | ||
| 96 | initialization code from ALSA) | ||
| 97 | */ | ||
| 98 | |||
| 99 | /* Card specific definitions */ | ||
| 100 | |||
| 101 | #define CS461X_BA0_SIZE 0x2000 | ||
| 102 | #define CS461X_BA1_DATA0_SIZE 0x3000 | ||
| 103 | #define CS461X_BA1_DATA1_SIZE 0x3800 | ||
| 104 | #define CS461X_BA1_PRG_SIZE 0x7000 | ||
| 105 | #define CS461X_BA1_REG_SIZE 0x0100 | ||
| 106 | |||
| 107 | #define BA1_SP_DMEM0 0x00000000 | ||
| 108 | #define BA1_SP_DMEM1 0x00010000 | ||
| 109 | #define BA1_SP_PMEM 0x00020000 | ||
| 110 | #define BA1_SP_REG 0x00030000 | ||
| 111 | |||
| 112 | #define BA1_DWORD_SIZE (13 * 1024 + 512) | ||
| 113 | #define BA1_MEMORY_COUNT 3 | ||
| 114 | |||
| 115 | /* | ||
| 116 | Only one CS461x card is still suppoted; the code requires | ||
| 117 | redesign to avoid this limitatuion. | ||
| 118 | */ | ||
| 119 | |||
| 120 | static unsigned long ba0_addr; | ||
| 121 | static unsigned int __iomem *ba0; | ||
| 122 | |||
| 123 | #ifdef CS461X_FULL_MAP | ||
| 124 | static unsigned long ba1_addr; | ||
| 125 | static union ba1_t { | ||
| 126 | struct { | ||
| 127 | unsigned int __iomem *data0; | ||
| 128 | unsigned int __iomem *data1; | ||
| 129 | unsigned int __iomem *pmem; | ||
| 130 | unsigned int __iomem *reg; | ||
| 131 | } name; | ||
| 132 | unsigned int __iomem *idx[4]; | ||
| 133 | } ba1; | ||
| 134 | |||
| 135 | static void cs461x_poke(unsigned long reg, unsigned int val) | ||
| 136 | { | ||
| 137 | writel(val, &ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
| 138 | } | ||
| 139 | |||
| 140 | static unsigned int cs461x_peek(unsigned long reg) | ||
| 141 | { | ||
| 142 | return readl(&ba1.idx[(reg >> 16) & 3][(reg >> 2) & 0x3fff]); | ||
| 143 | } | ||
| 144 | |||
| 145 | #endif | ||
| 146 | |||
| 147 | static void cs461x_pokeBA0(unsigned long reg, unsigned int val) | ||
| 148 | { | ||
| 149 | writel(val, &ba0[reg >> 2]); | ||
| 150 | } | ||
| 151 | |||
| 152 | static unsigned int cs461x_peekBA0(unsigned long reg) | ||
| 153 | { | ||
| 154 | return readl(&ba0[reg >> 2]); | ||
| 155 | } | ||
| 156 | |||
| 157 | static int cs461x_free(struct pci_dev *pdev) | ||
| 158 | { | ||
| 159 | struct gameport *port = pci_get_drvdata(pdev); | ||
| 160 | |||
| 161 | if (port) | ||
| 162 | gameport_unregister_port(port); | ||
| 163 | |||
| 164 | if (ba0) iounmap(ba0); | ||
| 165 | #ifdef CS461X_FULL_MAP | ||
| 166 | if (ba1.name.data0) iounmap(ba1.name.data0); | ||
| 167 | if (ba1.name.data1) iounmap(ba1.name.data1); | ||
| 168 | if (ba1.name.pmem) iounmap(ba1.name.pmem); | ||
| 169 | if (ba1.name.reg) iounmap(ba1.name.reg); | ||
| 170 | #endif | ||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static void cs461x_gameport_trigger(struct gameport *gameport) | ||
| 175 | { | ||
| 176 | cs461x_pokeBA0(BA0_JSPT, 0xFF); //outb(gameport->io, 0xFF); | ||
| 177 | } | ||
| 178 | |||
| 179 | static unsigned char cs461x_gameport_read(struct gameport *gameport) | ||
| 180 | { | ||
| 181 | return cs461x_peekBA0(BA0_JSPT); //inb(gameport->io); | ||
| 182 | } | ||
| 183 | |||
| 184 | static int cs461x_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
| 185 | { | ||
| 186 | unsigned js1, js2, jst; | ||
| 187 | |||
| 188 | js1 = cs461x_peekBA0(BA0_JSC1); | ||
| 189 | js2 = cs461x_peekBA0(BA0_JSC2); | ||
| 190 | jst = cs461x_peekBA0(BA0_JSPT); | ||
| 191 | |||
| 192 | *buttons = (~jst >> 4) & 0x0F; | ||
| 193 | |||
| 194 | axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF; | ||
| 195 | axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF; | ||
| 196 | axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF; | ||
| 197 | axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF; | ||
| 198 | |||
| 199 | for(jst=0;jst<4;++jst) | ||
| 200 | if(axes[jst]==0xFFFF) axes[jst] = -1; | ||
| 201 | return 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static int cs461x_gameport_open(struct gameport *gameport, int mode) | ||
| 205 | { | ||
| 206 | switch (mode) { | ||
| 207 | case GAMEPORT_MODE_COOKED: | ||
| 208 | case GAMEPORT_MODE_RAW: | ||
| 209 | return 0; | ||
| 210 | default: | ||
| 211 | return -1; | ||
| 212 | } | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 216 | static struct pci_device_id cs461x_pci_tbl[] = { | ||
| 217 | { PCI_VENDOR_ID_CIRRUS, 0x6001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4610 */ | ||
| 218 | { PCI_VENDOR_ID_CIRRUS, 0x6003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4612 */ | ||
| 219 | { PCI_VENDOR_ID_CIRRUS, 0x6005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Cirrus CS4615 */ | ||
| 220 | { 0, } | ||
| 221 | }; | ||
| 222 | MODULE_DEVICE_TABLE(pci, cs461x_pci_tbl); | ||
| 223 | |||
| 224 | static int __devinit cs461x_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
| 225 | { | ||
| 226 | int rc; | ||
| 227 | struct gameport* port; | ||
| 228 | |||
| 229 | rc = pci_enable_device(pdev); | ||
| 230 | if (rc) { | ||
| 231 | printk(KERN_ERR "cs461x: Cannot enable PCI gameport (bus %d, devfn %d) error=%d\n", | ||
| 232 | pdev->bus->number, pdev->devfn, rc); | ||
| 233 | return rc; | ||
| 234 | } | ||
| 235 | |||
| 236 | ba0_addr = pci_resource_start(pdev, 0); | ||
| 237 | #ifdef CS461X_FULL_MAP | ||
| 238 | ba1_addr = pci_resource_start(pdev, 1); | ||
| 239 | #endif | ||
| 240 | if (ba0_addr == 0 || ba0_addr == ~0 | ||
| 241 | #ifdef CS461X_FULL_MAP | ||
| 242 | || ba1_addr == 0 || ba1_addr == ~0 | ||
| 243 | #endif | ||
| 244 | ) { | ||
| 245 | printk(KERN_ERR "cs461x: wrong address - ba0 = 0x%lx\n", ba0_addr); | ||
| 246 | #ifdef CS461X_FULL_MAP | ||
| 247 | printk(KERN_ERR "cs461x: wrong address - ba1 = 0x%lx\n", ba1_addr); | ||
| 248 | #endif | ||
| 249 | cs461x_free(pdev); | ||
| 250 | return -ENOMEM; | ||
| 251 | } | ||
| 252 | |||
| 253 | ba0 = ioremap(ba0_addr, CS461X_BA0_SIZE); | ||
| 254 | #ifdef CS461X_FULL_MAP | ||
| 255 | ba1.name.data0 = ioremap(ba1_addr + BA1_SP_DMEM0, CS461X_BA1_DATA0_SIZE); | ||
| 256 | ba1.name.data1 = ioremap(ba1_addr + BA1_SP_DMEM1, CS461X_BA1_DATA1_SIZE); | ||
| 257 | ba1.name.pmem = ioremap(ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); | ||
| 258 | ba1.name.reg = ioremap(ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); | ||
| 259 | |||
| 260 | if (ba0 == NULL || ba1.name.data0 == NULL || | ||
| 261 | ba1.name.data1 == NULL || ba1.name.pmem == NULL || | ||
| 262 | ba1.name.reg == NULL) { | ||
| 263 | cs461x_free(pdev); | ||
| 264 | return -ENOMEM; | ||
| 265 | } | ||
| 266 | #else | ||
| 267 | if (ba0 == NULL) { | ||
| 268 | cs461x_free(pdev); | ||
| 269 | return -ENOMEM; | ||
| 270 | } | ||
| 271 | #endif | ||
| 272 | |||
| 273 | if (!(port = gameport_allocate_port())) { | ||
| 274 | printk(KERN_ERR "cs461x: Memory allocation failed\n"); | ||
| 275 | cs461x_free(pdev); | ||
| 276 | return -ENOMEM; | ||
| 277 | } | ||
| 278 | |||
| 279 | pci_set_drvdata(pdev, port); | ||
| 280 | |||
| 281 | port->open = cs461x_gameport_open; | ||
| 282 | port->trigger = cs461x_gameport_trigger; | ||
| 283 | port->read = cs461x_gameport_read; | ||
| 284 | port->cooked_read = cs461x_gameport_cooked_read; | ||
| 285 | |||
| 286 | gameport_set_name(port, "CS416x"); | ||
| 287 | gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev)); | ||
| 288 | port->dev.parent = &pdev->dev; | ||
| 289 | |||
| 290 | cs461x_pokeBA0(BA0_JSIO, 0xFF); // ? | ||
| 291 | cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW); | ||
| 292 | |||
| 293 | gameport_register_port(port); | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void __devexit cs461x_pci_remove(struct pci_dev *pdev) | ||
| 299 | { | ||
| 300 | cs461x_free(pdev); | ||
| 301 | } | ||
| 302 | |||
| 303 | static struct pci_driver cs461x_pci_driver = { | ||
| 304 | .name = "CS461x_gameport", | ||
| 305 | .id_table = cs461x_pci_tbl, | ||
| 306 | .probe = cs461x_pci_probe, | ||
| 307 | .remove = __devexit_p(cs461x_pci_remove), | ||
| 308 | }; | ||
| 309 | |||
| 310 | static int __init cs461x_init(void) | ||
| 311 | { | ||
| 312 | return pci_register_driver(&cs461x_pci_driver); | ||
| 313 | } | ||
| 314 | |||
| 315 | static void __exit cs461x_exit(void) | ||
| 316 | { | ||
| 317 | pci_unregister_driver(&cs461x_pci_driver); | ||
| 318 | } | ||
| 319 | |||
| 320 | module_init(cs461x_init); | ||
| 321 | module_exit(cs461x_exit); | ||
| 322 | |||
diff --git a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c index 7c5c6318eeb9..1ab5f2dc8a2a 100644 --- a/drivers/input/gameport/ns558.c +++ b/drivers/input/gameport/ns558.c | |||
| @@ -258,18 +258,18 @@ static int __init ns558_init(void) | |||
| 258 | { | 258 | { |
| 259 | int i = 0; | 259 | int i = 0; |
| 260 | 260 | ||
| 261 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
| 262 | pnp_registered = 1; | ||
| 263 | |||
| 261 | /* | 264 | /* |
| 262 | * Probe ISA ports first so that PnP gets to choose free port addresses | 265 | * Probe ISA ports after PnP, so that PnP ports that are already |
| 263 | * not occupied by the ISA ports. | 266 | * enabled get detected as PnP. This may be suboptimal in multi-device |
| 267 | * configurations, but saves hassle with simple setups. | ||
| 264 | */ | 268 | */ |
| 265 | 269 | ||
| 266 | while (ns558_isa_portlist[i]) | 270 | while (ns558_isa_portlist[i]) |
| 267 | ns558_isa_probe(ns558_isa_portlist[i++]); | 271 | ns558_isa_probe(ns558_isa_portlist[i++]); |
| 268 | 272 | ||
| 269 | if (pnp_register_driver(&ns558_pnp_driver) >= 0) | ||
| 270 | pnp_registered = 1; | ||
| 271 | |||
| 272 | |||
| 273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; | 273 | return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0; |
| 274 | } | 274 | } |
| 275 | 275 | ||
diff --git a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c deleted file mode 100644 index 36b0309c8bf6..000000000000 --- a/drivers/input/gameport/vortex.c +++ /dev/null | |||
| @@ -1,186 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * $Id: vortex.c,v 1.5 2002/07/01 15:39:30 vojtech Exp $ | ||
| 3 | * | ||
| 4 | * Copyright (c) 2000-2001 Vojtech Pavlik | ||
| 5 | * | ||
| 6 | * Based on the work of: | ||
| 7 | * Raymond Ingles | ||
| 8 | */ | ||
| 9 | |||
| 10 | /* | ||
| 11 | * Trident 4DWave and Aureal Vortex gameport driver for Linux | ||
| 12 | */ | ||
| 13 | |||
| 14 | /* | ||
| 15 | * This program is free software; you can redistribute it and/or modify | ||
| 16 | * it under the terms of the GNU General Public License as published by | ||
| 17 | * the Free Software Foundation; either version 2 of the License, or | ||
| 18 | * (at your option) any later version. | ||
| 19 | * | ||
| 20 | * This program is distributed in the hope that it will be useful, | ||
| 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 23 | * GNU General Public License for more details. | ||
| 24 | * | ||
| 25 | * You should have received a copy of the GNU General Public License | ||
| 26 | * along with this program; if not, write to the Free Software | ||
| 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 28 | * | ||
| 29 | * Should you need to contact me, the author, you can do so either by | ||
| 30 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | ||
| 31 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <asm/io.h> | ||
| 35 | #include <linux/delay.h> | ||
| 36 | #include <linux/errno.h> | ||
| 37 | #include <linux/ioport.h> | ||
| 38 | #include <linux/kernel.h> | ||
| 39 | #include <linux/module.h> | ||
| 40 | #include <linux/pci.h> | ||
| 41 | #include <linux/init.h> | ||
| 42 | #include <linux/slab.h> | ||
| 43 | #include <linux/delay.h> | ||
| 44 | #include <linux/gameport.h> | ||
| 45 | |||
| 46 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | ||
| 47 | MODULE_DESCRIPTION("Aureal Vortex and Vortex2 gameport driver"); | ||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | |||
| 50 | #define VORTEX_GCR 0x0c /* Gameport control register */ | ||
| 51 | #define VORTEX_LEG 0x08 /* Legacy port location */ | ||
| 52 | #define VORTEX_AXD 0x10 /* Axes start */ | ||
| 53 | #define VORTEX_DATA_WAIT 20 /* 20 ms */ | ||
| 54 | |||
| 55 | struct vortex { | ||
| 56 | struct gameport *gameport; | ||
| 57 | struct pci_dev *dev; | ||
| 58 | unsigned char __iomem *base; | ||
| 59 | unsigned char __iomem *io; | ||
| 60 | }; | ||
| 61 | |||
| 62 | static unsigned char vortex_read(struct gameport *gameport) | ||
| 63 | { | ||
| 64 | struct vortex *vortex = gameport->port_data; | ||
| 65 | return readb(vortex->io + VORTEX_LEG); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void vortex_trigger(struct gameport *gameport) | ||
| 69 | { | ||
| 70 | struct vortex *vortex = gameport->port_data; | ||
| 71 | writeb(0xff, vortex->io + VORTEX_LEG); | ||
| 72 | } | ||
| 73 | |||
| 74 | static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons) | ||
| 75 | { | ||
| 76 | struct vortex *vortex = gameport->port_data; | ||
| 77 | int i; | ||
| 78 | |||
| 79 | *buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf; | ||
| 80 | |||
| 81 | for (i = 0; i < 4; i++) { | ||
| 82 | axes[i] = readw(vortex->io + VORTEX_AXD + i * sizeof(u32)); | ||
| 83 | if (axes[i] == 0x1fff) axes[i] = -1; | ||
| 84 | } | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int vortex_open(struct gameport *gameport, int mode) | ||
| 90 | { | ||
| 91 | struct vortex *vortex = gameport->port_data; | ||
| 92 | |||
| 93 | switch (mode) { | ||
| 94 | case GAMEPORT_MODE_COOKED: | ||
| 95 | writeb(0x40, vortex->io + VORTEX_GCR); | ||
| 96 | msleep(VORTEX_DATA_WAIT); | ||
| 97 | return 0; | ||
| 98 | case GAMEPORT_MODE_RAW: | ||
| 99 | writeb(0x00, vortex->io + VORTEX_GCR); | ||
| 100 | return 0; | ||
| 101 | default: | ||
| 102 | return -1; | ||
| 103 | } | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
| 109 | { | ||
| 110 | struct vortex *vortex; | ||
| 111 | struct gameport *port; | ||
| 112 | int i; | ||
| 113 | |||
| 114 | vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL); | ||
| 115 | port = gameport_allocate_port(); | ||
| 116 | if (!vortex || !port) { | ||
| 117 | printk(KERN_ERR "vortex: Memory allocation failed.\n"); | ||
| 118 | kfree(vortex); | ||
| 119 | gameport_free_port(port); | ||
| 120 | return -ENOMEM; | ||
| 121 | } | ||
| 122 | |||
| 123 | for (i = 0; i < 6; i++) | ||
| 124 | if (~pci_resource_flags(dev, i) & IORESOURCE_IO) | ||
| 125 | break; | ||
| 126 | |||
| 127 | pci_enable_device(dev); | ||
| 128 | |||
| 129 | vortex->dev = dev; | ||
| 130 | vortex->gameport = port; | ||
| 131 | vortex->base = ioremap(pci_resource_start(vortex->dev, i), | ||
| 132 | pci_resource_len(vortex->dev, i)); | ||
| 133 | vortex->io = vortex->base + id->driver_data; | ||
| 134 | |||
| 135 | pci_set_drvdata(dev, vortex); | ||
| 136 | |||
| 137 | port->port_data = vortex; | ||
| 138 | port->fuzz = 64; | ||
| 139 | |||
| 140 | gameport_set_name(port, "AU88x0"); | ||
| 141 | gameport_set_phys(port, "pci%s/gameport0", pci_name(dev)); | ||
| 142 | port->dev.parent = &dev->dev; | ||
| 143 | port->read = vortex_read; | ||
| 144 | port->trigger = vortex_trigger; | ||
| 145 | port->cooked_read = vortex_cooked_read; | ||
| 146 | port->open = vortex_open; | ||
| 147 | |||
| 148 | gameport_register_port(port); | ||
| 149 | |||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static void __devexit vortex_remove(struct pci_dev *dev) | ||
| 154 | { | ||
| 155 | struct vortex *vortex = pci_get_drvdata(dev); | ||
| 156 | |||
| 157 | gameport_unregister_port(vortex->gameport); | ||
| 158 | iounmap(vortex->base); | ||
| 159 | kfree(vortex); | ||
| 160 | } | ||
| 161 | |||
| 162 | static struct pci_device_id vortex_id_table[] = { | ||
| 163 | { 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 }, | ||
| 164 | { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 }, | ||
| 165 | { 0 } | ||
| 166 | }; | ||
| 167 | |||
| 168 | static struct pci_driver vortex_driver = { | ||
| 169 | .name = "vortex_gameport", | ||
| 170 | .id_table = vortex_id_table, | ||
| 171 | .probe = vortex_probe, | ||
| 172 | .remove = __devexit_p(vortex_remove), | ||
| 173 | }; | ||
| 174 | |||
| 175 | static int __init vortex_init(void) | ||
| 176 | { | ||
| 177 | return pci_register_driver(&vortex_driver); | ||
| 178 | } | ||
| 179 | |||
| 180 | static void __exit vortex_exit(void) | ||
| 181 | { | ||
| 182 | pci_unregister_driver(&vortex_driver); | ||
| 183 | } | ||
| 184 | |||
| 185 | module_init(vortex_init); | ||
| 186 | module_exit(vortex_exit); | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index 83c77c990dda..7c4b4d37b3e6 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -219,10 +219,24 @@ void input_release_device(struct input_handle *handle) | |||
| 219 | 219 | ||
| 220 | int input_open_device(struct input_handle *handle) | 220 | int input_open_device(struct input_handle *handle) |
| 221 | { | 221 | { |
| 222 | struct input_dev *dev = handle->dev; | ||
| 223 | int err; | ||
| 224 | |||
| 225 | err = down_interruptible(&dev->sem); | ||
| 226 | if (err) | ||
| 227 | return err; | ||
| 228 | |||
| 222 | handle->open++; | 229 | handle->open++; |
| 223 | if (handle->dev->open) | 230 | |
| 224 | return handle->dev->open(handle->dev); | 231 | if (!dev->users++ && dev->open) |
| 225 | return 0; | 232 | err = dev->open(dev); |
| 233 | |||
| 234 | if (err) | ||
| 235 | handle->open--; | ||
| 236 | |||
| 237 | up(&dev->sem); | ||
| 238 | |||
| 239 | return err; | ||
| 226 | } | 240 | } |
| 227 | 241 | ||
| 228 | int input_flush_device(struct input_handle* handle, struct file* file) | 242 | int input_flush_device(struct input_handle* handle, struct file* file) |
| @@ -235,10 +249,17 @@ int input_flush_device(struct input_handle* handle, struct file* file) | |||
| 235 | 249 | ||
| 236 | void input_close_device(struct input_handle *handle) | 250 | void input_close_device(struct input_handle *handle) |
| 237 | { | 251 | { |
| 252 | struct input_dev *dev = handle->dev; | ||
| 253 | |||
| 238 | input_release_device(handle); | 254 | input_release_device(handle); |
| 239 | if (handle->dev->close) | 255 | |
| 240 | handle->dev->close(handle->dev); | 256 | down(&dev->sem); |
| 257 | |||
| 258 | if (!--dev->users && dev->close) | ||
| 259 | dev->close(dev); | ||
| 241 | handle->open--; | 260 | handle->open--; |
| 261 | |||
| 262 | up(&dev->sem); | ||
| 242 | } | 263 | } |
| 243 | 264 | ||
| 244 | static void input_link_handle(struct input_handle *handle) | 265 | static void input_link_handle(struct input_handle *handle) |
| @@ -415,6 +436,8 @@ void input_register_device(struct input_dev *dev) | |||
| 415 | 436 | ||
| 416 | set_bit(EV_SYN, dev->evbit); | 437 | set_bit(EV_SYN, dev->evbit); |
| 417 | 438 | ||
| 439 | init_MUTEX(&dev->sem); | ||
| 440 | |||
| 418 | /* | 441 | /* |
| 419 | * If delay and period are pre-set by the driver, then autorepeating | 442 | * If delay and period are pre-set by the driver, then autorepeating |
| 420 | * is handled by the driver itself and we don't do it in input.c. | 443 | * is handled by the driver itself and we don't do it in input.c. |
| @@ -674,6 +697,8 @@ static int input_handlers_read(char *buf, char **start, off_t pos, int count, in | |||
| 674 | return (count > cnt) ? cnt : count; | 697 | return (count > cnt) ? cnt : count; |
| 675 | } | 698 | } |
| 676 | 699 | ||
| 700 | static struct file_operations input_fileops; | ||
| 701 | |||
| 677 | static int __init input_proc_init(void) | 702 | static int __init input_proc_init(void) |
| 678 | { | 703 | { |
| 679 | struct proc_dir_entry *entry; | 704 | struct proc_dir_entry *entry; |
| @@ -688,6 +713,8 @@ static int __init input_proc_init(void) | |||
| 688 | return -ENOMEM; | 713 | return -ENOMEM; |
| 689 | } | 714 | } |
| 690 | entry->owner = THIS_MODULE; | 715 | entry->owner = THIS_MODULE; |
| 716 | input_fileops = *entry->proc_fops; | ||
| 717 | entry->proc_fops = &input_fileops; | ||
| 691 | entry->proc_fops->poll = input_devices_poll; | 718 | entry->proc_fops->poll = input_devices_poll; |
| 692 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); | 719 | entry = create_proc_read_entry("handlers", 0, proc_bus_input_dir, input_handlers_read, NULL); |
| 693 | if (entry == NULL) { | 720 | if (entry == NULL) { |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 39775fc380c7..ff8e1bbd0e13 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -285,48 +285,33 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
| 285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); | 285 | (POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR)); |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 288 | static int joydev_ioctl_common(struct joydev *joydev, unsigned int cmd, void __user *argp) |
| 289 | { | 289 | { |
| 290 | struct joydev_list *list = file->private_data; | ||
| 291 | struct joydev *joydev = list->joydev; | ||
| 292 | struct input_dev *dev = joydev->handle.dev; | 290 | struct input_dev *dev = joydev->handle.dev; |
| 293 | void __user *argp = (void __user *)arg; | ||
| 294 | int i, j; | 291 | int i, j; |
| 295 | 292 | ||
| 296 | if (!joydev->exist) return -ENODEV; | ||
| 297 | |||
| 298 | switch (cmd) { | 293 | switch (cmd) { |
| 299 | 294 | ||
| 300 | case JS_SET_CAL: | 295 | case JS_SET_CAL: |
| 301 | return copy_from_user(&joydev->glue.JS_CORR, argp, | 296 | return copy_from_user(&joydev->glue.JS_CORR, argp, |
| 302 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 297 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
| 303 | case JS_GET_CAL: | 298 | case JS_GET_CAL: |
| 304 | return copy_to_user(argp, &joydev->glue.JS_CORR, | 299 | return copy_to_user(argp, &joydev->glue.JS_CORR, |
| 305 | sizeof(struct JS_DATA_TYPE)) ? -EFAULT : 0; | 300 | sizeof(joydev->glue.JS_CORR)) ? -EFAULT : 0; |
| 306 | case JS_SET_TIMEOUT: | 301 | case JS_SET_TIMEOUT: |
| 307 | return get_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 302 | return get_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
| 308 | case JS_GET_TIMEOUT: | 303 | case JS_GET_TIMEOUT: |
| 309 | return put_user(joydev->glue.JS_TIMEOUT, (int __user *) arg); | 304 | return put_user(joydev->glue.JS_TIMEOUT, (s32 __user *) argp); |
| 310 | case JS_SET_TIMELIMIT: | ||
| 311 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
| 312 | case JS_GET_TIMELIMIT: | ||
| 313 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
| 314 | case JS_SET_ALL: | ||
| 315 | return copy_from_user(&joydev->glue, argp, | ||
| 316 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
| 317 | case JS_GET_ALL: | ||
| 318 | return copy_to_user(argp, &joydev->glue, | ||
| 319 | sizeof(struct JS_DATA_SAVE_TYPE)) ? -EFAULT : 0; | ||
| 320 | 305 | ||
| 321 | case JSIOCGVERSION: | 306 | case JSIOCGVERSION: |
| 322 | return put_user(JS_VERSION, (__u32 __user *) arg); | 307 | return put_user(JS_VERSION, (__u32 __user *) argp); |
| 323 | case JSIOCGAXES: | 308 | case JSIOCGAXES: |
| 324 | return put_user(joydev->nabs, (__u8 __user *) arg); | 309 | return put_user(joydev->nabs, (__u8 __user *) argp); |
| 325 | case JSIOCGBUTTONS: | 310 | case JSIOCGBUTTONS: |
| 326 | return put_user(joydev->nkey, (__u8 __user *) arg); | 311 | return put_user(joydev->nkey, (__u8 __user *) argp); |
| 327 | case JSIOCSCORR: | 312 | case JSIOCSCORR: |
| 328 | if (copy_from_user(joydev->corr, argp, | 313 | if (copy_from_user(joydev->corr, argp, |
| 329 | sizeof(struct js_corr) * joydev->nabs)) | 314 | sizeof(joydev->corr[0]) * joydev->nabs)) |
| 330 | return -EFAULT; | 315 | return -EFAULT; |
| 331 | for (i = 0; i < joydev->nabs; i++) { | 316 | for (i = 0; i < joydev->nabs; i++) { |
| 332 | j = joydev->abspam[i]; | 317 | j = joydev->abspam[i]; |
| @@ -335,7 +320,7 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 335 | return 0; | 320 | return 0; |
| 336 | case JSIOCGCORR: | 321 | case JSIOCGCORR: |
| 337 | return copy_to_user(argp, joydev->corr, | 322 | return copy_to_user(argp, joydev->corr, |
| 338 | sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0; | 323 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
| 339 | case JSIOCSAXMAP: | 324 | case JSIOCSAXMAP: |
| 340 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) | 325 | if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1))) |
| 341 | return -EFAULT; | 326 | return -EFAULT; |
| @@ -371,6 +356,84 @@ static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 371 | return -EINVAL; | 356 | return -EINVAL; |
| 372 | } | 357 | } |
| 373 | 358 | ||
| 359 | #ifdef CONFIG_COMPAT | ||
| 360 | static long joydev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 361 | { | ||
| 362 | struct joydev_list *list = file->private_data; | ||
| 363 | struct joydev *joydev = list->joydev; | ||
| 364 | void __user *argp = (void __user *)arg; | ||
| 365 | s32 tmp32; | ||
| 366 | struct JS_DATA_SAVE_TYPE_32 ds32; | ||
| 367 | int err; | ||
| 368 | |||
| 369 | if (!joydev->exist) return -ENODEV; | ||
| 370 | switch(cmd) { | ||
| 371 | case JS_SET_TIMELIMIT: | ||
| 372 | err = get_user(tmp32, (s32 __user *) arg); | ||
| 373 | if (err == 0) | ||
| 374 | joydev->glue.JS_TIMELIMIT = tmp32; | ||
| 375 | break; | ||
| 376 | case JS_GET_TIMELIMIT: | ||
| 377 | tmp32 = joydev->glue.JS_TIMELIMIT; | ||
| 378 | err = put_user(tmp32, (s32 __user *) arg); | ||
| 379 | break; | ||
| 380 | |||
| 381 | case JS_SET_ALL: | ||
| 382 | err = copy_from_user(&ds32, argp, | ||
| 383 | sizeof(ds32)) ? -EFAULT : 0; | ||
| 384 | if (err == 0) { | ||
| 385 | joydev->glue.JS_TIMEOUT = ds32.JS_TIMEOUT; | ||
| 386 | joydev->glue.BUSY = ds32.BUSY; | ||
| 387 | joydev->glue.JS_EXPIRETIME = ds32.JS_EXPIRETIME; | ||
| 388 | joydev->glue.JS_TIMELIMIT = ds32.JS_TIMELIMIT; | ||
| 389 | joydev->glue.JS_SAVE = ds32.JS_SAVE; | ||
| 390 | joydev->glue.JS_CORR = ds32.JS_CORR; | ||
| 391 | } | ||
| 392 | break; | ||
| 393 | |||
| 394 | case JS_GET_ALL: | ||
| 395 | ds32.JS_TIMEOUT = joydev->glue.JS_TIMEOUT; | ||
| 396 | ds32.BUSY = joydev->glue.BUSY; | ||
| 397 | ds32.JS_EXPIRETIME = joydev->glue.JS_EXPIRETIME; | ||
| 398 | ds32.JS_TIMELIMIT = joydev->glue.JS_TIMELIMIT; | ||
| 399 | ds32.JS_SAVE = joydev->glue.JS_SAVE; | ||
| 400 | ds32.JS_CORR = joydev->glue.JS_CORR; | ||
| 401 | |||
| 402 | err = copy_to_user(argp, &ds32, | ||
| 403 | sizeof(ds32)) ? -EFAULT : 0; | ||
| 404 | break; | ||
| 405 | |||
| 406 | default: | ||
| 407 | err = joydev_ioctl_common(joydev, cmd, argp); | ||
| 408 | } | ||
| 409 | return err; | ||
| 410 | } | ||
| 411 | #endif /* CONFIG_COMPAT */ | ||
| 412 | |||
| 413 | static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
| 414 | { | ||
| 415 | struct joydev_list *list = file->private_data; | ||
| 416 | struct joydev *joydev = list->joydev; | ||
| 417 | void __user *argp = (void __user *)arg; | ||
| 418 | |||
| 419 | if (!joydev->exist) return -ENODEV; | ||
| 420 | |||
| 421 | switch(cmd) { | ||
| 422 | case JS_SET_TIMELIMIT: | ||
| 423 | return get_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
| 424 | case JS_GET_TIMELIMIT: | ||
| 425 | return put_user(joydev->glue.JS_TIMELIMIT, (long __user *) arg); | ||
| 426 | case JS_SET_ALL: | ||
| 427 | return copy_from_user(&joydev->glue, argp, | ||
| 428 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
| 429 | case JS_GET_ALL: | ||
| 430 | return copy_to_user(argp, &joydev->glue, | ||
| 431 | sizeof(joydev->glue)) ? -EFAULT : 0; | ||
| 432 | default: | ||
| 433 | return joydev_ioctl_common(joydev, cmd, argp); | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 374 | static struct file_operations joydev_fops = { | 437 | static struct file_operations joydev_fops = { |
| 375 | .owner = THIS_MODULE, | 438 | .owner = THIS_MODULE, |
| 376 | .read = joydev_read, | 439 | .read = joydev_read, |
| @@ -379,6 +442,9 @@ static struct file_operations joydev_fops = { | |||
| 379 | .open = joydev_open, | 442 | .open = joydev_open, |
| 380 | .release = joydev_release, | 443 | .release = joydev_release, |
| 381 | .ioctl = joydev_ioctl, | 444 | .ioctl = joydev_ioctl, |
| 445 | #ifdef CONFIG_COMPAT | ||
| 446 | .compat_ioctl = joydev_compat_ioctl, | ||
| 447 | #endif | ||
| 382 | .fasync = joydev_fasync, | 448 | .fasync = joydev_fasync, |
| 383 | }; | 449 | }; |
| 384 | 450 | ||
diff --git a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c index ad39fe4bf35f..bf34f75b9467 100644 --- a/drivers/input/joystick/a3d.c +++ b/drivers/input/joystick/a3d.c | |||
| @@ -185,7 +185,7 @@ static void a3d_poll(struct gameport *gameport) | |||
| 185 | a3d->reads++; | 185 | a3d->reads++; |
| 186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || | 186 | if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length || |
| 187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) | 187 | data[0] != a3d->mode || a3d_csum(data, a3d->length)) |
| 188 | a3d->bads++; | 188 | a3d->bads++; |
| 189 | else | 189 | else |
| 190 | a3d_read(a3d, data); | 190 | a3d_read(a3d, data); |
| 191 | } | 191 | } |
diff --git a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c index 83f6dafc1716..265962956c63 100644 --- a/drivers/input/joystick/adi.c +++ b/drivers/input/joystick/adi.c | |||
| @@ -82,7 +82,7 @@ static char adi_cm2_abs[] = { ABS_X, ABS_Y, ABS_Z, ABS_RX, ABS_RY, ABS_RZ }; | |||
| 82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; | 82 | static char adi_wmf_abs[] = { ABS_WHEEL, ABS_GAS, ABS_BRAKE, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y, ABS_HAT2X, ABS_HAT2Y }; |
| 83 | 83 | ||
| 84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; | 84 | static short adi_wmgpe_key[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }; |
| 85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; | 85 | static short adi_wmi_key[] = { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_EXTRA }; |
| 86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; | 86 | static short adi_wmed3d_key[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2 }; |
| 87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; | 87 | static short adi_cm2_key[] = { BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8 }; |
| 88 | 88 | ||
| @@ -183,7 +183,7 @@ static void adi_move_bits(struct adi_port *port, int length) | |||
| 183 | int i; | 183 | int i; |
| 184 | struct adi *adi = port->adi; | 184 | struct adi *adi = port->adi; |
| 185 | 185 | ||
| 186 | adi[0].idx = adi[1].idx = 0; | 186 | adi[0].idx = adi[1].idx = 0; |
| 187 | 187 | ||
| 188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; | 188 | if (adi[0].ret <= 0 || adi[1].ret <= 0) return; |
| 189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; | 189 | if (adi[0].data[0] & 0x20 || ~adi[1].data[0] & 0x20) return; |
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index cf36ca9b92f3..033456bb9fe0 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
| @@ -51,7 +51,8 @@ MODULE_PARM_DESC(map, "Map of attached joysticks in form of <a>,<b> (default is | |||
| 51 | 51 | ||
| 52 | __obsolete_setup("amijoy="); | 52 | __obsolete_setup("amijoy="); |
| 53 | 53 | ||
| 54 | static int amijoy_used[2] = { 0, 0 }; | 54 | static int amijoy_used; |
| 55 | static DECLARE_MUTEX(amijoy_sem); | ||
| 55 | static struct input_dev amijoy_dev[2]; | 56 | static struct input_dev amijoy_dev[2]; |
| 56 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; | 57 | static char *amijoy_phys[2] = { "amijoy/input0", "amijoy/input1" }; |
| 57 | 58 | ||
| @@ -84,26 +85,30 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
| 84 | 85 | ||
| 85 | static int amijoy_open(struct input_dev *dev) | 86 | static int amijoy_open(struct input_dev *dev) |
| 86 | { | 87 | { |
| 87 | int *used = dev->private; | 88 | int err; |
| 88 | 89 | ||
| 89 | if ((*used)++) | 90 | err = down_interruptible(&amijoy_sem); |
| 90 | return 0; | 91 | if (err) |
| 92 | return err; | ||
| 91 | 93 | ||
| 92 | if (request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { | 94 | if (!amijoy_used && request_irq(IRQ_AMIGA_VERTB, amijoy_interrupt, 0, "amijoy", amijoy_interrupt)) { |
| 93 | (*used)--; | ||
| 94 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 95 | printk(KERN_ERR "amijoy.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
| 95 | return -EBUSY; | 96 | err = -EBUSY; |
| 97 | goto out; | ||
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | return 0; | 100 | amijoy_used++; |
| 101 | out: | ||
| 102 | up(&amijoy_sem); | ||
| 103 | return err; | ||
| 99 | } | 104 | } |
| 100 | 105 | ||
| 101 | static void amijoy_close(struct input_dev *dev) | 106 | static void amijoy_close(struct input_dev *dev) |
| 102 | { | 107 | { |
| 103 | int *used = dev->private; | 108 | down(&amijoysem); |
| 104 | 109 | if (!--amijoy_used) | |
| 105 | if (!--(*used)) | ||
| 106 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); | 110 | free_irq(IRQ_AMIGA_VERTB, amijoy_interrupt); |
| 111 | up(&amijoy_sem); | ||
| 107 | } | 112 | } |
| 108 | 113 | ||
| 109 | static int __init amijoy_init(void) | 114 | static int __init amijoy_init(void) |
| @@ -138,8 +143,6 @@ static int __init amijoy_init(void) | |||
| 138 | amijoy_dev[i].id.product = 0x0003; | 143 | amijoy_dev[i].id.product = 0x0003; |
| 139 | amijoy_dev[i].id.version = 0x0100; | 144 | amijoy_dev[i].id.version = 0x0100; |
| 140 | 145 | ||
| 141 | amijoy_dev[i].private = amijoy_used + i; | ||
| 142 | |||
| 143 | input_register_device(amijoy_dev + i); | 146 | input_register_device(amijoy_dev + i); |
| 144 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); | 147 | printk(KERN_INFO "input: %s at joy%ddat\n", amijoy_name, i); |
| 145 | } | 148 | } |
diff --git a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c index cfdd3acf06a1..fbd3eed07f90 100644 --- a/drivers/input/joystick/db9.c +++ b/drivers/input/joystick/db9.c | |||
| @@ -87,7 +87,7 @@ __obsolete_setup("db9_3="); | |||
| 87 | #define DB9_NORMAL 0x0a | 87 | #define DB9_NORMAL 0x0a |
| 88 | #define DB9_NOSELECT 0x08 | 88 | #define DB9_NOSELECT 0x08 |
| 89 | 89 | ||
| 90 | #define DB9_MAX_DEVICES 2 | 90 | #define DB9_MAX_DEVICES 2 |
| 91 | 91 | ||
| 92 | #define DB9_GENESIS6_DELAY 14 | 92 | #define DB9_GENESIS6_DELAY 14 |
| 93 | #define DB9_REFRESH_TIME HZ/100 | 93 | #define DB9_REFRESH_TIME HZ/100 |
| @@ -98,6 +98,7 @@ struct db9 { | |||
| 98 | struct pardevice *pd; | 98 | struct pardevice *pd; |
| 99 | int mode; | 99 | int mode; |
| 100 | int used; | 100 | int used; |
| 101 | struct semaphore sem; | ||
| 101 | char phys[2][32]; | 102 | char phys[2][32]; |
| 102 | }; | 103 | }; |
| 103 | 104 | ||
| @@ -503,6 +504,11 @@ static int db9_open(struct input_dev *dev) | |||
| 503 | { | 504 | { |
| 504 | struct db9 *db9 = dev->private; | 505 | struct db9 *db9 = dev->private; |
| 505 | struct parport *port = db9->pd->port; | 506 | struct parport *port = db9->pd->port; |
| 507 | int err; | ||
| 508 | |||
| 509 | err = down_interruptible(&db9->sem); | ||
| 510 | if (err) | ||
| 511 | return err; | ||
| 506 | 512 | ||
| 507 | if (!db9->used++) { | 513 | if (!db9->used++) { |
| 508 | parport_claim(db9->pd); | 514 | parport_claim(db9->pd); |
| @@ -514,6 +520,7 @@ static int db9_open(struct input_dev *dev) | |||
| 514 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); | 520 | mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME); |
| 515 | } | 521 | } |
| 516 | 522 | ||
| 523 | up(&db9->sem); | ||
| 517 | return 0; | 524 | return 0; |
| 518 | } | 525 | } |
| 519 | 526 | ||
| @@ -522,12 +529,14 @@ static void db9_close(struct input_dev *dev) | |||
| 522 | struct db9 *db9 = dev->private; | 529 | struct db9 *db9 = dev->private; |
| 523 | struct parport *port = db9->pd->port; | 530 | struct parport *port = db9->pd->port; |
| 524 | 531 | ||
| 532 | down(&db9->sem); | ||
| 525 | if (!--db9->used) { | 533 | if (!--db9->used) { |
| 526 | del_timer(&db9->timer); | 534 | del_timer_sync(&db9->timer); |
| 527 | parport_write_control(port, 0x00); | 535 | parport_write_control(port, 0x00); |
| 528 | parport_data_forward(port); | 536 | parport_data_forward(port); |
| 529 | parport_release(db9->pd); | 537 | parport_release(db9->pd); |
| 530 | } | 538 | } |
| 539 | up(&db9->sem); | ||
| 531 | } | 540 | } |
| 532 | 541 | ||
| 533 | static struct db9 __init *db9_probe(int *config, int nargs) | 542 | static struct db9 __init *db9_probe(int *config, int nargs) |
| @@ -563,12 +572,12 @@ static struct db9 __init *db9_probe(int *config, int nargs) | |||
| 563 | } | 572 | } |
| 564 | } | 573 | } |
| 565 | 574 | ||
| 566 | if (!(db9 = kmalloc(sizeof(struct db9), GFP_KERNEL))) { | 575 | if (!(db9 = kcalloc(1, sizeof(struct db9), GFP_KERNEL))) { |
| 567 | parport_put_port(pp); | 576 | parport_put_port(pp); |
| 568 | return NULL; | 577 | return NULL; |
| 569 | } | 578 | } |
| 570 | memset(db9, 0, sizeof(struct db9)); | ||
| 571 | 579 | ||
| 580 | init_MUTEX(&db9->sem); | ||
| 572 | db9->mode = config[1]; | 581 | db9->mode = config[1]; |
| 573 | init_timer(&db9->timer); | 582 | init_timer(&db9->timer); |
| 574 | db9->timer.data = (long) db9; | 583 | db9->timer.data = (long) db9; |
diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 8732f52bdd08..95bbdd302aad 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux | 2 | * NES, SNES, N64, MultiSystem, PSX gamepad driver for Linux |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> | 4 | * Copyright (c) 1999-2004 Vojtech Pavlik <vojtech@suse.cz> |
| 5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> | 5 | * Copyright (c) 2004 Peter Nelson <rufus-kernel@hackish.org> |
| 6 | * | 6 | * |
| 7 | * Based on the work of: | 7 | * Based on the work of: |
| 8 | * Andree Borrmann John Dahlstrom | 8 | * Andree Borrmann John Dahlstrom |
| 9 | * David Kuder Nathan Hand | 9 | * David Kuder Nathan Hand |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | /* | 12 | /* |
| @@ -81,6 +81,7 @@ struct gc { | |||
| 81 | struct timer_list timer; | 81 | struct timer_list timer; |
| 82 | unsigned char pads[GC_MAX + 1]; | 82 | unsigned char pads[GC_MAX + 1]; |
| 83 | int used; | 83 | int used; |
| 84 | struct semaphore sem; | ||
| 84 | char phys[5][32]; | 85 | char phys[5][32]; |
| 85 | }; | 86 | }; |
| 86 | 87 | ||
| @@ -433,7 +434,7 @@ static void gc_timer(unsigned long private) | |||
| 433 | gc_psx_read_packet(gc, data_psx, data); | 434 | gc_psx_read_packet(gc, data_psx, data); |
| 434 | 435 | ||
| 435 | for (i = 0; i < 5; i++) { | 436 | for (i = 0; i < 5; i++) { |
| 436 | switch (data[i]) { | 437 | switch (data[i]) { |
| 437 | 438 | ||
| 438 | case GC_PSX_RUMBLE: | 439 | case GC_PSX_RUMBLE: |
| 439 | 440 | ||
| @@ -503,22 +504,33 @@ static void gc_timer(unsigned long private) | |||
| 503 | static int gc_open(struct input_dev *dev) | 504 | static int gc_open(struct input_dev *dev) |
| 504 | { | 505 | { |
| 505 | struct gc *gc = dev->private; | 506 | struct gc *gc = dev->private; |
| 507 | int err; | ||
| 508 | |||
| 509 | err = down_interruptible(&gc->sem); | ||
| 510 | if (err) | ||
| 511 | return err; | ||
| 512 | |||
| 506 | if (!gc->used++) { | 513 | if (!gc->used++) { |
| 507 | parport_claim(gc->pd); | 514 | parport_claim(gc->pd); |
| 508 | parport_write_control(gc->pd->port, 0x04); | 515 | parport_write_control(gc->pd->port, 0x04); |
| 509 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); | 516 | mod_timer(&gc->timer, jiffies + GC_REFRESH_TIME); |
| 510 | } | 517 | } |
| 518 | |||
| 519 | up(&gc->sem); | ||
| 511 | return 0; | 520 | return 0; |
| 512 | } | 521 | } |
| 513 | 522 | ||
| 514 | static void gc_close(struct input_dev *dev) | 523 | static void gc_close(struct input_dev *dev) |
| 515 | { | 524 | { |
| 516 | struct gc *gc = dev->private; | 525 | struct gc *gc = dev->private; |
| 526 | |||
| 527 | down(&gc->sem); | ||
| 517 | if (!--gc->used) { | 528 | if (!--gc->used) { |
| 518 | del_timer(&gc->timer); | 529 | del_timer_sync(&gc->timer); |
| 519 | parport_write_control(gc->pd->port, 0x00); | 530 | parport_write_control(gc->pd->port, 0x00); |
| 520 | parport_release(gc->pd); | 531 | parport_release(gc->pd); |
| 521 | } | 532 | } |
| 533 | up(&gc->sem); | ||
| 522 | } | 534 | } |
| 523 | 535 | ||
| 524 | static struct gc __init *gc_probe(int *config, int nargs) | 536 | static struct gc __init *gc_probe(int *config, int nargs) |
| @@ -542,11 +554,12 @@ static struct gc __init *gc_probe(int *config, int nargs) | |||
| 542 | return NULL; | 554 | return NULL; |
| 543 | } | 555 | } |
| 544 | 556 | ||
| 545 | if (!(gc = kmalloc(sizeof(struct gc), GFP_KERNEL))) { | 557 | if (!(gc = kcalloc(1, sizeof(struct gc), GFP_KERNEL))) { |
| 546 | parport_put_port(pp); | 558 | parport_put_port(pp); |
| 547 | return NULL; | 559 | return NULL; |
| 548 | } | 560 | } |
| 549 | memset(gc, 0, sizeof(struct gc)); | 561 | |
| 562 | init_MUTEX(&gc->sem); | ||
| 550 | 563 | ||
| 551 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 564 | gc->pd = parport_register_device(pp, "gamecon", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
| 552 | 565 | ||
diff --git a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c index ad13f09a4e71..7d969420066c 100644 --- a/drivers/input/joystick/gf2k.c +++ b/drivers/input/joystick/gf2k.c | |||
| @@ -329,7 +329,7 @@ static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv) | |||
| 329 | 329 | ||
| 330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { | 330 | for (i = 0; i < gf2k_axes[gf2k->id]; i++) { |
| 331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : | 331 | gf2k->dev.absmax[gf2k_abs[i]] = (i < 2) ? gf2k->dev.abs[gf2k_abs[i]] * 2 - 32 : |
| 332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; | 332 | gf2k->dev.abs[gf2k_abs[0]] + gf2k->dev.abs[gf2k_abs[1]] - 32; |
| 333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; | 333 | gf2k->dev.absmin[gf2k_abs[i]] = 32; |
| 334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; | 334 | gf2k->dev.absfuzz[gf2k_abs[i]] = 8; |
| 335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; | 335 | gf2k->dev.absflat[gf2k_abs[i]] = (i < 2) ? 24 : 0; |
diff --git a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c index 42e5005d621f..0da7bd133ccf 100644 --- a/drivers/input/joystick/grip_mp.c +++ b/drivers/input/joystick/grip_mp.c | |||
| @@ -171,7 +171,7 @@ static int mp_io(struct gameport* gameport, int sendflags, int sendcode, u32 *pa | |||
| 171 | *packet = 0; | 171 | *packet = 0; |
| 172 | raw_data = gameport_read(gameport); | 172 | raw_data = gameport_read(gameport); |
| 173 | if (raw_data & 1) | 173 | if (raw_data & 1) |
| 174 | return IO_RETRY; | 174 | return IO_RETRY; |
| 175 | 175 | ||
| 176 | for (i = 0; i < 64; i++) { | 176 | for (i = 0; i < 64; i++) { |
| 177 | raw_data = gameport_read(gameport); | 177 | raw_data = gameport_read(gameport); |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index 028f3513629a..e31b7b93fde2 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
| @@ -78,6 +78,7 @@ static struct iforce_device iforce_device[] = { | |||
| 78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 78 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
| 79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
| 80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 80 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
| 81 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | ||
| 81 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 82 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
| 82 | }; | 83 | }; |
| 83 | 84 | ||
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index 617c0b0e5a39..6369a24684fe 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
| @@ -229,6 +229,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
| 229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 229 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
| 230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 230 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
| 231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 231 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
| 232 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | ||
| 232 | { } /* Terminating entry */ | 233 | { } /* Terminating entry */ |
| 233 | }; | 234 | }; |
| 234 | 235 | ||
diff --git a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c index ec0a2a64d49c..a436f2220856 100644 --- a/drivers/input/joystick/spaceball.c +++ b/drivers/input/joystick/spaceball.c | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
| 5 | * | 5 | * |
| 6 | * Based on the work of: | 6 | * Based on the work of: |
| 7 | * David Thompson | 7 | * David Thompson |
| 8 | * Joseph Krahn | 8 | * Joseph Krahn |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | /* | 11 | /* |
diff --git a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c index 874367bfab08..01fd2e4791ae 100644 --- a/drivers/input/joystick/spaceorb.c +++ b/drivers/input/joystick/spaceorb.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * Copyright (c) 1999-2001 Vojtech Pavlik | 4 | * Copyright (c) 1999-2001 Vojtech Pavlik |
| 5 | * | 5 | * |
| 6 | * Based on the work of: | 6 | * Based on the work of: |
| 7 | * David Thompson | 7 | * David Thompson |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | /* | 10 | /* |
diff --git a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c index aaee52ceb920..9eb9954cac6e 100644 --- a/drivers/input/joystick/tmdc.c +++ b/drivers/input/joystick/tmdc.c | |||
| @@ -79,7 +79,7 @@ static short tmdc_btn_pad[TMDC_BTN] = | |||
| 79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; | 79 | { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_START, BTN_SELECT, BTN_TL, BTN_TR }; |
| 80 | static short tmdc_btn_joy[TMDC_BTN] = | 80 | static short tmdc_btn_joy[TMDC_BTN] = |
| 81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, | 81 | { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_THUMB2, BTN_PINKIE, |
| 82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; | 82 | BTN_BASE3, BTN_BASE4, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z }; |
| 83 | static short tmdc_btn_fm[TMDC_BTN] = | 83 | static short tmdc_btn_fm[TMDC_BTN] = |
| 84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; | 84 | { BTN_TRIGGER, BTN_C, BTN_B, BTN_A, BTN_THUMB, BTN_X, BTN_Y, BTN_Z, BTN_TOP, BTN_TOP2 }; |
| 85 | static short tmdc_btn_at[TMDC_BTN] = | 85 | static short tmdc_btn_at[TMDC_BTN] = |
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c index dd88b9cb49fa..28100d461cb7 100644 --- a/drivers/input/joystick/turbografx.c +++ b/drivers/input/joystick/turbografx.c | |||
| @@ -84,6 +84,7 @@ static struct tgfx { | |||
| 84 | char phys[7][32]; | 84 | char phys[7][32]; |
| 85 | int sticks; | 85 | int sticks; |
| 86 | int used; | 86 | int used; |
| 87 | struct semaphore sem; | ||
| 87 | } *tgfx_base[3]; | 88 | } *tgfx_base[3]; |
| 88 | 89 | ||
| 89 | /* | 90 | /* |
| @@ -99,7 +100,7 @@ static void tgfx_timer(unsigned long private) | |||
| 99 | for (i = 0; i < 7; i++) | 100 | for (i = 0; i < 7; i++) |
| 100 | if (tgfx->sticks & (1 << i)) { | 101 | if (tgfx->sticks & (1 << i)) { |
| 101 | 102 | ||
| 102 | dev = tgfx->dev + i; | 103 | dev = tgfx->dev + i; |
| 103 | 104 | ||
| 104 | parport_write_data(tgfx->pd->port, ~(1 << i)); | 105 | parport_write_data(tgfx->pd->port, ~(1 << i)); |
| 105 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; | 106 | data1 = parport_read_status(tgfx->pd->port) ^ 0x7f; |
| @@ -122,23 +123,34 @@ static void tgfx_timer(unsigned long private) | |||
| 122 | 123 | ||
| 123 | static int tgfx_open(struct input_dev *dev) | 124 | static int tgfx_open(struct input_dev *dev) |
| 124 | { | 125 | { |
| 125 | struct tgfx *tgfx = dev->private; | 126 | struct tgfx *tgfx = dev->private; |
| 126 | if (!tgfx->used++) { | 127 | int err; |
| 128 | |||
| 129 | err = down_interruptible(&tgfx->sem); | ||
| 130 | if (err) | ||
| 131 | return err; | ||
| 132 | |||
| 133 | if (!tgfx->used++) { | ||
| 127 | parport_claim(tgfx->pd); | 134 | parport_claim(tgfx->pd); |
| 128 | parport_write_control(tgfx->pd->port, 0x04); | 135 | parport_write_control(tgfx->pd->port, 0x04); |
| 129 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); | 136 | mod_timer(&tgfx->timer, jiffies + TGFX_REFRESH_TIME); |
| 130 | } | 137 | } |
| 131 | return 0; | 138 | |
| 139 | up(&tgfx->sem); | ||
| 140 | return 0; | ||
| 132 | } | 141 | } |
| 133 | 142 | ||
| 134 | static void tgfx_close(struct input_dev *dev) | 143 | static void tgfx_close(struct input_dev *dev) |
| 135 | { | 144 | { |
| 136 | struct tgfx *tgfx = dev->private; | 145 | struct tgfx *tgfx = dev->private; |
| 137 | if (!--tgfx->used) { | 146 | |
| 138 | del_timer(&tgfx->timer); | 147 | down(&tgfx->sem); |
| 148 | if (!--tgfx->used) { | ||
| 149 | del_timer_sync(&tgfx->timer); | ||
| 139 | parport_write_control(tgfx->pd->port, 0x00); | 150 | parport_write_control(tgfx->pd->port, 0x00); |
| 140 | parport_release(tgfx->pd); | 151 | parport_release(tgfx->pd); |
| 141 | } | 152 | } |
| 153 | up(&tgfx->sem); | ||
| 142 | } | 154 | } |
| 143 | 155 | ||
| 144 | /* | 156 | /* |
| @@ -166,11 +178,12 @@ static struct tgfx __init *tgfx_probe(int *config, int nargs) | |||
| 166 | return NULL; | 178 | return NULL; |
| 167 | } | 179 | } |
| 168 | 180 | ||
| 169 | if (!(tgfx = kmalloc(sizeof(struct tgfx), GFP_KERNEL))) { | 181 | if (!(tgfx = kcalloc(1, sizeof(struct tgfx), GFP_KERNEL))) { |
| 170 | parport_put_port(pp); | 182 | parport_put_port(pp); |
| 171 | return NULL; | 183 | return NULL; |
| 172 | } | 184 | } |
| 173 | memset(tgfx, 0, sizeof(struct tgfx)); | 185 | |
| 186 | init_MUTEX(&tgfx->sem); | ||
| 174 | 187 | ||
| 175 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); | 188 | tgfx->pd = parport_register_device(pp, "turbografx", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL); |
| 176 | 189 | ||
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 82fad9a23ace..4d4985b59abf 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c | |||
| @@ -227,7 +227,7 @@ static ssize_t atkbd_do_set_##_name(struct device *d, struct device_attribute *a | |||
| 227 | { \ | 227 | { \ |
| 228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ | 228 | return atkbd_attr_set_helper(d, b, s, atkbd_set_##_name); \ |
| 229 | } \ | 229 | } \ |
| 230 | static struct device_attribute atkbd_attr_##_name = \ | 230 | static struct device_attribute atkbd_attr_##_name = \ |
| 231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); | 231 | __ATTR(_name, S_IWUSR | S_IRUGO, atkbd_do_show_##_name, atkbd_do_set_##_name); |
| 232 | 232 | ||
| 233 | ATKBD_DEFINE_ATTR(extra); | 233 | ATKBD_DEFINE_ATTR(extra); |
| @@ -388,7 +388,7 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, | |||
| 388 | value = atkbd->release ? 0 : | 388 | value = atkbd->release ? 0 : |
| 389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); | 389 | (1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key))); |
| 390 | 390 | ||
| 391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ | 391 | switch (value) { /* Workaround Toshiba laptop multiple keypress */ |
| 392 | case 0: | 392 | case 0: |
| 393 | atkbd->last = 0; | 393 | atkbd->last = 0; |
| 394 | break; | 394 | break; |
| @@ -894,7 +894,7 @@ static int atkbd_reconnect(struct serio *serio) | |||
| 894 | if (atkbd->write) { | 894 | if (atkbd->write) { |
| 895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) | 895 | param[0] = (test_bit(LED_SCROLLL, atkbd->dev.led) ? 1 : 0) |
| 896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) | 896 | | (test_bit(LED_NUML, atkbd->dev.led) ? 2 : 0) |
| 897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); | 897 | | (test_bit(LED_CAPSL, atkbd->dev.led) ? 4 : 0); |
| 898 | 898 | ||
| 899 | if (atkbd_probe(atkbd)) | 899 | if (atkbd_probe(atkbd)) |
| 900 | return -1; | 900 | return -1; |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c index 0f1220a0ceb5..a8551711e8d6 100644 --- a/drivers/input/keyboard/corgikbd.c +++ b/drivers/input/keyboard/corgikbd.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #define CORGI_KEY_CALENDER KEY_F1 | 39 | #define CORGI_KEY_CALENDER KEY_F1 |
| 40 | #define CORGI_KEY_ADDRESS KEY_F2 | 40 | #define CORGI_KEY_ADDRESS KEY_F2 |
| 41 | #define CORGI_KEY_FN KEY_F3 | 41 | #define CORGI_KEY_FN KEY_F3 |
| 42 | #define CORGI_KEY_CANCEL KEY_F4 | ||
| 42 | #define CORGI_KEY_OFF KEY_SUSPEND | 43 | #define CORGI_KEY_OFF KEY_SUSPEND |
| 43 | #define CORGI_KEY_EXOK KEY_F5 | 44 | #define CORGI_KEY_EXOK KEY_F5 |
| 44 | #define CORGI_KEY_EXCANCEL KEY_F6 | 45 | #define CORGI_KEY_EXCANCEL KEY_F6 |
| @@ -46,6 +47,7 @@ | |||
| 46 | #define CORGI_KEY_EXJOGUP KEY_F8 | 47 | #define CORGI_KEY_EXJOGUP KEY_F8 |
| 47 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | 48 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL |
| 48 | #define CORGI_KEY_JAP2 KEY_LEFTALT | 49 | #define CORGI_KEY_JAP2 KEY_LEFTALT |
| 50 | #define CORGI_KEY_MAIL KEY_F10 | ||
| 49 | #define CORGI_KEY_OK KEY_F11 | 51 | #define CORGI_KEY_OK KEY_F11 |
| 50 | #define CORGI_KEY_MENU KEY_F12 | 52 | #define CORGI_KEY_MENU KEY_F12 |
| 51 | #define CORGI_HINGE_0 KEY_KP0 | 53 | #define CORGI_HINGE_0 KEY_KP0 |
| @@ -59,8 +61,8 @@ static unsigned char corgikbd_keycode[NR_SCANCODES] = { | |||
| 59 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | 61 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ |
| 60 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | 62 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ |
| 61 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | 63 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ |
| 62 | KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | 64 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ |
| 63 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | 65 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ |
| 64 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | 66 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ |
| 65 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ | 67 | CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2 /* 125-127 */ |
| 66 | }; | 68 | }; |
diff --git a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c index 2694ff2b5beb..098963c7cdd6 100644 --- a/drivers/input/keyboard/lkkbd.c +++ b/drivers/input/keyboard/lkkbd.c | |||
| @@ -15,10 +15,10 @@ | |||
| 15 | * information given below, I will _not_ be liable! | 15 | * information given below, I will _not_ be liable! |
| 16 | * | 16 | * |
| 17 | * RJ10 pinout: To DE9: Or DB25: | 17 | * RJ10 pinout: To DE9: Or DB25: |
| 18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) | 18 | * 1 - RxD <----> Pin 3 (TxD) <-> Pin 2 (TxD) |
| 19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) | 19 | * 2 - GND <----> Pin 5 (GND) <-> Pin 7 (GND) |
| 20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) | 20 | * 4 - TxD <----> Pin 2 (RxD) <-> Pin 3 (RxD) |
| 21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! | 21 | * 3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!! |
| 22 | * | 22 | * |
| 23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For | 23 | * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For |
| 24 | * RJ10, it's like this: | 24 | * RJ10, it's like this: |
diff --git a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c index d3e9dd6a13cd..8935290256b3 100644 --- a/drivers/input/keyboard/locomokbd.c +++ b/drivers/input/keyboard/locomokbd.c | |||
| @@ -42,7 +42,7 @@ MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); | |||
| 42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); | 42 | MODULE_DESCRIPTION("LoCoMo keyboard driver"); |
| 43 | MODULE_LICENSE("GPL"); | 43 | MODULE_LICENSE("GPL"); |
| 44 | 44 | ||
| 45 | #define LOCOMOKBD_NUMKEYS 128 | 45 | #define LOCOMOKBD_NUMKEYS 128 |
| 46 | 46 | ||
| 47 | #define KEY_ACTIVITY KEY_F16 | 47 | #define KEY_ACTIVITY KEY_F16 |
| 48 | #define KEY_CONTACT KEY_F18 | 48 | #define KEY_CONTACT KEY_F18 |
| @@ -61,7 +61,7 @@ static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = { | |||
| 61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ | 61 | KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0, /* 90 - 99 */ |
| 62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ | 62 | 0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A, /* 100 - 109 */ |
| 63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ | 63 | KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0, /* 110 - 119 */ |
| 64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ | 64 | KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 /* 120 - 128 */ |
| 65 | }; | 65 | }; |
| 66 | 66 | ||
| 67 | #define KB_ROWS 16 | 67 | #define KB_ROWS 16 |
| @@ -82,7 +82,7 @@ struct locomokbd { | |||
| 82 | struct locomo_dev *ldev; | 82 | struct locomo_dev *ldev; |
| 83 | unsigned long base; | 83 | unsigned long base; |
| 84 | spinlock_t lock; | 84 | spinlock_t lock; |
| 85 | 85 | ||
| 86 | struct timer_list timer; | 86 | struct timer_list timer; |
| 87 | }; | 87 | }; |
| 88 | 88 | ||
| @@ -95,7 +95,7 @@ static inline void locomokbd_charge_all(unsigned long membase) | |||
| 95 | static inline void locomokbd_activate_all(unsigned long membase) | 95 | static inline void locomokbd_activate_all(unsigned long membase) |
| 96 | { | 96 | { |
| 97 | unsigned long r; | 97 | unsigned long r; |
| 98 | 98 | ||
| 99 | locomo_writel(0, membase + LOCOMO_KSC); | 99 | locomo_writel(0, membase + LOCOMO_KSC); |
| 100 | r = locomo_readl(membase + LOCOMO_KIC); | 100 | r = locomo_readl(membase + LOCOMO_KIC); |
| 101 | r &= 0xFEFF; | 101 | r &= 0xFEFF; |
| @@ -127,7 +127,7 @@ static inline void locomokbd_reset_col(unsigned long membase, int col) | |||
| 127 | */ | 127 | */ |
| 128 | 128 | ||
| 129 | /* Scan the hardware keyboard and push any changes up through the input layer */ | 129 | /* Scan the hardware keyboard and push any changes up through the input layer */ |
| 130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) | 130 | static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) |
| 131 | { | 131 | { |
| 132 | unsigned int row, col, rowd, scancode; | 132 | unsigned int row, col, rowd, scancode; |
| 133 | unsigned long flags; | 133 | unsigned long flags; |
| @@ -138,7 +138,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
| 138 | 138 | ||
| 139 | if (regs) | 139 | if (regs) |
| 140 | input_regs(&locomokbd->input, regs); | 140 | input_regs(&locomokbd->input, regs); |
| 141 | 141 | ||
| 142 | locomokbd_charge_all(membase); | 142 | locomokbd_charge_all(membase); |
| 143 | 143 | ||
| 144 | num_pressed = 0; | 144 | num_pressed = 0; |
| @@ -146,9 +146,9 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
| 146 | 146 | ||
| 147 | locomokbd_activate_col(membase, col); | 147 | locomokbd_activate_col(membase, col); |
| 148 | udelay(KB_DELAY); | 148 | udelay(KB_DELAY); |
| 149 | 149 | ||
| 150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); | 150 | rowd = ~locomo_readl(membase + LOCOMO_KIB); |
| 151 | for (row = 0; row < KB_ROWS; row++ ) { | 151 | for (row = 0; row < KB_ROWS; row++) { |
| 152 | scancode = SCANCODE(col, row); | 152 | scancode = SCANCODE(col, row); |
| 153 | if (rowd & KB_ROWMASK(row)) { | 153 | if (rowd & KB_ROWMASK(row)) { |
| 154 | num_pressed += 1; | 154 | num_pressed += 1; |
| @@ -170,7 +170,7 @@ static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs * | |||
| 170 | spin_unlock_irqrestore(&locomokbd->lock, flags); | 170 | spin_unlock_irqrestore(&locomokbd->lock, flags); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | /* | 173 | /* |
| 174 | * LoCoMo keyboard interrupt handler. | 174 | * LoCoMo keyboard interrupt handler. |
| 175 | */ | 175 | */ |
| 176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 176 | static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
| @@ -205,8 +205,8 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
| 205 | memset(locomokbd, 0, sizeof(struct locomokbd)); | 205 | memset(locomokbd, 0, sizeof(struct locomokbd)); |
| 206 | 206 | ||
| 207 | /* try and claim memory region */ | 207 | /* try and claim memory region */ |
| 208 | if (!request_mem_region((unsigned long) dev->mapbase, | 208 | if (!request_mem_region((unsigned long) dev->mapbase, |
| 209 | dev->length, | 209 | dev->length, |
| 210 | LOCOMO_DRIVER_NAME(dev))) { | 210 | LOCOMO_DRIVER_NAME(dev))) { |
| 211 | ret = -EBUSY; | 211 | ret = -EBUSY; |
| 212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); | 212 | printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n"); |
| @@ -225,7 +225,7 @@ static int locomokbd_probe(struct locomo_dev *dev) | |||
| 225 | locomokbd->timer.data = (unsigned long) locomokbd; | 225 | locomokbd->timer.data = (unsigned long) locomokbd; |
| 226 | 226 | ||
| 227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | 227 | locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
| 228 | 228 | ||
| 229 | init_input_dev(&locomokbd->input); | 229 | init_input_dev(&locomokbd->input); |
| 230 | locomokbd->input.keycode = locomokbd->keycode; | 230 | locomokbd->input.keycode = locomokbd->keycode; |
| 231 | locomokbd->input.keycodesize = sizeof(unsigned char); | 231 | locomokbd->input.keycodesize = sizeof(unsigned char); |
| @@ -271,11 +271,11 @@ free: | |||
| 271 | static int locomokbd_remove(struct locomo_dev *dev) | 271 | static int locomokbd_remove(struct locomo_dev *dev) |
| 272 | { | 272 | { |
| 273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); | 273 | struct locomokbd *locomokbd = locomo_get_drvdata(dev); |
| 274 | 274 | ||
| 275 | free_irq(dev->irq[0], locomokbd); | 275 | free_irq(dev->irq[0], locomokbd); |
| 276 | 276 | ||
| 277 | del_timer_sync(&locomokbd->timer); | 277 | del_timer_sync(&locomokbd->timer); |
| 278 | 278 | ||
| 279 | input_unregister_device(&locomokbd->input); | 279 | input_unregister_device(&locomokbd->input); |
| 280 | locomo_set_drvdata(dev, NULL); | 280 | locomo_set_drvdata(dev, NULL); |
| 281 | 281 | ||
diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index 859ed771ee0a..eecbde294f1f 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maple_keyb.c,v 1.4 2004/03/22 01:18:15 lethal Exp $ |
| 3 | * SEGA Dreamcast keyboard driver | 3 | * SEGA Dreamcast keyboard driver |
| 4 | * Based on drivers/usb/usbkbd.c | 4 | * Based on drivers/usb/usbkbd.c |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| @@ -40,7 +40,6 @@ struct dc_kbd { | |||
| 40 | struct input_dev dev; | 40 | struct input_dev dev; |
| 41 | unsigned char new[8]; | 41 | unsigned char new[8]; |
| 42 | unsigned char old[8]; | 42 | unsigned char old[8]; |
| 43 | int open; | ||
| 44 | }; | 43 | }; |
| 45 | 44 | ||
| 46 | 45 | ||
| @@ -95,22 +94,6 @@ static void dc_kbd_callback(struct mapleq *mq) | |||
| 95 | } | 94 | } |
| 96 | } | 95 | } |
| 97 | 96 | ||
| 98 | |||
| 99 | static int dc_kbd_open(struct input_dev *dev) | ||
| 100 | { | ||
| 101 | struct dc_kbd *kbd = dev->private; | ||
| 102 | kbd->open++; | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | |||
| 107 | static void dc_kbd_close(struct input_dev *dev) | ||
| 108 | { | ||
| 109 | struct dc_kbd *kbd = dev->private; | ||
| 110 | kbd->open--; | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 114 | static int dc_kbd_connect(struct maple_device *dev) | 97 | static int dc_kbd_connect(struct maple_device *dev) |
| 115 | { | 98 | { |
| 116 | int i; | 99 | int i; |
| @@ -133,9 +116,6 @@ static int dc_kbd_connect(struct maple_device *dev) | |||
| 133 | clear_bit(0, kbd->dev.keybit); | 116 | clear_bit(0, kbd->dev.keybit); |
| 134 | 117 | ||
| 135 | kbd->dev.private = kbd; | 118 | kbd->dev.private = kbd; |
| 136 | kbd->dev.open = dc_kbd_open; | ||
| 137 | kbd->dev.close = dc_kbd_close; | ||
| 138 | kbd->dev.event = NULL; | ||
| 139 | 119 | ||
| 140 | kbd->dev.name = dev->product_name; | 120 | kbd->dev.name = dev->product_name; |
| 141 | kbd->dev.id.bustype = BUS_MAPLE; | 121 | kbd->dev.id.bustype = BUS_MAPLE; |
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 158c8e845ff9..98710997aaaa 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
| @@ -298,9 +298,11 @@ static int uinput_alloc_device(struct file *file, const char __user *buffer, siz | |||
| 298 | /* check if absmin/absmax/absfuzz/absflat are filled as | 298 | /* check if absmin/absmax/absfuzz/absflat are filled as |
| 299 | * told in Documentation/input/input-programming.txt */ | 299 | * told in Documentation/input/input-programming.txt */ |
| 300 | if (test_bit(EV_ABS, dev->evbit)) { | 300 | if (test_bit(EV_ABS, dev->evbit)) { |
| 301 | retval = uinput_validate_absbits(dev); | 301 | int err = uinput_validate_absbits(dev); |
| 302 | if (retval < 0) | 302 | if (err < 0) { |
| 303 | retval = err; | ||
| 303 | kfree(dev->name); | 304 | kfree(dev->name); |
| 305 | } | ||
| 304 | } | 306 | } |
| 305 | 307 | ||
| 306 | exit: | 308 | exit: |
diff --git a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile index a7864195806a..c4909b49337d 100644 --- a/drivers/input/mouse/Makefile +++ b/drivers/input/mouse/Makefile | |||
| @@ -15,4 +15,4 @@ obj-$(CONFIG_MOUSE_SERIAL) += sermouse.o | |||
| 15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o | 15 | obj-$(CONFIG_MOUSE_HIL) += hil_ptr.o |
| 16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o | 16 | obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o |
| 17 | 17 | ||
| 18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o | 18 | psmouse-objs := psmouse-base.o alps.o logips2pp.o synaptics.o lifebook.o |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7bf4be733e9a..a12e98158a75 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -30,10 +30,11 @@ | |||
| 30 | 30 | ||
| 31 | #define ALPS_DUALPOINT 0x01 | 31 | #define ALPS_DUALPOINT 0x01 |
| 32 | #define ALPS_WHEEL 0x02 | 32 | #define ALPS_WHEEL 0x02 |
| 33 | #define ALPS_FW_BK 0x04 | 33 | #define ALPS_FW_BK_1 0x04 |
| 34 | #define ALPS_4BTN 0x08 | 34 | #define ALPS_4BTN 0x08 |
| 35 | #define ALPS_OLDPROTO 0x10 | 35 | #define ALPS_OLDPROTO 0x10 |
| 36 | #define ALPS_PASS 0x20 | 36 | #define ALPS_PASS 0x20 |
| 37 | #define ALPS_FW_BK_2 0x40 | ||
| 37 | 38 | ||
| 38 | static struct alps_model_info alps_model_data[] = { | 39 | static struct alps_model_info alps_model_data[] = { |
| 39 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ | 40 | { { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */ |
| @@ -43,11 +44,11 @@ static struct alps_model_info alps_model_data[] = { | |||
| 43 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 44 | { { 0x63, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, |
| 44 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, | 45 | { { 0x63, 0x02, 0x28 }, 0xf8, 0xf8, 0 }, |
| 45 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ | 46 | { { 0x63, 0x02, 0x3c }, 0x8f, 0x8f, ALPS_WHEEL }, /* Toshiba Satellite S2400-103 */ |
| 46 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK }, /* NEC Versa L320 */ | 47 | { { 0x63, 0x02, 0x50 }, 0xef, 0xef, ALPS_FW_BK_1 }, /* NEC Versa L320 */ |
| 47 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, | 48 | { { 0x63, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, |
| 48 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ | 49 | { { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS }, /* Dell Latitude D800 */ |
| 49 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, | 50 | { { 0x73, 0x02, 0x0a }, 0xf8, 0xf8, 0 }, |
| 50 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, 0 }, | 51 | { { 0x73, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_FW_BK_2 }, /* Ahtec Laptop */ |
| 51 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ | 52 | { { 0x20, 0x02, 0x0e }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */ |
| 52 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, | 53 | { { 0x22, 0x02, 0x0a }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, |
| 53 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ | 54 | { { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */ |
| @@ -61,11 +62,11 @@ static struct alps_model_info alps_model_data[] = { | |||
| 61 | 62 | ||
| 62 | /* | 63 | /* |
| 63 | * ALPS abolute Mode - new format | 64 | * ALPS abolute Mode - new format |
| 64 | * | 65 | * |
| 65 | * byte 0: 1 ? ? ? 1 ? ? ? | 66 | * byte 0: 1 ? ? ? 1 ? ? ? |
| 66 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 | 67 | * byte 1: 0 x6 x5 x4 x3 x2 x1 x0 |
| 67 | * byte 2: 0 x10 x9 x8 x7 ? fin ges | 68 | * byte 2: 0 x10 x9 x8 x7 ? fin ges |
| 68 | * byte 3: 0 y9 y8 y7 1 M R L | 69 | * byte 3: 0 y9 y8 y7 1 M R L |
| 69 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 | 70 | * byte 4: 0 y6 y5 y4 y3 y2 y1 y0 |
| 70 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 | 71 | * byte 5: 0 z6 z5 z4 z3 z2 z1 z0 |
| 71 | * | 72 | * |
| @@ -81,11 +82,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
| 81 | struct input_dev *dev = &psmouse->dev; | 82 | struct input_dev *dev = &psmouse->dev; |
| 82 | struct input_dev *dev2 = &priv->dev2; | 83 | struct input_dev *dev2 = &priv->dev2; |
| 83 | int x, y, z, ges, fin, left, right, middle; | 84 | int x, y, z, ges, fin, left, right, middle; |
| 85 | int back = 0, forward = 0; | ||
| 84 | 86 | ||
| 85 | input_regs(dev, regs); | 87 | input_regs(dev, regs); |
| 86 | 88 | ||
| 87 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ | 89 | if ((packet[0] & 0xc8) == 0x08) { /* 3-byte PS/2 packet */ |
| 88 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); | 90 | input_report_key(dev2, BTN_LEFT, packet[0] & 1); |
| 89 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); | 91 | input_report_key(dev2, BTN_RIGHT, packet[0] & 2); |
| 90 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); | 92 | input_report_key(dev2, BTN_MIDDLE, packet[0] & 4); |
| 91 | input_report_rel(dev2, REL_X, | 93 | input_report_rel(dev2, REL_X, |
| @@ -112,6 +114,18 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
| 112 | z = packet[5]; | 114 | z = packet[5]; |
| 113 | } | 115 | } |
| 114 | 116 | ||
| 117 | if (priv->i->flags & ALPS_FW_BK_1) { | ||
| 118 | back = packet[2] & 4; | ||
| 119 | forward = packet[0] & 0x10; | ||
| 120 | } | ||
| 121 | |||
| 122 | if (priv->i->flags & ALPS_FW_BK_2) { | ||
| 123 | back = packet[3] & 4; | ||
| 124 | forward = packet[2] & 4; | ||
| 125 | if ((middle = forward && back)) | ||
| 126 | forward = back = 0; | ||
| 127 | } | ||
| 128 | |||
| 115 | ges = packet[2] & 1; | 129 | ges = packet[2] & 1; |
| 116 | fin = packet[2] & 2; | 130 | fin = packet[2] & 2; |
| 117 | 131 | ||
| @@ -155,13 +169,12 @@ static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs) | |||
| 155 | input_report_abs(dev, ABS_PRESSURE, z); | 169 | input_report_abs(dev, ABS_PRESSURE, z); |
| 156 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); | 170 | input_report_key(dev, BTN_TOOL_FINGER, z > 0); |
| 157 | 171 | ||
| 158 | |||
| 159 | if (priv->i->flags & ALPS_WHEEL) | 172 | if (priv->i->flags & ALPS_WHEEL) |
| 160 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); | 173 | input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08)); |
| 161 | 174 | ||
| 162 | if (priv->i->flags & ALPS_FW_BK) { | 175 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
| 163 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x10); | 176 | input_report_key(dev, BTN_FORWARD, forward); |
| 164 | input_report_key(dev, BTN_BACK, packet[2] & 0x04); | 177 | input_report_key(dev, BTN_BACK, back); |
| 165 | } | 178 | } |
| 166 | 179 | ||
| 167 | input_sync(dev); | 180 | input_sync(dev); |
| @@ -257,7 +270,6 @@ static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *vers | |||
| 257 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | 270 | static int alps_passthrough_mode(struct psmouse *psmouse, int enable) |
| 258 | { | 271 | { |
| 259 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 272 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
| 260 | unsigned char param[3]; | ||
| 261 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; | 273 | int cmd = enable ? PSMOUSE_CMD_SETSCALE21 : PSMOUSE_CMD_SETSCALE11; |
| 262 | 274 | ||
| 263 | if (ps2_command(ps2dev, NULL, cmd) || | 275 | if (ps2_command(ps2dev, NULL, cmd) || |
| @@ -267,7 +279,7 @@ static int alps_passthrough_mode(struct psmouse *psmouse, int enable) | |||
| 267 | return -1; | 279 | return -1; |
| 268 | 280 | ||
| 269 | /* we may get 3 more bytes, just ignore them */ | 281 | /* we may get 3 more bytes, just ignore them */ |
| 270 | ps2_command(ps2dev, param, 0x0300); | 282 | ps2_drain(ps2dev, 3, 100); |
| 271 | 283 | ||
| 272 | return 0; | 284 | return 0; |
| 273 | } | 285 | } |
| @@ -425,7 +437,7 @@ int alps_init(struct psmouse *psmouse) | |||
| 425 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); | 437 | psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL); |
| 426 | } | 438 | } |
| 427 | 439 | ||
| 428 | if (priv->i->flags & ALPS_FW_BK) { | 440 | if (priv->i->flags & (ALPS_FW_BK_1 | ALPS_FW_BK_2)) { |
| 429 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); | 441 | psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD); |
| 430 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); | 442 | psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK); |
| 431 | } | 443 | } |
| @@ -436,8 +448,8 @@ int alps_init(struct psmouse *psmouse) | |||
| 436 | priv->dev2.id.bustype = BUS_I8042; | 448 | priv->dev2.id.bustype = BUS_I8042; |
| 437 | priv->dev2.id.vendor = 0x0002; | 449 | priv->dev2.id.vendor = 0x0002; |
| 438 | priv->dev2.id.product = PSMOUSE_ALPS; | 450 | priv->dev2.id.product = PSMOUSE_ALPS; |
| 439 | priv->dev2.id.version = 0x0000; | 451 | priv->dev2.id.version = 0x0000; |
| 440 | 452 | ||
| 441 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 453 | priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
| 442 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); | 454 | priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y); |
| 443 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | 455 | priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); |
| @@ -461,17 +473,15 @@ init_fail: | |||
| 461 | int alps_detect(struct psmouse *psmouse, int set_properties) | 473 | int alps_detect(struct psmouse *psmouse, int set_properties) |
| 462 | { | 474 | { |
| 463 | int version; | 475 | int version; |
| 464 | struct alps_model_info *model; | 476 | struct alps_model_info *model; |
| 465 | 477 | ||
| 466 | if (!(model = alps_get_model(psmouse, &version))) | 478 | if (!(model = alps_get_model(psmouse, &version))) |
| 467 | return -1; | 479 | return -1; |
| 468 | 480 | ||
| 469 | if (set_properties) { | 481 | if (set_properties) { |
| 470 | psmouse->vendor = "ALPS"; | 482 | psmouse->vendor = "ALPS"; |
| 471 | if (model->flags & ALPS_DUALPOINT) | 483 | psmouse->name = model->flags & ALPS_DUALPOINT ? |
| 472 | psmouse->name = "DualPoint TouchPad"; | 484 | "DualPoint TouchPad" : "GlidePoint"; |
| 473 | else | ||
| 474 | psmouse->name = "GlidePoint"; | ||
| 475 | psmouse->model = version; | 485 | psmouse->model = version; |
| 476 | } | 486 | } |
| 477 | return 0; | 487 | return 0; |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index 7baa09cca7c5..e994849efb8f 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
| @@ -33,7 +33,6 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | |||
| 33 | MODULE_DESCRIPTION("Amiga mouse driver"); | 33 | MODULE_DESCRIPTION("Amiga mouse driver"); |
| 34 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
| 35 | 35 | ||
| 36 | static int amimouse_used = 0; | ||
| 37 | static int amimouse_lastx, amimouse_lasty; | 36 | static int amimouse_lastx, amimouse_lasty; |
| 38 | static struct input_dev amimouse_dev; | 37 | static struct input_dev amimouse_dev; |
| 39 | 38 | ||
| @@ -81,16 +80,12 @@ static int amimouse_open(struct input_dev *dev) | |||
| 81 | { | 80 | { |
| 82 | unsigned short joy0dat; | 81 | unsigned short joy0dat; |
| 83 | 82 | ||
| 84 | if (amimouse_used++) | ||
| 85 | return 0; | ||
| 86 | |||
| 87 | joy0dat = custom.joy0dat; | 83 | joy0dat = custom.joy0dat; |
| 88 | 84 | ||
| 89 | amimouse_lastx = joy0dat & 0xff; | 85 | amimouse_lastx = joy0dat & 0xff; |
| 90 | amimouse_lasty = joy0dat >> 8; | 86 | amimouse_lasty = joy0dat >> 8; |
| 91 | 87 | ||
| 92 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { | 88 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { |
| 93 | amimouse_used--; | ||
| 94 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 89 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
| 95 | return -EBUSY; | 90 | return -EBUSY; |
| 96 | } | 91 | } |
| @@ -100,8 +95,7 @@ static int amimouse_open(struct input_dev *dev) | |||
| 100 | 95 | ||
| 101 | static void amimouse_close(struct input_dev *dev) | 96 | static void amimouse_close(struct input_dev *dev) |
| 102 | { | 97 | { |
| 103 | if (!--amimouse_used) | 98 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); |
| 104 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); | ||
| 105 | } | 99 | } |
| 106 | 100 | ||
| 107 | static int __init amimouse_init(void) | 101 | static int __init amimouse_init(void) |
diff --git a/drivers/input/mouse/inport.c b/drivers/input/mouse/inport.c index ca4e96886627..1f62c0134010 100644 --- a/drivers/input/mouse/inport.c +++ b/drivers/input/mouse/inport.c | |||
| @@ -17,18 +17,18 @@ | |||
| 17 | /* | 17 | /* |
| 18 | * This program is free software; you can redistribute it and/or modify | 18 | * This program is free software; you can redistribute it and/or modify |
| 19 | * it under the terms of the GNU General Public License as published by | 19 | * it under the terms of the GNU General Public License as published by |
| 20 | * the Free Software Foundation; either version 2 of the License, or | 20 | * the Free Software Foundation; either version 2 of the License, or |
| 21 | * (at your option) any later version. | 21 | * (at your option) any later version. |
| 22 | * | 22 | * |
| 23 | * This program is distributed in the hope that it will be useful, | 23 | * This program is distributed in the hope that it will be useful, |
| 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 26 | * GNU General Public License for more details. | 26 | * GNU General Public License for more details. |
| 27 | * | 27 | * |
| 28 | * You should have received a copy of the GNU General Public License | 28 | * You should have received a copy of the GNU General Public License |
| 29 | * along with this program; if not, write to the Free Software | 29 | * along with this program; if not, write to the Free Software |
| 30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 31 | * | 31 | * |
| 32 | * Should you need to contact me, the author, you can do so either by | 32 | * Should you need to contact me, the author, you can do so either by |
| 33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 33 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
| 34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 34 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| @@ -87,29 +87,23 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
| 87 | 87 | ||
| 88 | __obsolete_setup("inport_irq="); | 88 | __obsolete_setup("inport_irq="); |
| 89 | 89 | ||
| 90 | static int inport_used; | ||
| 91 | |||
| 92 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 90 | static irqreturn_t inport_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
| 93 | 91 | ||
| 94 | static int inport_open(struct input_dev *dev) | 92 | static int inport_open(struct input_dev *dev) |
| 95 | { | 93 | { |
| 96 | if (!inport_used++) { | 94 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) |
| 97 | if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL)) | 95 | return -EBUSY; |
| 98 | return -EBUSY; | 96 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
| 99 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 97 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); |
| 100 | outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT); | ||
| 101 | } | ||
| 102 | 98 | ||
| 103 | return 0; | 99 | return 0; |
| 104 | } | 100 | } |
| 105 | 101 | ||
| 106 | static void inport_close(struct input_dev *dev) | 102 | static void inport_close(struct input_dev *dev) |
| 107 | { | 103 | { |
| 108 | if (!--inport_used) { | 104 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); |
| 109 | outb(INPORT_REG_MODE, INPORT_CONTROL_PORT); | 105 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); |
| 110 | outb(INPORT_MODE_BASE, INPORT_DATA_PORT); | 106 | free_irq(inport_irq, NULL); |
| 111 | free_irq(inport_irq, NULL); | ||
| 112 | } | ||
| 113 | } | 107 | } |
| 114 | 108 | ||
| 115 | static struct input_dev inport_dev = { | 109 | static struct input_dev inport_dev = { |
| @@ -120,11 +114,11 @@ static struct input_dev inport_dev = { | |||
| 120 | .close = inport_close, | 114 | .close = inport_close, |
| 121 | .name = INPORT_NAME, | 115 | .name = INPORT_NAME, |
| 122 | .phys = "isa023c/input0", | 116 | .phys = "isa023c/input0", |
| 123 | .id = { | 117 | .id = { |
| 124 | .bustype = BUS_ISA, | 118 | .bustype = BUS_ISA, |
| 125 | .vendor = INPORT_VENDOR, | 119 | .vendor = INPORT_VENDOR, |
| 126 | .product = 0x0001, | 120 | .product = 0x0001, |
| 127 | .version = 0x0100, | 121 | .version = 0x0100, |
| 128 | }, | 122 | }, |
| 129 | }; | 123 | }; |
| 130 | 124 | ||
diff --git a/drivers/input/mouse/lifebook.c b/drivers/input/mouse/lifebook.c new file mode 100644 index 000000000000..bd9df9b28325 --- /dev/null +++ b/drivers/input/mouse/lifebook.c | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | /* | ||
| 2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz> | ||
| 5 | * Copyright (c) 2005 Kenan Esau <kenan.esau@conan.de> | ||
| 6 | * | ||
| 7 | * TouchScreen detection, absolute mode setting and packet layout is taken from | ||
| 8 | * Harald Hoyer's description of the device. | ||
| 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 | |||
| 15 | #include <linux/input.h> | ||
| 16 | #include <linux/serio.h> | ||
| 17 | #include <linux/libps2.h> | ||
| 18 | #include <linux/dmi.h> | ||
| 19 | |||
| 20 | #include "psmouse.h" | ||
| 21 | #include "lifebook.h" | ||
| 22 | |||
| 23 | static struct dmi_system_id lifebook_dmi_table[] = { | ||
| 24 | { | ||
| 25 | .ident = "Lifebook B", | ||
| 26 | .matches = { | ||
| 27 | DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"), | ||
| 28 | }, | ||
| 29 | }, | ||
| 30 | { } | ||
| 31 | }; | ||
| 32 | |||
| 33 | |||
| 34 | static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
| 35 | { | ||
| 36 | unsigned char *packet = psmouse->packet; | ||
| 37 | struct input_dev *dev = &psmouse->dev; | ||
| 38 | |||
| 39 | if (psmouse->pktcnt != 3) | ||
| 40 | return PSMOUSE_GOOD_DATA; | ||
| 41 | |||
| 42 | input_regs(dev, regs); | ||
| 43 | |||
| 44 | /* calculate X and Y */ | ||
| 45 | if ((packet[0] & 0x08) == 0x00) { | ||
| 46 | input_report_abs(dev, ABS_X, | ||
| 47 | (packet[1] | ((packet[0] & 0x30) << 4))); | ||
| 48 | input_report_abs(dev, ABS_Y, | ||
| 49 | 1024 - (packet[2] | ((packet[0] & 0xC0) << 2))); | ||
| 50 | } else { | ||
| 51 | input_report_rel(dev, REL_X, | ||
| 52 | ((packet[0] & 0x10) ? packet[1] - 256 : packet[1])); | ||
| 53 | input_report_rel(dev, REL_Y, | ||
| 54 | -(int)((packet[0] & 0x20) ? packet[2] - 256 : packet[2])); | ||
| 55 | } | ||
| 56 | |||
| 57 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | ||
| 58 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | ||
| 59 | input_report_key(dev, BTN_TOUCH, packet[0] & 0x04); | ||
| 60 | |||
| 61 | input_sync(dev); | ||
| 62 | |||
| 63 | return PSMOUSE_FULL_PACKET; | ||
| 64 | } | ||
| 65 | |||
| 66 | static int lifebook_absolute_mode(struct psmouse *psmouse) | ||
| 67 | { | ||
| 68 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
| 69 | unsigned char param; | ||
| 70 | |||
| 71 | if (psmouse_reset(psmouse)) | ||
| 72 | return -1; | ||
| 73 | |||
| 74 | /* | ||
| 75 | Enable absolute output -- ps2_command fails always but if | ||
| 76 | you leave this call out the touchsreen will never send | ||
| 77 | absolute coordinates | ||
| 78 | */ | ||
| 79 | param = 0x07; | ||
| 80 | ps2_command(ps2dev, ¶m, PSMOUSE_CMD_SETRES); | ||
| 81 | |||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | static void lifebook_set_resolution(struct psmouse *psmouse, unsigned int resolution) | ||
| 86 | { | ||
| 87 | unsigned char params[] = { 0, 1, 2, 2, 3 }; | ||
| 88 | |||
| 89 | if (resolution == 0 || resolution > 400) | ||
| 90 | resolution = 400; | ||
| 91 | |||
| 92 | ps2_command(&psmouse->ps2dev, ¶ms[resolution / 100], PSMOUSE_CMD_SETRES); | ||
| 93 | psmouse->resolution = 50 << params[resolution / 100]; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void lifebook_disconnect(struct psmouse *psmouse) | ||
| 97 | { | ||
| 98 | psmouse_reset(psmouse); | ||
| 99 | } | ||
| 100 | |||
| 101 | int lifebook_detect(struct psmouse *psmouse, int set_properties) | ||
| 102 | { | ||
| 103 | if (!dmi_check_system(lifebook_dmi_table)) | ||
| 104 | return -1; | ||
| 105 | |||
| 106 | if (set_properties) { | ||
| 107 | psmouse->vendor = "Fujitsu"; | ||
| 108 | psmouse->name = "Lifebook TouchScreen"; | ||
| 109 | } | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | int lifebook_init(struct psmouse *psmouse) | ||
| 115 | { | ||
| 116 | if (lifebook_absolute_mode(psmouse)) | ||
| 117 | return -1; | ||
| 118 | |||
| 119 | psmouse->dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY) | BIT(EV_REL); | ||
| 120 | psmouse->dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
| 121 | psmouse->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
| 122 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
| 123 | input_set_abs_params(&psmouse->dev, ABS_X, 0, 1024, 0, 0); | ||
| 124 | input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1024, 0, 0); | ||
| 125 | |||
| 126 | psmouse->protocol_handler = lifebook_process_byte; | ||
| 127 | psmouse->set_resolution = lifebook_set_resolution; | ||
| 128 | psmouse->disconnect = lifebook_disconnect; | ||
| 129 | psmouse->reconnect = lifebook_absolute_mode; | ||
| 130 | psmouse->pktsize = 3; | ||
| 131 | |||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | |||
diff --git a/drivers/input/mouse/lifebook.h b/drivers/input/mouse/lifebook.h new file mode 100644 index 000000000000..be1c0943825d --- /dev/null +++ b/drivers/input/mouse/lifebook.h | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | /* | ||
| 2 | * Fujitsu B-series Lifebook PS/2 TouchScreen driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Vojtech Pavlik | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License version 2 as published by | ||
| 8 | * the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #ifndef _LIFEBOOK_H | ||
| 12 | #define _LIFEBOOK_H | ||
| 13 | |||
| 14 | int lifebook_detect(struct psmouse *psmouse, int set_properties); | ||
| 15 | int lifebook_init(struct psmouse *psmouse); | ||
| 16 | |||
| 17 | #endif | ||
diff --git a/drivers/input/mouse/logibm.c b/drivers/input/mouse/logibm.c index 77eb83e87f61..8b5243167227 100644 --- a/drivers/input/mouse/logibm.c +++ b/drivers/input/mouse/logibm.c | |||
| @@ -18,18 +18,18 @@ | |||
| 18 | /* | 18 | /* |
| 19 | * This program is free software; you can redistribute it and/or modify | 19 | * This program is free software; you can redistribute it and/or modify |
| 20 | * it under the terms of the GNU General Public License as published by | 20 | * it under the terms of the GNU General Public License as published by |
| 21 | * the Free Software Foundation; either version 2 of the License, or | 21 | * the Free Software Foundation; either version 2 of the License, or |
| 22 | * (at your option) any later version. | 22 | * (at your option) any later version. |
| 23 | * | 23 | * |
| 24 | * This program is distributed in the hope that it will be useful, | 24 | * This program is distributed in the hope that it will be useful, |
| 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 27 | * GNU General Public License for more details. | 27 | * GNU General Public License for more details. |
| 28 | * | 28 | * |
| 29 | * You should have received a copy of the GNU General Public License | 29 | * You should have received a copy of the GNU General Public License |
| 30 | * along with this program; if not, write to the Free Software | 30 | * along with this program; if not, write to the Free Software |
| 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 32 | * | 32 | * |
| 33 | * Should you need to contact me, the author, you can do so either by | 33 | * Should you need to contact me, the author, you can do so either by |
| 34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 34 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
| 35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 35 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| @@ -77,16 +77,11 @@ MODULE_PARM_DESC(irq, "IRQ number (5=default)"); | |||
| 77 | 77 | ||
| 78 | __obsolete_setup("logibm_irq="); | 78 | __obsolete_setup("logibm_irq="); |
| 79 | 79 | ||
| 80 | static int logibm_used = 0; | ||
| 81 | |||
| 82 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 80 | static irqreturn_t logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs); |
| 83 | 81 | ||
| 84 | static int logibm_open(struct input_dev *dev) | 82 | static int logibm_open(struct input_dev *dev) |
| 85 | { | 83 | { |
| 86 | if (logibm_used++) | ||
| 87 | return 0; | ||
| 88 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { | 84 | if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) { |
| 89 | logibm_used--; | ||
| 90 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); | 85 | printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq); |
| 91 | return -EBUSY; | 86 | return -EBUSY; |
| 92 | } | 87 | } |
| @@ -96,8 +91,6 @@ static int logibm_open(struct input_dev *dev) | |||
| 96 | 91 | ||
| 97 | static void logibm_close(struct input_dev *dev) | 92 | static void logibm_close(struct input_dev *dev) |
| 98 | { | 93 | { |
| 99 | if (--logibm_used) | ||
| 100 | return; | ||
| 101 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 94 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
| 102 | free_irq(logibm_irq, NULL); | 95 | free_irq(logibm_irq, NULL); |
| 103 | } | 96 | } |
| @@ -167,7 +160,7 @@ static int __init logibm_init(void) | |||
| 167 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); | 160 | outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT); |
| 168 | 161 | ||
| 169 | input_register_device(&logibm_dev); | 162 | input_register_device(&logibm_dev); |
| 170 | 163 | ||
| 171 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); | 164 | printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq); |
| 172 | 165 | ||
| 173 | return 0; | 166 | return 0; |
diff --git a/drivers/input/mouse/maplemouse.c b/drivers/input/mouse/maplemouse.c index 12dc0ef5020f..e90c60cbbf05 100644 --- a/drivers/input/mouse/maplemouse.c +++ b/drivers/input/mouse/maplemouse.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ | 2 | * $Id: maplemouse.c,v 1.2 2004/03/22 01:18:15 lethal Exp $ |
| 3 | * SEGA Dreamcast mouse driver | 3 | * SEGA Dreamcast mouse driver |
| 4 | * Based on drivers/usb/usbmouse.c | 4 | * Based on drivers/usb/usbmouse.c |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| @@ -15,80 +15,51 @@ | |||
| 15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); | 15 | MODULE_AUTHOR("YAEGASHI Takeshi <t@keshi.org>"); |
| 16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); | 16 | MODULE_DESCRIPTION("SEGA Dreamcast mouse driver"); |
| 17 | 17 | ||
| 18 | struct dc_mouse { | ||
| 19 | struct input_dev dev; | ||
| 20 | int open; | ||
| 21 | }; | ||
| 22 | |||
| 23 | |||
| 24 | static void dc_mouse_callback(struct mapleq *mq) | 18 | static void dc_mouse_callback(struct mapleq *mq) |
| 25 | { | 19 | { |
| 26 | int buttons, relx, rely, relz; | 20 | int buttons, relx, rely, relz; |
| 27 | struct maple_device *mapledev = mq->dev; | 21 | struct maple_device *mapledev = mq->dev; |
| 28 | struct dc_mouse *mouse = mapledev->private_data; | 22 | struct input_dev *dev = mapledev->private_data; |
| 29 | struct input_dev *dev = &mouse->dev; | ||
| 30 | unsigned char *res = mq->recvbuf; | 23 | unsigned char *res = mq->recvbuf; |
| 31 | 24 | ||
| 32 | buttons = ~res[8]; | 25 | buttons = ~res[8]; |
| 33 | relx=*(unsigned short *)(res+12)-512; | 26 | relx = *(unsigned short *)(res + 12) - 512; |
| 34 | rely=*(unsigned short *)(res+14)-512; | 27 | rely = *(unsigned short *)(res + 14) - 512; |
| 35 | relz=*(unsigned short *)(res+16)-512; | 28 | relz = *(unsigned short *)(res + 16) - 512; |
| 36 | 29 | ||
| 37 | input_report_key(dev, BTN_LEFT, buttons&4); | 30 | input_report_key(dev, BTN_LEFT, buttons & 4); |
| 38 | input_report_key(dev, BTN_MIDDLE, buttons&9); | 31 | input_report_key(dev, BTN_MIDDLE, buttons & 9); |
| 39 | input_report_key(dev, BTN_RIGHT, buttons&2); | 32 | input_report_key(dev, BTN_RIGHT, buttons & 2); |
| 40 | input_report_rel(dev, REL_X, relx); | 33 | input_report_rel(dev, REL_X, relx); |
| 41 | input_report_rel(dev, REL_Y, rely); | 34 | input_report_rel(dev, REL_Y, rely); |
| 42 | input_report_rel(dev, REL_WHEEL, relz); | 35 | input_report_rel(dev, REL_WHEEL, relz); |
| 43 | input_sync(dev); | 36 | input_sync(dev); |
| 44 | } | 37 | } |
| 45 | 38 | ||
| 46 | |||
| 47 | static int dc_mouse_open(struct input_dev *dev) | ||
| 48 | { | ||
| 49 | struct dc_mouse *mouse = dev->private; | ||
| 50 | mouse->open++; | ||
| 51 | return 0; | ||
| 52 | } | ||
| 53 | |||
| 54 | |||
| 55 | static void dc_mouse_close(struct input_dev *dev) | ||
| 56 | { | ||
| 57 | struct dc_mouse *mouse = dev->private; | ||
| 58 | mouse->open--; | ||
| 59 | } | ||
| 60 | |||
| 61 | |||
| 62 | static int dc_mouse_connect(struct maple_device *dev) | 39 | static int dc_mouse_connect(struct maple_device *dev) |
| 63 | { | 40 | { |
| 64 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); | 41 | unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]); |
| 65 | struct dc_mouse *mouse; | 42 | struct input_dev *input_dev; |
| 66 | 43 | ||
| 67 | if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL))) | 44 | if (!(input_dev = kmalloc(sizeof(struct input_dev), GFP_KERNEL))) |
| 68 | return -1; | 45 | return -1; |
| 69 | memset(mouse, 0, sizeof(struct dc_mouse)); | ||
| 70 | |||
| 71 | dev->private_data = mouse; | ||
| 72 | 46 | ||
| 73 | mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 47 | dev->private_data = input_dev; |
| 74 | mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
| 75 | mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
| 76 | 48 | ||
| 77 | init_input_dev(&mouse->dev); | 49 | memset(input_dev, 0, sizeof(struct dc_mouse)); |
| 50 | init_input_dev(input_dev); | ||
| 51 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
| 52 | input_dev->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | ||
| 53 | input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL); | ||
| 78 | 54 | ||
| 79 | mouse->dev.private = mouse; | 55 | input_dev->name = dev->product_name; |
| 80 | mouse->dev.open = dc_mouse_open; | 56 | input_dev->id.bustype = BUS_MAPLE; |
| 81 | mouse->dev.close = dc_mouse_close; | ||
| 82 | mouse->dev.event = NULL; | ||
| 83 | 57 | ||
| 84 | mouse->dev.name = dev->product_name; | 58 | input_register_device(input_dev); |
| 85 | mouse->dev.id.bustype = BUS_MAPLE; | ||
| 86 | |||
| 87 | input_register_device(&mouse->dev); | ||
| 88 | 59 | ||
| 89 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); | 60 | maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE); |
| 90 | 61 | ||
| 91 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, mouse->dev.name); | 62 | printk(KERN_INFO "input: mouse(0x%lx): %s\n", data, input_dev->name); |
| 92 | 63 | ||
| 93 | return 0; | 64 | return 0; |
| 94 | } | 65 | } |
| @@ -96,10 +67,10 @@ static int dc_mouse_connect(struct maple_device *dev) | |||
| 96 | 67 | ||
| 97 | static void dc_mouse_disconnect(struct maple_device *dev) | 68 | static void dc_mouse_disconnect(struct maple_device *dev) |
| 98 | { | 69 | { |
| 99 | struct dc_mouse *mouse = dev->private_data; | 70 | struct input_dev *input_dev = dev->private_data; |
| 100 | 71 | ||
| 101 | input_unregister_device(&mouse->dev); | 72 | input_unregister_device(input_dev); |
| 102 | kfree(mouse); | 73 | kfree(input_dev); |
| 103 | } | 74 | } |
| 104 | 75 | ||
| 105 | 76 | ||
diff --git a/drivers/input/mouse/pc110pad.c b/drivers/input/mouse/pc110pad.c index 0c74918fe254..93393d5c0078 100644 --- a/drivers/input/mouse/pc110pad.c +++ b/drivers/input/mouse/pc110pad.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | * Copyright (c) 2000-2001 Vojtech Pavlik | 4 | * Copyright (c) 2000-2001 Vojtech Pavlik |
| 5 | * | 5 | * |
| 6 | * Based on the work of: | 6 | * Based on the work of: |
| 7 | * Alan Cox Robin O'Leary | 7 | * Alan Cox Robin O'Leary |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | /* | 10 | /* |
| @@ -56,7 +56,6 @@ static int pc110pad_io = 0x15e0; | |||
| 56 | static struct input_dev pc110pad_dev; | 56 | static struct input_dev pc110pad_dev; |
| 57 | static int pc110pad_data[3]; | 57 | static int pc110pad_data[3]; |
| 58 | static int pc110pad_count; | 58 | static int pc110pad_count; |
| 59 | static int pc110pad_used; | ||
| 60 | 59 | ||
| 61 | static char *pc110pad_name = "IBM PC110 TouchPad"; | 60 | static char *pc110pad_name = "IBM PC110 TouchPad"; |
| 62 | static char *pc110pad_phys = "isa15e0/input0"; | 61 | static char *pc110pad_phys = "isa15e0/input0"; |
| @@ -74,7 +73,7 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
| 74 | 73 | ||
| 75 | if (pc110pad_count < 3) | 74 | if (pc110pad_count < 3) |
| 76 | return IRQ_HANDLED; | 75 | return IRQ_HANDLED; |
| 77 | 76 | ||
| 78 | input_regs(&pc110pad_dev, regs); | 77 | input_regs(&pc110pad_dev, regs); |
| 79 | input_report_key(&pc110pad_dev, BTN_TOUCH, | 78 | input_report_key(&pc110pad_dev, BTN_TOUCH, |
| 80 | pc110pad_data[0] & 0x01); | 79 | pc110pad_data[0] & 0x01); |
| @@ -90,15 +89,11 @@ static irqreturn_t pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs) | |||
| 90 | 89 | ||
| 91 | static void pc110pad_close(struct input_dev *dev) | 90 | static void pc110pad_close(struct input_dev *dev) |
| 92 | { | 91 | { |
| 93 | if (!--pc110pad_used) | 92 | outb(PC110PAD_OFF, pc110pad_io + 2); |
| 94 | outb(PC110PAD_OFF, pc110pad_io + 2); | ||
| 95 | } | 93 | } |
| 96 | 94 | ||
| 97 | static int pc110pad_open(struct input_dev *dev) | 95 | static int pc110pad_open(struct input_dev *dev) |
| 98 | { | 96 | { |
| 99 | if (pc110pad_used++) | ||
| 100 | return 0; | ||
| 101 | |||
| 102 | pc110pad_interrupt(0,NULL,NULL); | 97 | pc110pad_interrupt(0,NULL,NULL); |
| 103 | pc110pad_interrupt(0,NULL,NULL); | 98 | pc110pad_interrupt(0,NULL,NULL); |
| 104 | pc110pad_interrupt(0,NULL,NULL); | 99 | pc110pad_interrupt(0,NULL,NULL); |
| @@ -145,7 +140,7 @@ static int __init pc110pad_init(void) | |||
| 145 | 140 | ||
| 146 | pc110pad_dev.absmax[ABS_X] = 0x1ff; | 141 | pc110pad_dev.absmax[ABS_X] = 0x1ff; |
| 147 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; | 142 | pc110pad_dev.absmax[ABS_Y] = 0x0ff; |
| 148 | 143 | ||
| 149 | pc110pad_dev.open = pc110pad_open; | 144 | pc110pad_dev.open = pc110pad_open; |
| 150 | pc110pad_dev.close = pc110pad_close; | 145 | pc110pad_dev.close = pc110pad_close; |
| 151 | 146 | ||
| @@ -156,17 +151,17 @@ static int __init pc110pad_init(void) | |||
| 156 | pc110pad_dev.id.product = 0x0001; | 151 | pc110pad_dev.id.product = 0x0001; |
| 157 | pc110pad_dev.id.version = 0x0100; | 152 | pc110pad_dev.id.version = 0x0100; |
| 158 | 153 | ||
| 159 | input_register_device(&pc110pad_dev); | 154 | input_register_device(&pc110pad_dev); |
| 160 | 155 | ||
| 161 | printk(KERN_INFO "input: %s at %#x irq %d\n", | 156 | printk(KERN_INFO "input: %s at %#x irq %d\n", |
| 162 | pc110pad_name, pc110pad_io, pc110pad_irq); | 157 | pc110pad_name, pc110pad_io, pc110pad_irq); |
| 163 | 158 | ||
| 164 | return 0; | 159 | return 0; |
| 165 | } | 160 | } |
| 166 | 161 | ||
| 167 | static void __exit pc110pad_exit(void) | 162 | static void __exit pc110pad_exit(void) |
| 168 | { | 163 | { |
| 169 | input_unregister_device(&pc110pad_dev); | 164 | input_unregister_device(&pc110pad_dev); |
| 170 | 165 | ||
| 171 | outb(PC110PAD_OFF, pc110pad_io + 2); | 166 | outb(PC110PAD_OFF, pc110pad_io + 2); |
| 172 | 167 | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 019034b21a0b..19785a6c5abd 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "synaptics.h" | 24 | #include "synaptics.h" |
| 25 | #include "logips2pp.h" | 25 | #include "logips2pp.h" |
| 26 | #include "alps.h" | 26 | #include "alps.h" |
| 27 | #include "lifebook.h" | ||
| 27 | 28 | ||
| 28 | #define DRIVER_DESC "PS/2 mouse driver" | 29 | #define DRIVER_DESC "PS/2 mouse driver" |
| 29 | 30 | ||
| @@ -31,10 +32,9 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@suse.cz>"); | |||
| 31 | MODULE_DESCRIPTION(DRIVER_DESC); | 32 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 33 | 34 | ||
| 34 | static unsigned int psmouse_max_proto = -1U; | 35 | static unsigned int psmouse_max_proto = PSMOUSE_AUTO; |
| 35 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); | 36 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp); |
| 36 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); | 37 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp); |
| 37 | static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL }; | ||
| 38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) | 38 | #define param_check_proto_abbrev(name, p) __param_check(name, p, unsigned int) |
| 39 | #define param_set_proto_abbrev psmouse_set_maxproto | 39 | #define param_set_proto_abbrev psmouse_set_maxproto |
| 40 | #define param_get_proto_abbrev psmouse_get_maxproto | 40 | #define param_get_proto_abbrev psmouse_get_maxproto |
| @@ -57,6 +57,7 @@ static unsigned int psmouse_resetafter; | |||
| 57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 57 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
| 58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 58 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
| 59 | 59 | ||
| 60 | PSMOUSE_DEFINE_ATTR(protocol); | ||
| 60 | PSMOUSE_DEFINE_ATTR(rate); | 61 | PSMOUSE_DEFINE_ATTR(rate); |
| 61 | PSMOUSE_DEFINE_ATTR(resolution); | 62 | PSMOUSE_DEFINE_ATTR(resolution); |
| 62 | PSMOUSE_DEFINE_ATTR(resetafter); | 63 | PSMOUSE_DEFINE_ATTR(resetafter); |
| @@ -67,7 +68,23 @@ __obsolete_setup("psmouse_smartscroll="); | |||
| 67 | __obsolete_setup("psmouse_resetafter="); | 68 | __obsolete_setup("psmouse_resetafter="); |
| 68 | __obsolete_setup("psmouse_rate="); | 69 | __obsolete_setup("psmouse_rate="); |
| 69 | 70 | ||
| 70 | static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "ThinkPS/2", "GenPS/2", "ImPS/2", "ImExPS/2", "SynPS/2", "AlpsPS/2" }; | 71 | /* |
| 72 | * psmouse_sem protects all operations changing state of mouse | ||
| 73 | * (connecting, disconnecting, changing rate or resolution via | ||
| 74 | * sysfs). We could use a per-device semaphore but since there | ||
| 75 | * rarely more than one PS/2 mouse connected and since semaphore | ||
| 76 | * is taken in "slow" paths it is not worth it. | ||
| 77 | */ | ||
| 78 | static DECLARE_MUTEX(psmouse_sem); | ||
| 79 | |||
| 80 | struct psmouse_protocol { | ||
| 81 | enum psmouse_type type; | ||
| 82 | char *name; | ||
| 83 | char *alias; | ||
| 84 | int maxproto; | ||
| 85 | int (*detect)(struct psmouse *, int); | ||
| 86 | int (*init)(struct psmouse *); | ||
| 87 | }; | ||
| 71 | 88 | ||
| 72 | /* | 89 | /* |
| 73 | * psmouse_process_byte() analyzes the PS/2 data stream and reports | 90 | * psmouse_process_byte() analyzes the PS/2 data stream and reports |
| @@ -407,12 +424,15 @@ static int thinking_detect(struct psmouse *psmouse, int set_properties) | |||
| 407 | */ | 424 | */ |
| 408 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) | 425 | static int ps2bare_detect(struct psmouse *psmouse, int set_properties) |
| 409 | { | 426 | { |
| 410 | if (!psmouse->vendor) psmouse->vendor = "Generic"; | 427 | if (set_properties) { |
| 411 | if (!psmouse->name) psmouse->name = "Mouse"; | 428 | if (!psmouse->vendor) psmouse->vendor = "Generic"; |
| 429 | if (!psmouse->name) psmouse->name = "Mouse"; | ||
| 430 | } | ||
| 412 | 431 | ||
| 413 | return 0; | 432 | return 0; |
| 414 | } | 433 | } |
| 415 | 434 | ||
| 435 | |||
| 416 | /* | 436 | /* |
| 417 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol | 437 | * psmouse_extensions() probes for any extensions to the basic PS/2 protocol |
| 418 | * the mouse may have. | 438 | * the mouse may have. |
| @@ -424,6 +444,17 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 424 | int synaptics_hardware = 0; | 444 | int synaptics_hardware = 0; |
| 425 | 445 | ||
| 426 | /* | 446 | /* |
| 447 | * We always check for lifebook because it does not disturb mouse | ||
| 448 | * (it only checks DMI information). | ||
| 449 | */ | ||
| 450 | if (lifebook_detect(psmouse, set_properties) == 0) { | ||
| 451 | if (max_proto > PSMOUSE_IMEX) { | ||
| 452 | if (!set_properties || lifebook_init(psmouse) == 0) | ||
| 453 | return PSMOUSE_LIFEBOOK; | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | /* | ||
| 427 | * Try Kensington ThinkingMouse (we try first, because synaptics probe | 458 | * Try Kensington ThinkingMouse (we try first, because synaptics probe |
| 428 | * upsets the thinkingmouse). | 459 | * upsets the thinkingmouse). |
| 429 | */ | 460 | */ |
| @@ -506,6 +537,103 @@ static int psmouse_extensions(struct psmouse *psmouse, | |||
| 506 | return PSMOUSE_PS2; | 537 | return PSMOUSE_PS2; |
| 507 | } | 538 | } |
| 508 | 539 | ||
| 540 | static struct psmouse_protocol psmouse_protocols[] = { | ||
| 541 | { | ||
| 542 | .type = PSMOUSE_PS2, | ||
| 543 | .name = "PS/2", | ||
| 544 | .alias = "bare", | ||
| 545 | .maxproto = 1, | ||
| 546 | .detect = ps2bare_detect, | ||
| 547 | }, | ||
| 548 | { | ||
| 549 | .type = PSMOUSE_PS2PP, | ||
| 550 | .name = "PS2++", | ||
| 551 | .alias = "logitech", | ||
| 552 | .detect = ps2pp_init, | ||
| 553 | }, | ||
| 554 | { | ||
| 555 | .type = PSMOUSE_THINKPS, | ||
| 556 | .name = "ThinkPS/2", | ||
| 557 | .alias = "thinkps", | ||
| 558 | .detect = thinking_detect, | ||
| 559 | }, | ||
| 560 | { | ||
| 561 | .type = PSMOUSE_GENPS, | ||
| 562 | .name = "GenPS/2", | ||
| 563 | .alias = "genius", | ||
| 564 | .detect = genius_detect, | ||
| 565 | }, | ||
| 566 | { | ||
| 567 | .type = PSMOUSE_IMPS, | ||
| 568 | .name = "ImPS/2", | ||
| 569 | .alias = "imps", | ||
| 570 | .maxproto = 1, | ||
| 571 | .detect = intellimouse_detect, | ||
| 572 | }, | ||
| 573 | { | ||
| 574 | .type = PSMOUSE_IMEX, | ||
| 575 | .name = "ImExPS/2", | ||
| 576 | .alias = "exps", | ||
| 577 | .maxproto = 1, | ||
| 578 | .detect = im_explorer_detect, | ||
| 579 | }, | ||
| 580 | { | ||
| 581 | .type = PSMOUSE_SYNAPTICS, | ||
| 582 | .name = "SynPS/2", | ||
| 583 | .alias = "synaptics", | ||
| 584 | .detect = synaptics_detect, | ||
| 585 | .init = synaptics_init, | ||
| 586 | }, | ||
| 587 | { | ||
| 588 | .type = PSMOUSE_ALPS, | ||
| 589 | .name = "AlpsPS/2", | ||
| 590 | .alias = "alps", | ||
| 591 | .detect = alps_detect, | ||
| 592 | .init = alps_init, | ||
| 593 | }, | ||
| 594 | { | ||
| 595 | .type = PSMOUSE_LIFEBOOK, | ||
| 596 | .name = "LBPS/2", | ||
| 597 | .alias = "lifebook", | ||
| 598 | .init = lifebook_init, | ||
| 599 | }, | ||
| 600 | { | ||
| 601 | .type = PSMOUSE_AUTO, | ||
| 602 | .name = "auto", | ||
| 603 | .alias = "any", | ||
| 604 | .maxproto = 1, | ||
| 605 | }, | ||
| 606 | }; | ||
| 607 | |||
| 608 | static struct psmouse_protocol *psmouse_protocol_by_type(enum psmouse_type type) | ||
| 609 | { | ||
| 610 | int i; | ||
| 611 | |||
| 612 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) | ||
| 613 | if (psmouse_protocols[i].type == type) | ||
| 614 | return &psmouse_protocols[i]; | ||
| 615 | |||
| 616 | WARN_ON(1); | ||
| 617 | return &psmouse_protocols[0]; | ||
| 618 | } | ||
| 619 | |||
| 620 | static struct psmouse_protocol *psmouse_protocol_by_name(const char *name, size_t len) | ||
| 621 | { | ||
| 622 | struct psmouse_protocol *p; | ||
| 623 | int i; | ||
| 624 | |||
| 625 | for (i = 0; i < ARRAY_SIZE(psmouse_protocols); i++) { | ||
| 626 | p = &psmouse_protocols[i]; | ||
| 627 | |||
| 628 | if ((strlen(p->name) == len && !strncmp(p->name, name, len)) || | ||
| 629 | (strlen(p->alias) == len && !strncmp(p->alias, name, len))) | ||
| 630 | return &psmouse_protocols[i]; | ||
| 631 | } | ||
| 632 | |||
| 633 | return NULL; | ||
| 634 | } | ||
| 635 | |||
| 636 | |||
| 509 | /* | 637 | /* |
| 510 | * psmouse_probe() probes for a PS/2 mouse. | 638 | * psmouse_probe() probes for a PS/2 mouse. |
| 511 | */ | 639 | */ |
| @@ -653,30 +781,84 @@ static void psmouse_cleanup(struct serio *serio) | |||
| 653 | 781 | ||
| 654 | static void psmouse_disconnect(struct serio *serio) | 782 | static void psmouse_disconnect(struct serio *serio) |
| 655 | { | 783 | { |
| 656 | struct psmouse *psmouse, *parent; | 784 | struct psmouse *psmouse, *parent = NULL; |
| 657 | 785 | ||
| 786 | psmouse = serio_get_drvdata(serio); | ||
| 787 | |||
| 788 | device_remove_file(&serio->dev, &psmouse_attr_protocol); | ||
| 658 | device_remove_file(&serio->dev, &psmouse_attr_rate); | 789 | device_remove_file(&serio->dev, &psmouse_attr_rate); |
| 659 | device_remove_file(&serio->dev, &psmouse_attr_resolution); | 790 | device_remove_file(&serio->dev, &psmouse_attr_resolution); |
| 660 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); | 791 | device_remove_file(&serio->dev, &psmouse_attr_resetafter); |
| 661 | 792 | ||
| 662 | psmouse = serio_get_drvdata(serio); | 793 | down(&psmouse_sem); |
| 794 | |||
| 663 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 795 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| 664 | 796 | ||
| 665 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 797 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
| 666 | parent = serio_get_drvdata(serio->parent); | 798 | parent = serio_get_drvdata(serio->parent); |
| 667 | if (parent->pt_deactivate) | 799 | psmouse_deactivate(parent); |
| 668 | parent->pt_deactivate(parent); | ||
| 669 | } | 800 | } |
| 670 | 801 | ||
| 671 | if (psmouse->disconnect) | 802 | if (psmouse->disconnect) |
| 672 | psmouse->disconnect(psmouse); | 803 | psmouse->disconnect(psmouse); |
| 673 | 804 | ||
| 805 | if (parent && parent->pt_deactivate) | ||
| 806 | parent->pt_deactivate(parent); | ||
| 807 | |||
| 674 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | 808 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
| 675 | 809 | ||
| 676 | input_unregister_device(&psmouse->dev); | 810 | input_unregister_device(&psmouse->dev); |
| 677 | serio_close(serio); | 811 | serio_close(serio); |
| 678 | serio_set_drvdata(serio, NULL); | 812 | serio_set_drvdata(serio, NULL); |
| 679 | kfree(psmouse); | 813 | kfree(psmouse); |
| 814 | |||
| 815 | if (parent) | ||
| 816 | psmouse_activate(parent); | ||
| 817 | |||
| 818 | up(&psmouse_sem); | ||
| 819 | } | ||
| 820 | |||
| 821 | static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_protocol *proto) | ||
| 822 | { | ||
| 823 | memset(&psmouse->dev, 0, sizeof(struct input_dev)); | ||
| 824 | |||
| 825 | init_input_dev(&psmouse->dev); | ||
| 826 | |||
| 827 | psmouse->dev.private = psmouse; | ||
| 828 | psmouse->dev.dev = &psmouse->ps2dev.serio->dev; | ||
| 829 | |||
| 830 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | ||
| 831 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
| 832 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
| 833 | |||
| 834 | psmouse->set_rate = psmouse_set_rate; | ||
| 835 | psmouse->set_resolution = psmouse_set_resolution; | ||
| 836 | psmouse->protocol_handler = psmouse_process_byte; | ||
| 837 | psmouse->pktsize = 3; | ||
| 838 | |||
| 839 | if (proto && (proto->detect || proto->init)) { | ||
| 840 | if (proto->detect && proto->detect(psmouse, 1) < 0) | ||
| 841 | return -1; | ||
| 842 | |||
| 843 | if (proto->init && proto->init(psmouse) < 0) | ||
| 844 | return -1; | ||
| 845 | |||
| 846 | psmouse->type = proto->type; | ||
| 847 | } | ||
| 848 | else | ||
| 849 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | ||
| 850 | |||
| 851 | sprintf(psmouse->devname, "%s %s %s", | ||
| 852 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | ||
| 853 | |||
| 854 | psmouse->dev.name = psmouse->devname; | ||
| 855 | psmouse->dev.phys = psmouse->phys; | ||
| 856 | psmouse->dev.id.bustype = BUS_I8042; | ||
| 857 | psmouse->dev.id.vendor = 0x0002; | ||
| 858 | psmouse->dev.id.product = psmouse->type; | ||
| 859 | psmouse->dev.id.version = psmouse->model; | ||
| 860 | |||
| 861 | return 0; | ||
| 680 | } | 862 | } |
| 681 | 863 | ||
| 682 | /* | 864 | /* |
| @@ -688,6 +870,8 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 688 | struct psmouse *psmouse, *parent = NULL; | 870 | struct psmouse *psmouse, *parent = NULL; |
| 689 | int retval; | 871 | int retval; |
| 690 | 872 | ||
| 873 | down(&psmouse_sem); | ||
| 874 | |||
| 691 | /* | 875 | /* |
| 692 | * If this is a pass-through port deactivate parent so the device | 876 | * If this is a pass-through port deactivate parent so the device |
| 693 | * connected to this port can be successfully identified | 877 | * connected to this port can be successfully identified |
| @@ -697,20 +881,14 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 697 | psmouse_deactivate(parent); | 881 | psmouse_deactivate(parent); |
| 698 | } | 882 | } |
| 699 | 883 | ||
| 700 | if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) { | 884 | if (!(psmouse = kcalloc(1, sizeof(struct psmouse), GFP_KERNEL))) { |
| 701 | retval = -ENOMEM; | 885 | retval = -ENOMEM; |
| 702 | goto out; | 886 | goto out; |
| 703 | } | 887 | } |
| 704 | 888 | ||
| 705 | memset(psmouse, 0, sizeof(struct psmouse)); | ||
| 706 | |||
| 707 | ps2_init(&psmouse->ps2dev, serio); | 889 | ps2_init(&psmouse->ps2dev, serio); |
| 708 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 890 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
| 709 | psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 891 | |
| 710 | psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); | ||
| 711 | psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); | ||
| 712 | psmouse->dev.private = psmouse; | ||
| 713 | psmouse->dev.dev = &serio->dev; | ||
| 714 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | 892 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); |
| 715 | 893 | ||
| 716 | serio_set_drvdata(serio, psmouse); | 894 | serio_set_drvdata(serio, psmouse); |
| @@ -734,25 +912,10 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 734 | psmouse->resolution = psmouse_resolution; | 912 | psmouse->resolution = psmouse_resolution; |
| 735 | psmouse->resetafter = psmouse_resetafter; | 913 | psmouse->resetafter = psmouse_resetafter; |
| 736 | psmouse->smartscroll = psmouse_smartscroll; | 914 | psmouse->smartscroll = psmouse_smartscroll; |
| 737 | psmouse->set_rate = psmouse_set_rate; | ||
| 738 | psmouse->set_resolution = psmouse_set_resolution; | ||
| 739 | psmouse->protocol_handler = psmouse_process_byte; | ||
| 740 | psmouse->pktsize = 3; | ||
| 741 | 915 | ||
| 742 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 916 | psmouse_switch_protocol(psmouse, NULL); |
| 743 | |||
| 744 | sprintf(psmouse->devname, "%s %s %s", | ||
| 745 | psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name); | ||
| 746 | |||
| 747 | psmouse->dev.name = psmouse->devname; | ||
| 748 | psmouse->dev.phys = psmouse->phys; | ||
| 749 | psmouse->dev.id.bustype = BUS_I8042; | ||
| 750 | psmouse->dev.id.vendor = 0x0002; | ||
| 751 | psmouse->dev.id.product = psmouse->type; | ||
| 752 | psmouse->dev.id.version = psmouse->model; | ||
| 753 | 917 | ||
| 754 | input_register_device(&psmouse->dev); | 918 | input_register_device(&psmouse->dev); |
| 755 | |||
| 756 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | 919 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); |
| 757 | 920 | ||
| 758 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 921 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
| @@ -762,6 +925,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 762 | if (parent && parent->pt_activate) | 925 | if (parent && parent->pt_activate) |
| 763 | parent->pt_activate(parent); | 926 | parent->pt_activate(parent); |
| 764 | 927 | ||
| 928 | device_create_file(&serio->dev, &psmouse_attr_protocol); | ||
| 765 | device_create_file(&serio->dev, &psmouse_attr_rate); | 929 | device_create_file(&serio->dev, &psmouse_attr_rate); |
| 766 | device_create_file(&serio->dev, &psmouse_attr_resolution); | 930 | device_create_file(&serio->dev, &psmouse_attr_resolution); |
| 767 | device_create_file(&serio->dev, &psmouse_attr_resetafter); | 931 | device_create_file(&serio->dev, &psmouse_attr_resetafter); |
| @@ -771,10 +935,11 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
| 771 | retval = 0; | 935 | retval = 0; |
| 772 | 936 | ||
| 773 | out: | 937 | out: |
| 774 | /* If this is a pass-through port the parent awaits to be activated */ | 938 | /* If this is a pass-through port the parent needs to be re-activated */ |
| 775 | if (parent) | 939 | if (parent) |
| 776 | psmouse_activate(parent); | 940 | psmouse_activate(parent); |
| 777 | 941 | ||
| 942 | up(&psmouse_sem); | ||
| 778 | return retval; | 943 | return retval; |
| 779 | } | 944 | } |
| 780 | 945 | ||
| @@ -791,6 +956,8 @@ static int psmouse_reconnect(struct serio *serio) | |||
| 791 | return -1; | 956 | return -1; |
| 792 | } | 957 | } |
| 793 | 958 | ||
| 959 | down(&psmouse_sem); | ||
| 960 | |||
| 794 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 961 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
| 795 | parent = serio_get_drvdata(serio->parent); | 962 | parent = serio_get_drvdata(serio->parent); |
| 796 | psmouse_deactivate(parent); | 963 | psmouse_deactivate(parent); |
| @@ -823,6 +990,7 @@ out: | |||
| 823 | if (parent) | 990 | if (parent) |
| 824 | psmouse_activate(parent); | 991 | psmouse_activate(parent); |
| 825 | 992 | ||
| 993 | up(&psmouse_sem); | ||
| 826 | return rc; | 994 | return rc; |
| 827 | } | 995 | } |
| 828 | 996 | ||
| @@ -893,26 +1061,109 @@ ssize_t psmouse_attr_set_helper(struct device *dev, const char *buf, size_t coun | |||
| 893 | 1061 | ||
| 894 | if (serio->drv != &psmouse_drv) { | 1062 | if (serio->drv != &psmouse_drv) { |
| 895 | retval = -ENODEV; | 1063 | retval = -ENODEV; |
| 896 | goto out; | 1064 | goto out_unpin; |
| 1065 | } | ||
| 1066 | |||
| 1067 | retval = down_interruptible(&psmouse_sem); | ||
| 1068 | if (retval) | ||
| 1069 | goto out_unpin; | ||
| 1070 | |||
| 1071 | if (psmouse->state == PSMOUSE_IGNORE) { | ||
| 1072 | retval = -ENODEV; | ||
| 1073 | goto out_up; | ||
| 897 | } | 1074 | } |
| 898 | 1075 | ||
| 899 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 1076 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
| 900 | parent = serio_get_drvdata(serio->parent); | 1077 | parent = serio_get_drvdata(serio->parent); |
| 901 | psmouse_deactivate(parent); | 1078 | psmouse_deactivate(parent); |
| 902 | } | 1079 | } |
| 1080 | |||
| 903 | psmouse_deactivate(psmouse); | 1081 | psmouse_deactivate(psmouse); |
| 904 | 1082 | ||
| 905 | retval = handler(psmouse, buf, count); | 1083 | retval = handler(psmouse, buf, count); |
| 906 | 1084 | ||
| 907 | psmouse_activate(psmouse); | 1085 | if (retval != -ENODEV) |
| 1086 | psmouse_activate(psmouse); | ||
| 1087 | |||
| 908 | if (parent) | 1088 | if (parent) |
| 909 | psmouse_activate(parent); | 1089 | psmouse_activate(parent); |
| 910 | 1090 | ||
| 911 | out: | 1091 | out_up: |
| 1092 | up(&psmouse_sem); | ||
| 1093 | out_unpin: | ||
| 912 | serio_unpin_driver(serio); | 1094 | serio_unpin_driver(serio); |
| 913 | return retval; | 1095 | return retval; |
| 914 | } | 1096 | } |
| 915 | 1097 | ||
| 1098 | static ssize_t psmouse_attr_show_protocol(struct psmouse *psmouse, char *buf) | ||
| 1099 | { | ||
| 1100 | return sprintf(buf, "%s\n", psmouse_protocol_by_type(psmouse->type)->name); | ||
| 1101 | } | ||
| 1102 | |||
| 1103 | static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, const char *buf, size_t count) | ||
| 1104 | { | ||
| 1105 | struct serio *serio = psmouse->ps2dev.serio; | ||
| 1106 | struct psmouse *parent = NULL; | ||
| 1107 | struct psmouse_protocol *proto; | ||
| 1108 | int retry = 0; | ||
| 1109 | |||
| 1110 | if (!(proto = psmouse_protocol_by_name(buf, count))) | ||
| 1111 | return -EINVAL; | ||
| 1112 | |||
| 1113 | if (psmouse->type == proto->type) | ||
| 1114 | return count; | ||
| 1115 | |||
| 1116 | while (serio->child) { | ||
| 1117 | if (++retry > 3) { | ||
| 1118 | printk(KERN_WARNING "psmouse: failed to destroy child port, protocol change aborted.\n"); | ||
| 1119 | return -EIO; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | up(&psmouse_sem); | ||
| 1123 | serio_unpin_driver(serio); | ||
| 1124 | serio_unregister_child_port(serio); | ||
| 1125 | serio_pin_driver_uninterruptible(serio); | ||
| 1126 | down(&psmouse_sem); | ||
| 1127 | |||
| 1128 | if (serio->drv != &psmouse_drv) | ||
| 1129 | return -ENODEV; | ||
| 1130 | |||
| 1131 | if (psmouse->type == proto->type) | ||
| 1132 | return count; /* switched by other thread */ | ||
| 1133 | } | ||
| 1134 | |||
| 1135 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
| 1136 | parent = serio_get_drvdata(serio->parent); | ||
| 1137 | if (parent->pt_deactivate) | ||
| 1138 | parent->pt_deactivate(parent); | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | if (psmouse->disconnect) | ||
| 1142 | psmouse->disconnect(psmouse); | ||
| 1143 | |||
| 1144 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
| 1145 | input_unregister_device(&psmouse->dev); | ||
| 1146 | |||
| 1147 | psmouse_set_state(psmouse, PSMOUSE_INITIALIZING); | ||
| 1148 | |||
| 1149 | if (psmouse_switch_protocol(psmouse, proto) < 0) { | ||
| 1150 | psmouse_reset(psmouse); | ||
| 1151 | /* default to PSMOUSE_PS2 */ | ||
| 1152 | psmouse_switch_protocol(psmouse, &psmouse_protocols[0]); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | psmouse_initialize(psmouse); | ||
| 1156 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
| 1157 | |||
| 1158 | input_register_device(&psmouse->dev); | ||
| 1159 | printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys); | ||
| 1160 | |||
| 1161 | if (parent && parent->pt_activate) | ||
| 1162 | parent->pt_activate(parent); | ||
| 1163 | |||
| 1164 | return count; | ||
| 1165 | } | ||
| 1166 | |||
| 916 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) | 1167 | static ssize_t psmouse_attr_show_rate(struct psmouse *psmouse, char *buf) |
| 917 | { | 1168 | { |
| 918 | return sprintf(buf, "%d\n", psmouse->rate); | 1169 | return sprintf(buf, "%d\n", psmouse->rate); |
| @@ -969,34 +1220,26 @@ static ssize_t psmouse_attr_set_resetafter(struct psmouse *psmouse, const char * | |||
| 969 | 1220 | ||
| 970 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) | 1221 | static int psmouse_set_maxproto(const char *val, struct kernel_param *kp) |
| 971 | { | 1222 | { |
| 972 | int i; | 1223 | struct psmouse_protocol *proto; |
| 973 | 1224 | ||
| 974 | if (!val) | 1225 | if (!val) |
| 975 | return -EINVAL; | 1226 | return -EINVAL; |
| 976 | 1227 | ||
| 977 | if (!strncmp(val, "any", 3)) { | 1228 | proto = psmouse_protocol_by_name(val, strlen(val)); |
| 978 | *((unsigned int *)kp->arg) = -1U; | ||
| 979 | return 0; | ||
| 980 | } | ||
| 981 | 1229 | ||
| 982 | for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) { | 1230 | if (!proto || !proto->maxproto) |
| 983 | if (!psmouse_proto_abbrev[i]) | 1231 | return -EINVAL; |
| 984 | continue; | ||
| 985 | 1232 | ||
| 986 | if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) { | 1233 | *((unsigned int *)kp->arg) = proto->type; |
| 987 | *((unsigned int *)kp->arg) = i; | ||
| 988 | return 0; | ||
| 989 | } | ||
| 990 | } | ||
| 991 | 1234 | ||
| 992 | return -EINVAL; \ | 1235 | return 0; \ |
| 993 | } | 1236 | } |
| 994 | 1237 | ||
| 995 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | 1238 | static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) |
| 996 | { | 1239 | { |
| 997 | return sprintf(buffer, "%s\n", | 1240 | int type = *((unsigned int *)kp->arg); |
| 998 | psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ? | 1241 | |
| 999 | psmouse_proto_abbrev[psmouse_max_proto] : "any"); | 1242 | return sprintf(buffer, "%s\n", psmouse_protocol_by_type(type)->name); |
| 1000 | } | 1243 | } |
| 1001 | 1244 | ||
| 1002 | static int __init psmouse_init(void) | 1245 | static int __init psmouse_init(void) |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 79e17a0c4664..86691cf43433 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -77,6 +77,8 @@ enum psmouse_type { | |||
| 77 | PSMOUSE_IMEX, | 77 | PSMOUSE_IMEX, |
| 78 | PSMOUSE_SYNAPTICS, | 78 | PSMOUSE_SYNAPTICS, |
| 79 | PSMOUSE_ALPS, | 79 | PSMOUSE_ALPS, |
| 80 | PSMOUSE_LIFEBOOK, | ||
| 81 | PSMOUSE_AUTO /* This one should always be last */ | ||
| 80 | }; | 82 | }; |
| 81 | 83 | ||
| 82 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); | 84 | int psmouse_sliced_command(struct psmouse *psmouse, unsigned char command); |
| @@ -99,7 +101,7 @@ static ssize_t psmouse_do_set_##_name(struct device *d, struct device_attribute | |||
| 99 | { \ | 101 | { \ |
| 100 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ | 102 | return psmouse_attr_set_helper(d, b, s, psmouse_attr_set_##_name); \ |
| 101 | } \ | 103 | } \ |
| 102 | static struct device_attribute psmouse_attr_##_name = \ | 104 | static struct device_attribute psmouse_attr_##_name = \ |
| 103 | __ATTR(_name, S_IWUSR | S_IRUGO, \ | 105 | __ATTR(_name, S_IWUSR | S_IRUGO, \ |
| 104 | psmouse_do_show_##_name, psmouse_do_set_##_name); | 106 | psmouse_do_show_##_name, psmouse_do_set_##_name); |
| 105 | 107 | ||
diff --git a/drivers/input/mouse/rpcmouse.c b/drivers/input/mouse/rpcmouse.c index 7280f68afcee..8fe1212b8fd7 100644 --- a/drivers/input/mouse/rpcmouse.c +++ b/drivers/input/mouse/rpcmouse.c | |||
| @@ -59,7 +59,7 @@ static irqreturn_t rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs) | |||
| 59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); | 59 | b = (short) (__raw_readl(0xe0310000) ^ 0x70); |
| 60 | 60 | ||
| 61 | dx = x - rpcmouse_lastx; | 61 | dx = x - rpcmouse_lastx; |
| 62 | dy = y - rpcmouse_lasty; | 62 | dy = y - rpcmouse_lasty; |
| 63 | 63 | ||
| 64 | rpcmouse_lastx = x; | 64 | rpcmouse_lastx = x; |
| 65 | rpcmouse_lasty = y; | 65 | rpcmouse_lasty = y; |
diff --git a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c index b2cb101c8110..f024be9b44d2 100644 --- a/drivers/input/mouse/vsxxxaa.c +++ b/drivers/input/mouse/vsxxxaa.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) | 2 | * Driver for DEC VSXXX-AA mouse (hockey-puck mouse, ball or two rollers) |
| 3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) | 3 | * DEC VSXXX-GA mouse (rectangular mouse, with ball) |
| 4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) | 4 | * DEC VSXXX-AB tablet (digitizer with hair cross or stylus) |
| 5 | * | 5 | * |
| 6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> | 6 | * Copyright (C) 2003-2004 by Jan-Benedict Glaw <jbglaw@lug-owl.de> |
| 7 | * | 7 | * |
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index 062848ac7e6b..c6194a9dd174 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c | |||
| @@ -220,6 +220,7 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
| 220 | struct mousedev_list *list; | 220 | struct mousedev_list *list; |
| 221 | struct mousedev_motion *p; | 221 | struct mousedev_motion *p; |
| 222 | unsigned long flags; | 222 | unsigned long flags; |
| 223 | int wake_readers = 0; | ||
| 223 | 224 | ||
| 224 | list_for_each_entry(list, &mousedev->list, node) { | 225 | list_for_each_entry(list, &mousedev->list, node) { |
| 225 | spin_lock_irqsave(&list->packet_lock, flags); | 226 | spin_lock_irqsave(&list->packet_lock, flags); |
| @@ -255,11 +256,14 @@ static void mousedev_notify_readers(struct mousedev *mousedev, struct mousedev_h | |||
| 255 | 256 | ||
| 256 | spin_unlock_irqrestore(&list->packet_lock, flags); | 257 | spin_unlock_irqrestore(&list->packet_lock, flags); |
| 257 | 258 | ||
| 258 | if (list->ready) | 259 | if (list->ready) { |
| 259 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 260 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
| 261 | wake_readers = 1; | ||
| 262 | } | ||
| 260 | } | 263 | } |
| 261 | 264 | ||
| 262 | wake_up_interruptible(&mousedev->wait); | 265 | if (wake_readers) |
| 266 | wake_up_interruptible(&mousedev->wait); | ||
| 263 | } | 267 | } |
| 264 | 268 | ||
| 265 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) | 269 | static void mousedev_touchpad_touch(struct mousedev *mousedev, int value) |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index c978657068c5..d4c990f7c85e 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
| @@ -29,6 +29,7 @@ MODULE_LICENSE("GPL"); | |||
| 29 | 29 | ||
| 30 | EXPORT_SYMBOL(ps2_init); | 30 | EXPORT_SYMBOL(ps2_init); |
| 31 | EXPORT_SYMBOL(ps2_sendbyte); | 31 | EXPORT_SYMBOL(ps2_sendbyte); |
| 32 | EXPORT_SYMBOL(ps2_drain); | ||
| 32 | EXPORT_SYMBOL(ps2_command); | 33 | EXPORT_SYMBOL(ps2_command); |
| 33 | EXPORT_SYMBOL(ps2_schedule_command); | 34 | EXPORT_SYMBOL(ps2_schedule_command); |
| 34 | EXPORT_SYMBOL(ps2_handle_ack); | 35 | EXPORT_SYMBOL(ps2_handle_ack); |
| @@ -45,11 +46,11 @@ struct ps2work { | |||
| 45 | 46 | ||
| 46 | 47 | ||
| 47 | /* | 48 | /* |
| 48 | * ps2_sendbyte() sends a byte to the mouse, and waits for acknowledge. | 49 | * ps2_sendbyte() sends a byte to the device and waits for acknowledge. |
| 49 | * It doesn't handle retransmission, though it could - because when there would | 50 | * It doesn't handle retransmission, though it could - because if there |
| 50 | * be need for retransmissions, the mouse has to be replaced anyway. | 51 | * is a need for retransmissions device has to be replaced anyway. |
| 51 | * | 52 | * |
| 52 | * ps2_sendbyte() can only be called from a process context | 53 | * ps2_sendbyte() can only be called from a process context. |
| 53 | */ | 54 | */ |
| 54 | 55 | ||
| 55 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | 56 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) |
| @@ -72,6 +73,91 @@ int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout) | |||
| 72 | } | 73 | } |
| 73 | 74 | ||
| 74 | /* | 75 | /* |
| 76 | * ps2_drain() waits for device to transmit requested number of bytes | ||
| 77 | * and discards them. | ||
| 78 | */ | ||
| 79 | |||
| 80 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout) | ||
| 81 | { | ||
| 82 | if (maxbytes > sizeof(ps2dev->cmdbuf)) { | ||
| 83 | WARN_ON(1); | ||
| 84 | maxbytes = sizeof(ps2dev->cmdbuf); | ||
| 85 | } | ||
| 86 | |||
| 87 | down(&ps2dev->cmd_sem); | ||
| 88 | |||
| 89 | serio_pause_rx(ps2dev->serio); | ||
| 90 | ps2dev->flags = PS2_FLAG_CMD; | ||
| 91 | ps2dev->cmdcnt = maxbytes; | ||
| 92 | serio_continue_rx(ps2dev->serio); | ||
| 93 | |||
| 94 | wait_event_timeout(ps2dev->wait, | ||
| 95 | !(ps2dev->flags & PS2_FLAG_CMD), | ||
| 96 | msecs_to_jiffies(timeout)); | ||
| 97 | up(&ps2dev->cmd_sem); | ||
| 98 | } | ||
| 99 | |||
| 100 | /* | ||
| 101 | * ps2_is_keyboard_id() checks received ID byte against the list of | ||
| 102 | * known keyboard IDs. | ||
| 103 | */ | ||
| 104 | |||
| 105 | static inline int ps2_is_keyboard_id(char id_byte) | ||
| 106 | { | ||
| 107 | static char keyboard_ids[] = { | ||
| 108 | 0xab, /* Regular keyboards */ | ||
| 109 | 0xac, /* NCD Sun keyboard */ | ||
| 110 | 0x2b, /* Trust keyboard, translated */ | ||
| 111 | 0x5d, /* Trust keyboard */ | ||
| 112 | 0x60, /* NMB SGI keyboard, translated */ | ||
| 113 | 0x47, /* NMB SGI keyboard */ | ||
| 114 | }; | ||
| 115 | |||
| 116 | return memchr(keyboard_ids, id_byte, sizeof(keyboard_ids)) != NULL; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* | ||
| 120 | * ps2_adjust_timeout() is called after receiving 1st byte of command | ||
| 121 | * response and tries to reduce remaining timeout to speed up command | ||
| 122 | * completion. | ||
| 123 | */ | ||
| 124 | |||
| 125 | static int ps2_adjust_timeout(struct ps2dev *ps2dev, int command, int timeout) | ||
| 126 | { | ||
| 127 | switch (command) { | ||
| 128 | case PS2_CMD_RESET_BAT: | ||
| 129 | /* | ||
| 130 | * Device has sent the first response byte after | ||
| 131 | * reset command, reset is thus done, so we can | ||
| 132 | * shorten the timeout. | ||
| 133 | * The next byte will come soon (keyboard) or not | ||
| 134 | * at all (mouse). | ||
| 135 | */ | ||
| 136 | if (timeout > msecs_to_jiffies(100)) | ||
| 137 | timeout = msecs_to_jiffies(100); | ||
| 138 | break; | ||
| 139 | |||
| 140 | case PS2_CMD_GETID: | ||
| 141 | /* | ||
| 142 | * If device behind the port is not a keyboard there | ||
| 143 | * won't be 2nd byte of ID response. | ||
| 144 | */ | ||
| 145 | if (!ps2_is_keyboard_id(ps2dev->cmdbuf[1])) { | ||
| 146 | serio_pause_rx(ps2dev->serio); | ||
| 147 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
| 148 | serio_continue_rx(ps2dev->serio); | ||
| 149 | timeout = 0; | ||
| 150 | } | ||
| 151 | break; | ||
| 152 | |||
| 153 | default: | ||
| 154 | break; | ||
| 155 | } | ||
| 156 | |||
| 157 | return timeout; | ||
| 158 | } | ||
| 159 | |||
| 160 | /* | ||
| 75 | * ps2_command() sends a command and its parameters to the mouse, | 161 | * ps2_command() sends a command and its parameters to the mouse, |
| 76 | * then waits for the response and puts it in the param array. | 162 | * then waits for the response and puts it in the param array. |
| 77 | * | 163 | * |
| @@ -86,6 +172,11 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 86 | int rc = -1; | 172 | int rc = -1; |
| 87 | int i; | 173 | int i; |
| 88 | 174 | ||
| 175 | if (receive > sizeof(ps2dev->cmdbuf)) { | ||
| 176 | WARN_ON(1); | ||
| 177 | return -1; | ||
| 178 | } | ||
| 179 | |||
| 89 | down(&ps2dev->cmd_sem); | 180 | down(&ps2dev->cmd_sem); |
| 90 | 181 | ||
| 91 | serio_pause_rx(ps2dev->serio); | 182 | serio_pause_rx(ps2dev->serio); |
| @@ -101,10 +192,9 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 101 | * ACKing the reset command, and so it can take a long | 192 | * ACKing the reset command, and so it can take a long |
| 102 | * time before the ACK arrrives. | 193 | * time before the ACK arrrives. |
| 103 | */ | 194 | */ |
| 104 | if (command & 0xff) | 195 | if (ps2_sendbyte(ps2dev, command & 0xff, |
| 105 | if (ps2_sendbyte(ps2dev, command & 0xff, | 196 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) |
| 106 | command == PS2_CMD_RESET_BAT ? 1000 : 200)) | 197 | goto out; |
| 107 | goto out; | ||
| 108 | 198 | ||
| 109 | for (i = 0; i < send; i++) | 199 | for (i = 0; i < send; i++) |
| 110 | if (ps2_sendbyte(ps2dev, param[i], 200)) | 200 | if (ps2_sendbyte(ps2dev, param[i], 200)) |
| @@ -120,33 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 120 | 210 | ||
| 121 | if (ps2dev->cmdcnt && timeout > 0) { | 211 | if (ps2dev->cmdcnt && timeout > 0) { |
| 122 | 212 | ||
| 123 | if (command == PS2_CMD_RESET_BAT && timeout > msecs_to_jiffies(100)) { | 213 | timeout = ps2_adjust_timeout(ps2dev, command, timeout); |
| 124 | /* | ||
| 125 | * Device has sent the first response byte | ||
| 126 | * after a reset command, reset is thus done, | ||
| 127 | * shorten the timeout. The next byte will come | ||
| 128 | * soon (keyboard) or not at all (mouse). | ||
| 129 | */ | ||
| 130 | timeout = msecs_to_jiffies(100); | ||
| 131 | } | ||
| 132 | |||
| 133 | if (command == PS2_CMD_GETID && | ||
| 134 | ps2dev->cmdbuf[receive - 1] != 0xab && /* Regular keyboards */ | ||
| 135 | ps2dev->cmdbuf[receive - 1] != 0xac && /* NCD Sun keyboard */ | ||
| 136 | ps2dev->cmdbuf[receive - 1] != 0x2b && /* Trust keyboard, translated */ | ||
| 137 | ps2dev->cmdbuf[receive - 1] != 0x5d && /* Trust keyboard */ | ||
| 138 | ps2dev->cmdbuf[receive - 1] != 0x60 && /* NMB SGI keyboard, translated */ | ||
| 139 | ps2dev->cmdbuf[receive - 1] != 0x47) { /* NMB SGI keyboard */ | ||
| 140 | /* | ||
| 141 | * Device behind the port is not a keyboard | ||
| 142 | * so we don't need to wait for the 2nd byte | ||
| 143 | * of ID response. | ||
| 144 | */ | ||
| 145 | serio_pause_rx(ps2dev->serio); | ||
| 146 | ps2dev->flags = ps2dev->cmdcnt = 0; | ||
| 147 | serio_continue_rx(ps2dev->serio); | ||
| 148 | } | ||
| 149 | |||
| 150 | wait_event_timeout(ps2dev->wait, | 214 | wait_event_timeout(ps2dev->wait, |
| 151 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); | 215 | !(ps2dev->flags & PS2_FLAG_CMD), timeout); |
| 152 | } | 216 | } |
| @@ -160,7 +224,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 160 | 224 | ||
| 161 | rc = 0; | 225 | rc = 0; |
| 162 | 226 | ||
| 163 | out: | 227 | out: |
| 164 | serio_pause_rx(ps2dev->serio); | 228 | serio_pause_rx(ps2dev->serio); |
| 165 | ps2dev->flags = 0; | 229 | ps2dev->flags = 0; |
| 166 | serio_continue_rx(ps2dev->serio); | 230 | serio_continue_rx(ps2dev->serio); |
diff --git a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c index 546ce599334e..3cdc9cab688d 100644 --- a/drivers/input/touchscreen/elo.c +++ b/drivers/input/touchscreen/elo.c | |||
| @@ -226,7 +226,7 @@ static int elo_connect(struct serio *serio, struct serio_driver *drv) | |||
| 226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); | 226 | input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0); |
| 227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); | 227 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0); |
| 228 | break; | 228 | break; |
| 229 | 229 | ||
| 230 | case 1: /* 6-byte protocol */ | 230 | case 1: /* 6-byte protocol */ |
| 231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); | 231 | input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0); |
| 232 | 232 | ||
diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index acb9137a0226..bcfa1e36f957 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c | |||
| @@ -89,9 +89,9 @@ MODULE_LICENSE("GPL"); | |||
| 89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ | 89 | #define H3600_SCANCODE_Q 4 /* 4 -> Q button */ |
| 90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ | 90 | #define H3600_SCANCODE_START 5 /* 5 -> start menu */ |
| 91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ | 91 | #define H3600_SCANCODE_UP 6 /* 6 -> up */ |
| 92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ | 92 | #define H3600_SCANCODE_RIGHT 7 /* 7 -> right */ |
| 93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ | 93 | #define H3600_SCANCODE_LEFT 8 /* 8 -> left */ |
| 94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ | 94 | #define H3600_SCANCODE_DOWN 9 /* 9 -> down */ |
| 95 | 95 | ||
| 96 | static char *h3600_name = "H3600 TouchScreen"; | 96 | static char *h3600_name = "H3600 TouchScreen"; |
| 97 | 97 | ||
| @@ -113,7 +113,7 @@ struct h3600_dev { | |||
| 113 | 113 | ||
| 114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 114 | static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
| 115 | { | 115 | { |
| 116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; | 116 | int down = (GPLR & GPIO_BITSY_ACTION_BUTTON) ? 0 : 1; |
| 117 | struct input_dev *dev = (struct input_dev *) dev_id; | 117 | struct input_dev *dev = (struct input_dev *) dev_id; |
| 118 | 118 | ||
| 119 | input_regs(dev, regs); | 119 | input_regs(dev, regs); |
| @@ -125,7 +125,7 @@ static irqreturn_t action_button_handler(int irq, void *dev_id, struct pt_regs * | |||
| 125 | 125 | ||
| 126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) | 126 | static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs *regs) |
| 127 | { | 127 | { |
| 128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; | 128 | int down = (GPLR & GPIO_BITSY_NPOWER_BUTTON) ? 0 : 1; |
| 129 | struct input_dev *dev = (struct input_dev *) dev_id; | 129 | struct input_dev *dev = (struct input_dev *) dev_id; |
| 130 | 130 | ||
| 131 | /* | 131 | /* |
| @@ -145,8 +145,8 @@ static irqreturn_t npower_button_handler(int irq, void *dev_id, struct pt_regs * | |||
| 145 | static int flite_brightness = 25; | 145 | static int flite_brightness = 25; |
| 146 | 146 | ||
| 147 | enum flite_pwr { | 147 | enum flite_pwr { |
| 148 | FLITE_PWR_OFF = 0, | 148 | FLITE_PWR_OFF = 0, |
| 149 | FLITE_PWR_ON = 1 | 149 | FLITE_PWR_ON = 1 |
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | /* | 152 | /* |
| @@ -157,9 +157,9 @@ unsigned int h3600_flite_power(struct input_dev *dev, enum flite_pwr pwr) | |||
| 157 | struct h3600_dev *ts = dev->private; | 157 | struct h3600_dev *ts = dev->private; |
| 158 | 158 | ||
| 159 | /* Must be in this order */ | 159 | /* Must be in this order */ |
| 160 | ts->serio->write(ts->serio, 1); | 160 | ts->serio->write(ts->serio, 1); |
| 161 | ts->serio->write(ts->serio, pwr); | 161 | ts->serio->write(ts->serio, pwr); |
| 162 | ts->serio->write(ts->serio, brightness); | 162 | ts->serio->write(ts->serio, brightness); |
| 163 | return 0; | 163 | return 0; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| @@ -169,26 +169,26 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
| 169 | { | 169 | { |
| 170 | struct input_dev *dev = (struct input_dev *) data; | 170 | struct input_dev *dev = (struct input_dev *) data; |
| 171 | 171 | ||
| 172 | switch (req) { | 172 | switch (req) { |
| 173 | case PM_SUSPEND: /* enter D1-D3 */ | 173 | case PM_SUSPEND: /* enter D1-D3 */ |
| 174 | suspended = 1; | 174 | suspended = 1; |
| 175 | h3600_flite_power(dev, FLITE_PWR_OFF); | 175 | h3600_flite_power(dev, FLITE_PWR_OFF); |
| 176 | break; | 176 | break; |
| 177 | case PM_BLANK: | 177 | case PM_BLANK: |
| 178 | if (!suspended) | 178 | if (!suspended) |
| 179 | h3600_flite_power(dev, FLITE_PWR_OFF); | 179 | h3600_flite_power(dev, FLITE_PWR_OFF); |
| 180 | break; | 180 | break; |
| 181 | case PM_RESUME: /* enter D0 */ | 181 | case PM_RESUME: /* enter D0 */ |
| 182 | /* same as unblank */ | 182 | /* same as unblank */ |
| 183 | case PM_UNBLANK: | 183 | case PM_UNBLANK: |
| 184 | if (suspended) { | 184 | if (suspended) { |
| 185 | //initSerial(); | 185 | //initSerial(); |
| 186 | suspended = 0; | 186 | suspended = 0; |
| 187 | } | 187 | } |
| 188 | h3600_flite_power(dev, FLITE_PWR_ON); | 188 | h3600_flite_power(dev, FLITE_PWR_ON); |
| 189 | break; | 189 | break; |
| 190 | } | 190 | } |
| 191 | return 0; | 191 | return 0; |
| 192 | } | 192 | } |
| 193 | #endif | 193 | #endif |
| 194 | 194 | ||
| @@ -199,25 +199,25 @@ static int h3600ts_pm_callback(struct pm_dev *pm_dev, pm_request_t req, | |||
| 199 | */ | 199 | */ |
| 200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | 200 | static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) |
| 201 | { | 201 | { |
| 202 | struct input_dev *dev = &ts->dev; | 202 | struct input_dev *dev = &ts->dev; |
| 203 | static int touched = 0; | 203 | static int touched = 0; |
| 204 | int key, down = 0; | 204 | int key, down = 0; |
| 205 | 205 | ||
| 206 | input_regs(dev, regs); | 206 | input_regs(dev, regs); |
| 207 | 207 | ||
| 208 | switch (ts->event) { | 208 | switch (ts->event) { |
| 209 | /* | 209 | /* |
| 210 | Buttons - returned as a single byte | 210 | Buttons - returned as a single byte |
| 211 | 7 6 5 4 3 2 1 0 | 211 | 7 6 5 4 3 2 1 0 |
| 212 | S x x x N N N N | 212 | S x x x N N N N |
| 213 | 213 | ||
| 214 | S switch state ( 0=pressed 1=released) | 214 | S switch state ( 0=pressed 1=released) |
| 215 | x Unused. | 215 | x Unused. |
| 216 | NNNN switch number 0-15 | 216 | NNNN switch number 0-15 |
| 217 | 217 | ||
| 218 | Note: This is true for non interrupt generated key events. | 218 | Note: This is true for non interrupt generated key events. |
| 219 | */ | 219 | */ |
| 220 | case KEYBD_ID: | 220 | case KEYBD_ID: |
| 221 | down = (ts->buf[0] & 0x80) ? 0 : 1; | 221 | down = (ts->buf[0] & 0x80) ? 0 : 1; |
| 222 | 222 | ||
| 223 | switch (ts->buf[0] & 0x7f) { | 223 | switch (ts->buf[0] & 0x7f) { |
| @@ -229,40 +229,40 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
| 229 | break; | 229 | break; |
| 230 | case H3600_SCANCODE_CONTACTS: | 230 | case H3600_SCANCODE_CONTACTS: |
| 231 | key = KEY_PROG2; | 231 | key = KEY_PROG2; |
| 232 | break; | 232 | break; |
| 233 | case H3600_SCANCODE_Q: | 233 | case H3600_SCANCODE_Q: |
| 234 | key = KEY_Q; | 234 | key = KEY_Q; |
| 235 | break; | 235 | break; |
| 236 | case H3600_SCANCODE_START: | 236 | case H3600_SCANCODE_START: |
| 237 | key = KEY_PROG3; | 237 | key = KEY_PROG3; |
| 238 | break; | 238 | break; |
| 239 | case H3600_SCANCODE_UP: | 239 | case H3600_SCANCODE_UP: |
| 240 | key = KEY_UP; | 240 | key = KEY_UP; |
| 241 | break; | 241 | break; |
| 242 | case H3600_SCANCODE_RIGHT: | 242 | case H3600_SCANCODE_RIGHT: |
| 243 | key = KEY_RIGHT; | 243 | key = KEY_RIGHT; |
| 244 | break; | 244 | break; |
| 245 | case H3600_SCANCODE_LEFT: | 245 | case H3600_SCANCODE_LEFT: |
| 246 | key = KEY_LEFT; | 246 | key = KEY_LEFT; |
| 247 | break; | 247 | break; |
| 248 | case H3600_SCANCODE_DOWN: | 248 | case H3600_SCANCODE_DOWN: |
| 249 | key = KEY_DOWN; | 249 | key = KEY_DOWN; |
| 250 | break; | 250 | break; |
| 251 | default: | 251 | default: |
| 252 | key = 0; | 252 | key = 0; |
| 253 | } | 253 | } |
| 254 | if (key) | 254 | if (key) |
| 255 | input_report_key(dev, key, down); | 255 | input_report_key(dev, key, down); |
| 256 | break; | 256 | break; |
| 257 | /* | 257 | /* |
| 258 | * Native touchscreen event data is formatted as shown below:- | 258 | * Native touchscreen event data is formatted as shown below:- |
| 259 | * | 259 | * |
| 260 | * +-------+-------+-------+-------+ | 260 | * +-------+-------+-------+-------+ |
| 261 | * | Xmsb | Xlsb | Ymsb | Ylsb | | 261 | * | Xmsb | Xlsb | Ymsb | Ylsb | |
| 262 | * +-------+-------+-------+-------+ | 262 | * +-------+-------+-------+-------+ |
| 263 | * byte 0 1 2 3 | 263 | * byte 0 1 2 3 |
| 264 | */ | 264 | */ |
| 265 | case TOUCHS_ID: | 265 | case TOUCHS_ID: |
| 266 | if (!touched) { | 266 | if (!touched) { |
| 267 | input_report_key(dev, BTN_TOUCH, 1); | 267 | input_report_key(dev, BTN_TOUCH, 1); |
| 268 | touched = 1; | 268 | touched = 1; |
| @@ -272,19 +272,19 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
| 272 | unsigned short x, y; | 272 | unsigned short x, y; |
| 273 | 273 | ||
| 274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; | 274 | x = ts->buf[0]; x <<= 8; x += ts->buf[1]; |
| 275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; | 275 | y = ts->buf[2]; y <<= 8; y += ts->buf[3]; |
| 276 | 276 | ||
| 277 | input_report_abs(dev, ABS_X, x); | 277 | input_report_abs(dev, ABS_X, x); |
| 278 | input_report_abs(dev, ABS_Y, y); | 278 | input_report_abs(dev, ABS_Y, y); |
| 279 | } else { | 279 | } else { |
| 280 | input_report_key(dev, BTN_TOUCH, 0); | 280 | input_report_key(dev, BTN_TOUCH, 0); |
| 281 | touched = 0; | 281 | touched = 0; |
| 282 | } | 282 | } |
| 283 | break; | 283 | break; |
| 284 | default: | 284 | default: |
| 285 | /* Send a non input event elsewhere */ | 285 | /* Send a non input event elsewhere */ |
| 286 | break; | 286 | break; |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | input_sync(dev); | 289 | input_sync(dev); |
| 290 | } | 290 | } |
| @@ -293,7 +293,7 @@ static void h3600ts_process_packet(struct h3600_dev *ts, struct pt_regs *regs) | |||
| 293 | * h3600ts_event() handles events from the input module. | 293 | * h3600ts_event() handles events from the input module. |
| 294 | */ | 294 | */ |
| 295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, | 295 | static int h3600ts_event(struct input_dev *dev, unsigned int type, |
| 296 | unsigned int code, int value) | 296 | unsigned int code, int value) |
| 297 | { | 297 | { |
| 298 | struct h3600_dev *ts = dev->private; | 298 | struct h3600_dev *ts = dev->private; |
| 299 | 299 | ||
| @@ -332,41 +332,41 @@ static int state; | |||
| 332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, | 332 | static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data, |
| 333 | unsigned int flags, struct pt_regs *regs) | 333 | unsigned int flags, struct pt_regs *regs) |
| 334 | { | 334 | { |
| 335 | struct h3600_dev *ts = serio_get_drvdata(serio); | 335 | struct h3600_dev *ts = serio_get_drvdata(serio); |
| 336 | 336 | ||
| 337 | /* | 337 | /* |
| 338 | * We have a new frame coming in. | 338 | * We have a new frame coming in. |
| 339 | */ | 339 | */ |
| 340 | switch (state) { | 340 | switch (state) { |
| 341 | case STATE_SOF: | 341 | case STATE_SOF: |
| 342 | if (data == CHAR_SOF) | 342 | if (data == CHAR_SOF) |
| 343 | state = STATE_ID; | 343 | state = STATE_ID; |
| 344 | break; | 344 | break; |
| 345 | case STATE_ID: | 345 | case STATE_ID: |
| 346 | ts->event = (data & 0xf0) >> 4; | 346 | ts->event = (data & 0xf0) >> 4; |
| 347 | ts->len = (data & 0xf); | 347 | ts->len = (data & 0xf); |
| 348 | ts->idx = 0; | 348 | ts->idx = 0; |
| 349 | if (ts->event >= MAX_ID) { | 349 | if (ts->event >= MAX_ID) { |
| 350 | state = STATE_SOF; | 350 | state = STATE_SOF; |
| 351 | break; | 351 | break; |
| 352 | } | 352 | } |
| 353 | ts->chksum = data; | 353 | ts->chksum = data; |
| 354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; | 354 | state = (ts->len > 0) ? STATE_DATA : STATE_EOF; |
| 355 | break; | 355 | break; |
| 356 | case STATE_DATA: | 356 | case STATE_DATA: |
| 357 | ts->chksum += data; | 357 | ts->chksum += data; |
| 358 | ts->buf[ts->idx]= data; | 358 | ts->buf[ts->idx]= data; |
| 359 | if(++ts->idx == ts->len) | 359 | if (++ts->idx == ts->len) |
| 360 | state = STATE_EOF; | 360 | state = STATE_EOF; |
| 361 | break; | 361 | break; |
| 362 | case STATE_EOF: | 362 | case STATE_EOF: |
| 363 | state = STATE_SOF; | 363 | state = STATE_SOF; |
| 364 | if (data == CHAR_EOF || data == ts->chksum) | 364 | if (data == CHAR_EOF || data == ts->chksum) |
| 365 | h3600ts_process_packet(ts, regs); | 365 | h3600ts_process_packet(ts, regs); |
| 366 | break; | 366 | break; |
| 367 | default: | 367 | default: |
| 368 | printk("Error3\n"); | 368 | printk("Error3\n"); |
| 369 | break; | 369 | break; |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | return IRQ_HANDLED; | 372 | return IRQ_HANDLED; |
| @@ -390,10 +390,10 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
| 390 | init_input_dev(&ts->dev); | 390 | init_input_dev(&ts->dev); |
| 391 | 391 | ||
| 392 | /* Device specific stuff */ | 392 | /* Device specific stuff */ |
| 393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); | 393 | set_GPIO_IRQ_edge(GPIO_BITSY_ACTION_BUTTON, GPIO_BOTH_EDGES); |
| 394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); | 394 | set_GPIO_IRQ_edge(GPIO_BITSY_NPOWER_BUTTON, GPIO_RISING_EDGE); |
| 395 | 395 | ||
| 396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, | 396 | if (request_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, action_button_handler, |
| 397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 397 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
| 398 | "h3600_action", &ts->dev)) { | 398 | "h3600_action", &ts->dev)) { |
| 399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); | 399 | printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n"); |
| @@ -401,7 +401,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
| 401 | return -EBUSY; | 401 | return -EBUSY; |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, | 404 | if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler, |
| 405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, | 405 | SA_SHIRQ | SA_INTERRUPT | SA_SAMPLE_RANDOM, |
| 406 | "h3600_suspend", &ts->dev)) { | 406 | "h3600_suspend", &ts->dev)) { |
| 407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); | 407 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev); |
| @@ -433,7 +433,7 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
| 433 | 433 | ||
| 434 | sprintf(ts->phys, "%s/input0", serio->phys); | 434 | sprintf(ts->phys, "%s/input0", serio->phys); |
| 435 | 435 | ||
| 436 | ts->dev.event = h3600ts_event; | 436 | ts->dev.event = h3600ts_event; |
| 437 | ts->dev.private = ts; | 437 | ts->dev.private = ts; |
| 438 | ts->dev.name = h3600_name; | 438 | ts->dev.name = h3600_name; |
| 439 | ts->dev.phys = ts->phys; | 439 | ts->dev.phys = ts->phys; |
| @@ -446,8 +446,8 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv) | |||
| 446 | 446 | ||
| 447 | err = serio_open(serio, drv); | 447 | err = serio_open(serio, drv); |
| 448 | if (err) { | 448 | if (err) { |
| 449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); | 449 | free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts); |
| 450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); | 450 | free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts); |
| 451 | serio_set_drvdata(serio, NULL); | 451 | serio_set_drvdata(serio, NULL); |
| 452 | kfree(ts); | 452 | kfree(ts); |
| 453 | return err; | 453 | return err; |
diff --git a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c index 2d14a57a05e5..afaaebe5225b 100644 --- a/drivers/input/touchscreen/mk712.c +++ b/drivers/input/touchscreen/mk712.c | |||
| @@ -17,7 +17,7 @@ | |||
| 17 | * found in Gateway AOL Connected Touchpad computers. | 17 | * found in Gateway AOL Connected Touchpad computers. |
| 18 | * | 18 | * |
| 19 | * Documentation for ICS MK712 can be found at: | 19 | * Documentation for ICS MK712 can be found at: |
| 20 | * http://www.icst.com/pdf/mk712.pdf | 20 | * http://www.icst.com/pdf/mk712.pdf |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | /* | 23 | /* |
| @@ -77,7 +77,6 @@ MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller"); | |||
| 77 | #define MK712_READ_ONE_POINT 0x20 | 77 | #define MK712_READ_ONE_POINT 0x20 |
| 78 | #define MK712_POWERUP 0x40 | 78 | #define MK712_POWERUP 0x40 |
| 79 | 79 | ||
| 80 | static int mk712_used = 0; | ||
| 81 | static struct input_dev mk712_dev; | 80 | static struct input_dev mk712_dev; |
| 82 | static DEFINE_SPINLOCK(mk712_lock); | 81 | static DEFINE_SPINLOCK(mk712_lock); |
| 83 | 82 | ||
| @@ -130,17 +129,14 @@ static int mk712_open(struct input_dev *dev) | |||
| 130 | 129 | ||
| 131 | spin_lock_irqsave(&mk712_lock, flags); | 130 | spin_lock_irqsave(&mk712_lock, flags); |
| 132 | 131 | ||
| 133 | if (!mk712_used++) { | 132 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ |
| 134 | 133 | ||
| 135 | outb(0, mk712_io + MK712_CONTROL); /* Reset */ | 134 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | |
| 135 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
| 136 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
| 137 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
| 136 | 138 | ||
| 137 | outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE | | 139 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ |
| 138 | MK712_INT_ON_CHANGE_IN_TOUCH_STATUS | | ||
| 139 | MK712_ENABLE_PERIODIC_CONVERSIONS | | ||
| 140 | MK712_POWERUP, mk712_io + MK712_CONTROL); | ||
| 141 | |||
| 142 | outb(10, mk712_io + MK712_RATE); /* 187 points per second */ | ||
| 143 | } | ||
| 144 | 140 | ||
| 145 | spin_unlock_irqrestore(&mk712_lock, flags); | 141 | spin_unlock_irqrestore(&mk712_lock, flags); |
| 146 | 142 | ||
| @@ -153,8 +149,7 @@ static void mk712_close(struct input_dev *dev) | |||
| 153 | 149 | ||
| 154 | spin_lock_irqsave(&mk712_lock, flags); | 150 | spin_lock_irqsave(&mk712_lock, flags); |
| 155 | 151 | ||
| 156 | if (!--mk712_used) | 152 | outb(0, mk712_io + MK712_CONTROL); |
| 157 | outb(0, mk712_io + MK712_CONTROL); | ||
| 158 | 153 | ||
| 159 | spin_unlock_irqrestore(&mk712_lock, flags); | 154 | spin_unlock_irqrestore(&mk712_lock, flags); |
| 160 | } | 155 | } |
