diff options
79 files changed, 2416 insertions, 1795 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4924d387a657..1a50d0357197 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1104,7 +1104,7 @@ running once the system is up. | |||
| 1104 | See Documentation/ramdisk.txt. | 1104 | See Documentation/ramdisk.txt. |
| 1105 | 1105 | ||
| 1106 | psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to | 1106 | psmouse.proto= [HW,MOUSE] Highest PS2 mouse protocol extension to |
| 1107 | probe for (bare|imps|exps). | 1107 | probe for (bare|imps|exps|lifebook|any). |
| 1108 | psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports | 1108 | psmouse.rate= [HW,MOUSE] Set desired mouse report rate, in reports |
| 1109 | per second. | 1109 | per second. |
| 1110 | psmouse.resetafter= | 1110 | psmouse.resetafter= |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 17552a29978b..d62c73f5ba93 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/gameport.c b/drivers/input/gameport/gameport.c index f20c3f23388b..d7dfa6f53cf6 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
| @@ -17,11 +17,10 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/gameport.h> | 18 | #include <linux/gameport.h> |
| 19 | #include <linux/wait.h> | 19 | #include <linux/wait.h> |
| 20 | #include <linux/completion.h> | ||
| 21 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
| 22 | #include <linux/smp_lock.h> | ||
| 23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 24 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/kthread.h> | ||
| 25 | 24 | ||
| 26 | /*#include <asm/io.h>*/ | 25 | /*#include <asm/io.h>*/ |
| 27 | 26 | ||
| @@ -238,8 +237,7 @@ struct gameport_event { | |||
| 238 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ | 237 | static DEFINE_SPINLOCK(gameport_event_lock); /* protects gameport_event_list */ |
| 239 | static LIST_HEAD(gameport_event_list); | 238 | static LIST_HEAD(gameport_event_list); |
| 240 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); | 239 | static DECLARE_WAIT_QUEUE_HEAD(gameport_wait); |
| 241 | static DECLARE_COMPLETION(gameport_exited); | 240 | static struct task_struct *gameport_task; |
| 242 | static int gameport_pid; | ||
| 243 | 241 | ||
| 244 | static void gameport_queue_event(void *object, struct module *owner, | 242 | static void gameport_queue_event(void *object, struct module *owner, |
| 245 | enum gameport_event_type event_type) | 243 | enum gameport_event_type event_type) |
| @@ -250,12 +248,12 @@ static void gameport_queue_event(void *object, struct module *owner, | |||
| 250 | spin_lock_irqsave(&gameport_event_lock, flags); | 248 | spin_lock_irqsave(&gameport_event_lock, flags); |
| 251 | 249 | ||
| 252 | /* | 250 | /* |
| 253 | * Scan event list for the other events for the same gameport port, | 251 | * Scan event list for the other events for the same gameport port, |
| 254 | * starting with the most recent one. If event is the same we | 252 | * starting with the most recent one. If event is the same we |
| 255 | * do not need add new one. If event is of different type we | 253 | * do not need add new one. If event is of different type we |
| 256 | * need to add this event and should not look further because | 254 | * need to add this event and should not look further because |
| 257 | * we need to preseve sequence of distinct events. | 255 | * we need to preseve sequence of distinct events. |
| 258 | */ | 256 | */ |
| 259 | list_for_each_entry_reverse(event, &gameport_event_list, node) { | 257 | list_for_each_entry_reverse(event, &gameport_event_list, node) { |
| 260 | if (event->object == object) { | 258 | if (event->object == object) { |
| 261 | if (event->type == event_type) | 259 | if (event->type == event_type) |
| @@ -432,20 +430,15 @@ static struct gameport *gameport_get_pending_child(struct gameport *parent) | |||
| 432 | 430 | ||
| 433 | static int gameport_thread(void *nothing) | 431 | static int gameport_thread(void *nothing) |
| 434 | { | 432 | { |
| 435 | lock_kernel(); | ||
| 436 | daemonize("kgameportd"); | ||
| 437 | allow_signal(SIGTERM); | ||
| 438 | |||
| 439 | do { | 433 | do { |
| 440 | gameport_handle_events(); | 434 | gameport_handle_events(); |
| 441 | wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list)); | 435 | wait_event_interruptible(gameport_wait, |
| 436 | kthread_should_stop() || !list_empty(&gameport_event_list)); | ||
| 442 | try_to_freeze(PF_FREEZE); | 437 | try_to_freeze(PF_FREEZE); |
| 443 | } while (!signal_pending(current)); | 438 | } while (!kthread_should_stop()); |
| 444 | 439 | ||
| 445 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); | 440 | printk(KERN_DEBUG "gameport: kgameportd exiting\n"); |
| 446 | 441 | return 0; | |
| 447 | unlock_kernel(); | ||
| 448 | complete_and_exit(&gameport_exited, 0); | ||
| 449 | } | 442 | } |
| 450 | 443 | ||
| 451 | 444 | ||
| @@ -773,9 +766,10 @@ void gameport_close(struct gameport *gameport) | |||
| 773 | 766 | ||
| 774 | static int __init gameport_init(void) | 767 | static int __init gameport_init(void) |
| 775 | { | 768 | { |
| 776 | if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) { | 769 | gameport_task = kthread_run(gameport_thread, NULL, "kgameportd"); |
| 770 | if (IS_ERR(gameport_task)) { | ||
| 777 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); | 771 | printk(KERN_ERR "gameport: Failed to start kgameportd\n"); |
| 778 | return -1; | 772 | return PTR_ERR(gameport_task); |
| 779 | } | 773 | } |
| 780 | 774 | ||
| 781 | gameport_bus.dev_attrs = gameport_device_attrs; | 775 | gameport_bus.dev_attrs = gameport_device_attrs; |
| @@ -789,8 +783,7 @@ static int __init gameport_init(void) | |||
| 789 | static void __exit gameport_exit(void) | 783 | static void __exit gameport_exit(void) |
| 790 | { | 784 | { |
| 791 | bus_unregister(&gameport_bus); | 785 | bus_unregister(&gameport_bus); |
| 792 | kill_proc(gameport_pid, SIGTERM, 1); | 786 | kthread_stop(gameport_task); |
| 793 | wait_for_completion(&gameport_exited); | ||
| 794 | } | 787 | } |
| 795 | 788 | ||
| 796 | module_init(gameport_init); | 789 | module_init(gameport_init); |
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 3385dd03abfc..c1dbc04cf54a 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 627d343dfba1..816a585a0e6b 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 af0446c6de82..9f9da6d4a23f 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, const char *b, size_t s) \ | |||
| 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 42a9f7f6f8cb..ffdc82313192 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 bda5b065d03c..dc8e9ae07f32 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, const char *b, size_t s) | |||
| 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 96fb9870834a..08b191180af0 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/serio/serio.c b/drivers/input/serio/serio.c index 0beacb77ee18..615bf62ad468 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
| @@ -31,10 +31,9 @@ | |||
| 31 | #include <linux/serio.h> | 31 | #include <linux/serio.h> |
| 32 | #include <linux/errno.h> | 32 | #include <linux/errno.h> |
| 33 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
| 34 | #include <linux/completion.h> | ||
| 35 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
| 36 | #include <linux/smp_lock.h> | ||
| 37 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 36 | #include <linux/kthread.h> | ||
| 38 | 37 | ||
| 39 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); | 38 | MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>"); |
| 40 | MODULE_DESCRIPTION("Serio abstraction core"); | 39 | MODULE_DESCRIPTION("Serio abstraction core"); |
| @@ -43,6 +42,7 @@ MODULE_LICENSE("GPL"); | |||
| 43 | EXPORT_SYMBOL(serio_interrupt); | 42 | EXPORT_SYMBOL(serio_interrupt); |
| 44 | EXPORT_SYMBOL(__serio_register_port); | 43 | EXPORT_SYMBOL(__serio_register_port); |
| 45 | EXPORT_SYMBOL(serio_unregister_port); | 44 | EXPORT_SYMBOL(serio_unregister_port); |
| 45 | EXPORT_SYMBOL(serio_unregister_child_port); | ||
| 46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); | 46 | EXPORT_SYMBOL(__serio_unregister_port_delayed); |
| 47 | EXPORT_SYMBOL(__serio_register_driver); | 47 | EXPORT_SYMBOL(__serio_register_driver); |
| 48 | EXPORT_SYMBOL(serio_unregister_driver); | 48 | EXPORT_SYMBOL(serio_unregister_driver); |
| @@ -68,6 +68,37 @@ static void serio_destroy_port(struct serio *serio); | |||
| 68 | static void serio_reconnect_port(struct serio *serio); | 68 | static void serio_reconnect_port(struct serio *serio); |
| 69 | static void serio_disconnect_port(struct serio *serio); | 69 | static void serio_disconnect_port(struct serio *serio); |
| 70 | 70 | ||
| 71 | static int serio_connect_driver(struct serio *serio, struct serio_driver *drv) | ||
| 72 | { | ||
| 73 | int retval; | ||
| 74 | |||
| 75 | down(&serio->drv_sem); | ||
| 76 | retval = drv->connect(serio, drv); | ||
| 77 | up(&serio->drv_sem); | ||
| 78 | |||
| 79 | return retval; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int serio_reconnect_driver(struct serio *serio) | ||
| 83 | { | ||
| 84 | int retval = -1; | ||
| 85 | |||
| 86 | down(&serio->drv_sem); | ||
| 87 | if (serio->drv && serio->drv->reconnect) | ||
| 88 | retval = serio->drv->reconnect(serio); | ||
| 89 | up(&serio->drv_sem); | ||
| 90 | |||
| 91 | return retval; | ||
| 92 | } | ||
| 93 | |||
| 94 | static void serio_disconnect_driver(struct serio *serio) | ||
| 95 | { | ||
| 96 | down(&serio->drv_sem); | ||
| 97 | if (serio->drv) | ||
| 98 | serio->drv->disconnect(serio); | ||
| 99 | up(&serio->drv_sem); | ||
| 100 | } | ||
| 101 | |||
| 71 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) | 102 | static int serio_match_port(const struct serio_device_id *ids, struct serio *serio) |
| 72 | { | 103 | { |
| 73 | while (ids->type || ids->proto) { | 104 | while (ids->type || ids->proto) { |
| @@ -91,7 +122,7 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv) | |||
| 91 | 122 | ||
| 92 | if (serio_match_port(drv->id_table, serio)) { | 123 | if (serio_match_port(drv->id_table, serio)) { |
| 93 | serio->dev.driver = &drv->driver; | 124 | serio->dev.driver = &drv->driver; |
| 94 | if (drv->connect(serio, drv)) { | 125 | if (serio_connect_driver(serio, drv)) { |
| 95 | serio->dev.driver = NULL; | 126 | serio->dev.driver = NULL; |
| 96 | goto out; | 127 | goto out; |
| 97 | } | 128 | } |
| @@ -138,8 +169,7 @@ struct serio_event { | |||
| 138 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ | 169 | static DEFINE_SPINLOCK(serio_event_lock); /* protects serio_event_list */ |
| 139 | static LIST_HEAD(serio_event_list); | 170 | static LIST_HEAD(serio_event_list); |
| 140 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); | 171 | static DECLARE_WAIT_QUEUE_HEAD(serio_wait); |
| 141 | static DECLARE_COMPLETION(serio_exited); | 172 | static struct task_struct *serio_task; |
| 142 | static int serio_pid; | ||
| 143 | 173 | ||
| 144 | static void serio_queue_event(void *object, struct module *owner, | 174 | static void serio_queue_event(void *object, struct module *owner, |
| 145 | enum serio_event_type event_type) | 175 | enum serio_event_type event_type) |
| @@ -150,12 +180,12 @@ static void serio_queue_event(void *object, struct module *owner, | |||
| 150 | spin_lock_irqsave(&serio_event_lock, flags); | 180 | spin_lock_irqsave(&serio_event_lock, flags); |
| 151 | 181 | ||
| 152 | /* | 182 | /* |
| 153 | * Scan event list for the other events for the same serio port, | 183 | * Scan event list for the other events for the same serio port, |
| 154 | * starting with the most recent one. If event is the same we | 184 | * starting with the most recent one. If event is the same we |
| 155 | * do not need add new one. If event is of different type we | 185 | * do not need add new one. If event is of different type we |
| 156 | * need to add this event and should not look further because | 186 | * need to add this event and should not look further because |
| 157 | * we need to preseve sequence of distinct events. | 187 | * we need to preseve sequence of distinct events. |
| 158 | */ | 188 | */ |
| 159 | list_for_each_entry_reverse(event, &serio_event_list, node) { | 189 | list_for_each_entry_reverse(event, &serio_event_list, node) { |
| 160 | if (event->object == object) { | 190 | if (event->object == object) { |
| 161 | if (event->type == event_type) | 191 | if (event->type == event_type) |
| @@ -337,20 +367,15 @@ static struct serio *serio_get_pending_child(struct serio *parent) | |||
| 337 | 367 | ||
| 338 | static int serio_thread(void *nothing) | 368 | static int serio_thread(void *nothing) |
| 339 | { | 369 | { |
| 340 | lock_kernel(); | ||
| 341 | daemonize("kseriod"); | ||
| 342 | allow_signal(SIGTERM); | ||
| 343 | |||
| 344 | do { | 370 | do { |
| 345 | serio_handle_events(); | 371 | serio_handle_events(); |
| 346 | wait_event_interruptible(serio_wait, !list_empty(&serio_event_list)); | 372 | wait_event_interruptible(serio_wait, |
| 373 | kthread_should_stop() || !list_empty(&serio_event_list)); | ||
| 347 | try_to_freeze(PF_FREEZE); | 374 | try_to_freeze(PF_FREEZE); |
| 348 | } while (!signal_pending(current)); | 375 | } while (!kthread_should_stop()); |
| 349 | 376 | ||
| 350 | printk(KERN_DEBUG "serio: kseriod exiting\n"); | 377 | printk(KERN_DEBUG "serio: kseriod exiting\n"); |
| 351 | 378 | return 0; | |
| 352 | unlock_kernel(); | ||
| 353 | complete_and_exit(&serio_exited, 0); | ||
| 354 | } | 379 | } |
| 355 | 380 | ||
| 356 | 381 | ||
| @@ -557,7 +582,7 @@ static void serio_destroy_port(struct serio *serio) | |||
| 557 | static void serio_reconnect_port(struct serio *serio) | 582 | static void serio_reconnect_port(struct serio *serio) |
| 558 | { | 583 | { |
| 559 | do { | 584 | do { |
| 560 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 585 | if (serio_reconnect_driver(serio)) { |
| 561 | serio_disconnect_port(serio); | 586 | serio_disconnect_port(serio); |
| 562 | serio_find_driver(serio); | 587 | serio_find_driver(serio); |
| 563 | /* Ok, old children are now gone, we are done */ | 588 | /* Ok, old children are now gone, we are done */ |
| @@ -630,6 +655,19 @@ void serio_unregister_port(struct serio *serio) | |||
| 630 | } | 655 | } |
| 631 | 656 | ||
| 632 | /* | 657 | /* |
| 658 | * Safely unregisters child port if one is present. | ||
| 659 | */ | ||
| 660 | void serio_unregister_child_port(struct serio *serio) | ||
| 661 | { | ||
| 662 | down(&serio_sem); | ||
| 663 | if (serio->child) { | ||
| 664 | serio_disconnect_port(serio->child); | ||
| 665 | serio_destroy_port(serio->child); | ||
| 666 | } | ||
| 667 | up(&serio_sem); | ||
| 668 | } | ||
| 669 | |||
| 670 | /* | ||
| 633 | * Submits register request to kseriod for subsequent execution. | 671 | * Submits register request to kseriod for subsequent execution. |
| 634 | * Can be used when it is not obvious whether the serio_sem is | 672 | * Can be used when it is not obvious whether the serio_sem is |
| 635 | * taken or not and when delayed execution is feasible. | 673 | * taken or not and when delayed execution is feasible. |
| @@ -686,15 +724,14 @@ static int serio_driver_probe(struct device *dev) | |||
| 686 | struct serio *serio = to_serio_port(dev); | 724 | struct serio *serio = to_serio_port(dev); |
| 687 | struct serio_driver *drv = to_serio_driver(dev->driver); | 725 | struct serio_driver *drv = to_serio_driver(dev->driver); |
| 688 | 726 | ||
| 689 | return drv->connect(serio, drv); | 727 | return serio_connect_driver(serio, drv); |
| 690 | } | 728 | } |
| 691 | 729 | ||
| 692 | static int serio_driver_remove(struct device *dev) | 730 | static int serio_driver_remove(struct device *dev) |
| 693 | { | 731 | { |
| 694 | struct serio *serio = to_serio_port(dev); | 732 | struct serio *serio = to_serio_port(dev); |
| 695 | struct serio_driver *drv = to_serio_driver(dev->driver); | ||
| 696 | 733 | ||
| 697 | drv->disconnect(serio); | 734 | serio_disconnect_driver(serio); |
| 698 | return 0; | 735 | return 0; |
| 699 | } | 736 | } |
| 700 | 737 | ||
| @@ -730,11 +767,9 @@ start_over: | |||
| 730 | 767 | ||
| 731 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) | 768 | static void serio_set_drv(struct serio *serio, struct serio_driver *drv) |
| 732 | { | 769 | { |
| 733 | down(&serio->drv_sem); | ||
| 734 | serio_pause_rx(serio); | 770 | serio_pause_rx(serio); |
| 735 | serio->drv = drv; | 771 | serio->drv = drv; |
| 736 | serio_continue_rx(serio); | 772 | serio_continue_rx(serio); |
| 737 | up(&serio->drv_sem); | ||
| 738 | } | 773 | } |
| 739 | 774 | ||
| 740 | static int serio_bus_match(struct device *dev, struct device_driver *drv) | 775 | static int serio_bus_match(struct device *dev, struct device_driver *drv) |
| @@ -794,7 +829,7 @@ static int serio_resume(struct device *dev) | |||
| 794 | { | 829 | { |
| 795 | struct serio *serio = to_serio_port(dev); | 830 | struct serio *serio = to_serio_port(dev); |
| 796 | 831 | ||
| 797 | if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) { | 832 | if (serio_reconnect_driver(serio)) { |
| 798 | /* | 833 | /* |
| 799 | * Driver re-probing can take a while, so better let kseriod | 834 | * Driver re-probing can take a while, so better let kseriod |
| 800 | * deal with it. | 835 | * deal with it. |
| @@ -848,9 +883,10 @@ irqreturn_t serio_interrupt(struct serio *serio, | |||
| 848 | 883 | ||
| 849 | static int __init serio_init(void) | 884 | static int __init serio_init(void) |
| 850 | { | 885 | { |
| 851 | if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) { | 886 | serio_task = kthread_run(serio_thread, NULL, "kseriod"); |
| 887 | if (IS_ERR(serio_task)) { | ||
| 852 | printk(KERN_ERR "serio: Failed to start kseriod\n"); | 888 | printk(KERN_ERR "serio: Failed to start kseriod\n"); |
| 853 | return -1; | 889 | return PTR_ERR(serio_task); |
| 854 | } | 890 | } |
| 855 | 891 | ||
| 856 | serio_bus.dev_attrs = serio_device_attrs; | 892 | serio_bus.dev_attrs = serio_device_attrs; |
| @@ -866,8 +902,7 @@ static int __init serio_init(void) | |||
| 866 | static void __exit serio_exit(void) | 902 | static void __exit serio_exit(void) |
| 867 | { | 903 | { |
| 868 | bus_unregister(&serio_bus); | 904 | bus_unregister(&serio_bus); |
| 869 | kill_proc(serio_pid, SIGTERM, 1); | 905 | kthread_stop(serio_task); |
| 870 | wait_for_completion(&serio_exited); | ||
| 871 | } | 906 | } |
| 872 | 907 | ||
| 873 | module_init(serio_init); | 908 | module_init(serio_init); |
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 | } |
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index d28e7eab6f98..fcae574f3106 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
| @@ -190,6 +190,18 @@ config USB_MTOUCH | |||
| 190 | To compile this driver as a module, choose M here: the | 190 | To compile this driver as a module, choose M here: the |
| 191 | module will be called mtouchusb. | 191 | module will be called mtouchusb. |
| 192 | 192 | ||
| 193 | config USB_ITMTOUCH | ||
| 194 | tristate "ITM Touch USB Touchscreen Driver" | ||
| 195 | depends on USB && INPUT | ||
| 196 | ---help--- | ||
| 197 | Say Y here if you want to use a ITM Touch USB | ||
| 198 | Touchscreen controller. | ||
| 199 | |||
| 200 | This touchscreen is used in LG 1510SF monitors. | ||
| 201 | |||
| 202 | To compile this driver as a module, choose M here: the | ||
| 203 | module will be called itmtouch. | ||
| 204 | |||
| 193 | config USB_EGALAX | 205 | config USB_EGALAX |
| 194 | tristate "eGalax TouchKit USB Touchscreen Driver" | 206 | tristate "eGalax TouchKit USB Touchscreen Driver" |
| 195 | depends on USB && INPUT | 207 | depends on USB && INPUT |
diff --git a/drivers/usb/input/Makefile b/drivers/usb/input/Makefile index 6bcedd16b0a1..f0fd02e00d32 100644 --- a/drivers/usb/input/Makefile +++ b/drivers/usb/input/Makefile | |||
| @@ -33,6 +33,7 @@ obj-$(CONFIG_USB_KBD) += usbkbd.o | |||
| 33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o | 33 | obj-$(CONFIG_USB_KBTAB) += kbtab.o |
| 34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o | 34 | obj-$(CONFIG_USB_MOUSE) += usbmouse.o |
| 35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o | 35 | obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o |
| 36 | obj-$(CONFIG_USB_ITMTOUCH) += itmtouch.o | ||
| 36 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o | 37 | obj-$(CONFIG_USB_EGALAX) += touchkitusb.o |
| 37 | obj-$(CONFIG_USB_POWERMATE) += powermate.o | 38 | obj-$(CONFIG_USB_POWERMATE) += powermate.o |
| 38 | obj-$(CONFIG_USB_WACOM) += wacom.o | 39 | obj-$(CONFIG_USB_WACOM) += wacom.o |
diff --git a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c index 94ce2a9ad50f..a6921856a112 100644 --- a/drivers/usb/input/aiptek.c +++ b/drivers/usb/input/aiptek.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Native support for the Aiptek HyperPen USB Tablets | 2 | * Native support for the Aiptek HyperPen USB Tablets |
| 3 | * (4000U/5000U/6000U/8000U/12000U) | 3 | * (4000U/5000U/6000U/8000U/12000U) |
| 4 | * | 4 | * |
| 5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> | 5 | * Copyright (c) 2001 Chris Atenasio <chris@crud.net> |
| 6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> | 6 | * Copyright (c) 2002-2004 Bryan W. Headley <bwheadley@earthlink.net> |
| 7 | * | 7 | * |
| @@ -31,7 +31,7 @@ | |||
| 31 | * - Added support for the sysfs interface, deprecating the | 31 | * - Added support for the sysfs interface, deprecating the |
| 32 | * procfs interface for 2.5.x kernel. Also added support for | 32 | * procfs interface for 2.5.x kernel. Also added support for |
| 33 | * Wheel command. Bryan W. Headley July-15-2003. | 33 | * Wheel command. Bryan W. Headley July-15-2003. |
| 34 | * v1.2 - Reworked jitter timer as a kernel thread. | 34 | * v1.2 - Reworked jitter timer as a kernel thread. |
| 35 | * Bryan W. Headley November-28-2003/Jan-10-2004. | 35 | * Bryan W. Headley November-28-2003/Jan-10-2004. |
| 36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor | 36 | * v1.3 - Repaired issue of kernel thread going nuts on single-processor |
| 37 | * machines, introduced programmableDelay as a command line | 37 | * machines, introduced programmableDelay as a command line |
| @@ -49,10 +49,10 @@ | |||
| 49 | * NOTE: | 49 | * NOTE: |
| 50 | * This kernel driver is augmented by the "Aiptek" XFree86 input | 50 | * This kernel driver is augmented by the "Aiptek" XFree86 input |
| 51 | * driver for your X server, as well as the Gaiptek GUI Front-end | 51 | * driver for your X server, as well as the Gaiptek GUI Front-end |
| 52 | * "Tablet Manager". | 52 | * "Tablet Manager". |
| 53 | * These three products are highly interactive with one another, | 53 | * These three products are highly interactive with one another, |
| 54 | * so therefore it's easier to document them all as one subsystem. | 54 | * so therefore it's easier to document them all as one subsystem. |
| 55 | * Please visit the project's "home page", located at, | 55 | * Please visit the project's "home page", located at, |
| 56 | * http://aiptektablet.sourceforge.net. | 56 | * http://aiptektablet.sourceforge.net. |
| 57 | * | 57 | * |
| 58 | * This program is free software; you can redistribute it and/or modify | 58 | * This program is free software; you can redistribute it and/or modify |
| @@ -156,7 +156,7 @@ | |||
| 156 | * Command/Data Description Return Bytes Return Value | 156 | * Command/Data Description Return Bytes Return Value |
| 157 | * 0x10/0x00 SwitchToMouse 0 | 157 | * 0x10/0x00 SwitchToMouse 0 |
| 158 | * 0x10/0x01 SwitchToTablet 0 | 158 | * 0x10/0x01 SwitchToTablet 0 |
| 159 | * 0x18/0x04 SetResolution 0 | 159 | * 0x18/0x04 SetResolution 0 |
| 160 | * 0x12/0xFF AutoGainOn 0 | 160 | * 0x12/0xFF AutoGainOn 0 |
| 161 | * 0x17/0x00 FilterOn 0 | 161 | * 0x17/0x00 FilterOn 0 |
| 162 | * 0x01/0x00 GetXExtension 2 MaxX | 162 | * 0x01/0x00 GetXExtension 2 MaxX |
| @@ -247,7 +247,7 @@ | |||
| 247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 | 247 | #define AIPTEK_DIAGNOSTIC_SENDING_ABSOLUTE_IN_RELATIVE 2 |
| 248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 | 248 | #define AIPTEK_DIAGNOSTIC_TOOL_DISALLOWED 3 |
| 249 | 249 | ||
| 250 | /* Time to wait (in ms) to help mask hand jittering | 250 | /* Time to wait (in ms) to help mask hand jittering |
| 251 | * when pressing the stylus buttons. | 251 | * when pressing the stylus buttons. |
| 252 | */ | 252 | */ |
| 253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 | 253 | #define AIPTEK_JITTER_DELAY_DEFAULT 50 |
| @@ -324,7 +324,6 @@ struct aiptek { | |||
| 324 | struct aiptek_settings curSetting; /* tablet's current programmable */ | 324 | struct aiptek_settings curSetting; /* tablet's current programmable */ |
| 325 | struct aiptek_settings newSetting; /* ... and new param settings */ | 325 | struct aiptek_settings newSetting; /* ... and new param settings */ |
| 326 | unsigned int ifnum; /* interface number for IO */ | 326 | unsigned int ifnum; /* interface number for IO */ |
| 327 | int openCount; /* module use counter */ | ||
| 328 | int diagnostic; /* tablet diagnostic codes */ | 327 | int diagnostic; /* tablet diagnostic codes */ |
| 329 | unsigned long eventCount; /* event count */ | 328 | unsigned long eventCount; /* event count */ |
| 330 | int inDelay; /* jitter: in jitter delay? */ | 329 | int inDelay; /* jitter: in jitter delay? */ |
| @@ -791,7 +790,7 @@ exit: | |||
| 791 | * specific Aiptek model numbers, because there has been overlaps, | 790 | * specific Aiptek model numbers, because there has been overlaps, |
| 792 | * use, and reuse of id's in existing models. Certain models have | 791 | * use, and reuse of id's in existing models. Certain models have |
| 793 | * been known to use more than one ID, indicative perhaps of | 792 | * been known to use more than one ID, indicative perhaps of |
| 794 | * manufacturing revisions. In any event, we consider these | 793 | * manufacturing revisions. In any event, we consider these |
| 795 | * IDs to not be model-specific nor unique. | 794 | * IDs to not be model-specific nor unique. |
| 796 | */ | 795 | */ |
| 797 | static const struct usb_device_id aiptek_ids[] = { | 796 | static const struct usb_device_id aiptek_ids[] = { |
| @@ -814,15 +813,9 @@ static int aiptek_open(struct input_dev *inputdev) | |||
| 814 | { | 813 | { |
| 815 | struct aiptek *aiptek = inputdev->private; | 814 | struct aiptek *aiptek = inputdev->private; |
| 816 | 815 | ||
| 817 | if (aiptek->openCount++ > 0) { | ||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | |||
| 821 | aiptek->urb->dev = aiptek->usbdev; | 816 | aiptek->urb->dev = aiptek->usbdev; |
| 822 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) { | 817 | if (usb_submit_urb(aiptek->urb, GFP_KERNEL) != 0) |
| 823 | aiptek->openCount--; | ||
| 824 | return -EIO; | 818 | return -EIO; |
| 825 | } | ||
| 826 | 819 | ||
| 827 | return 0; | 820 | return 0; |
| 828 | } | 821 | } |
| @@ -834,13 +827,11 @@ static void aiptek_close(struct input_dev *inputdev) | |||
| 834 | { | 827 | { |
| 835 | struct aiptek *aiptek = inputdev->private; | 828 | struct aiptek *aiptek = inputdev->private; |
| 836 | 829 | ||
| 837 | if (--aiptek->openCount == 0) { | 830 | usb_kill_urb(aiptek->urb); |
| 838 | usb_kill_urb(aiptek->urb); | ||
| 839 | } | ||
| 840 | } | 831 | } |
| 841 | 832 | ||
| 842 | /*********************************************************************** | 833 | /*********************************************************************** |
| 843 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, | 834 | * aiptek_set_report and aiptek_get_report() are borrowed from Linux 2.4.x, |
| 844 | * where they were known as usb_set_report and usb_get_report. | 835 | * where they were known as usb_set_report and usb_get_report. |
| 845 | */ | 836 | */ |
| 846 | static int | 837 | static int |
| @@ -2252,7 +2243,6 @@ static void aiptek_disconnect(struct usb_interface *intf) | |||
| 2252 | AIPTEK_PACKET_LENGTH, | 2243 | AIPTEK_PACKET_LENGTH, |
| 2253 | aiptek->data, aiptek->data_dma); | 2244 | aiptek->data, aiptek->data_dma); |
| 2254 | kfree(aiptek); | 2245 | kfree(aiptek); |
| 2255 | aiptek = NULL; | ||
| 2256 | } | 2246 | } |
| 2257 | } | 2247 | } |
| 2258 | 2248 | ||
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 860df26323b1..db95c975952b 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
| @@ -1,15 +1,15 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * USB ATI Remote support | 2 | * USB ATI Remote support |
| 3 | * | 3 | * |
| 4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> | 4 | * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net> |
| 5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev | 5 | * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev |
| 6 | * | 6 | * |
| 7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including | 7 | * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including |
| 8 | * porting to the 2.6 kernel interfaces, along with other modification | 8 | * porting to the 2.6 kernel interfaces, along with other modification |
| 9 | * to better match the style of the existing usb/input drivers. However, the | 9 | * to better match the style of the existing usb/input drivers. However, the |
| 10 | * protocol and hardware handling is essentially unchanged from 2.1.1. | 10 | * protocol and hardware handling is essentially unchanged from 2.1.1. |
| 11 | * | 11 | * |
| 12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by | 12 | * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by |
| 13 | * Vojtech Pavlik. | 13 | * Vojtech Pavlik. |
| 14 | * | 14 | * |
| 15 | * Changes: | 15 | * Changes: |
| @@ -23,64 +23,64 @@ | |||
| 23 | * Added support for the "Lola" remote contributed by: | 23 | * Added support for the "Lola" remote contributed by: |
| 24 | * Seth Cohn <sethcohn@yahoo.com> | 24 | * Seth Cohn <sethcohn@yahoo.com> |
| 25 | * | 25 | * |
| 26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 26 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 27 | * | 27 | * |
| 28 | * This program is free software; you can redistribute it and/or modify | 28 | * This program is free software; you can redistribute it and/or modify |
| 29 | * it under the terms of the GNU General Public License as published by | 29 | * it under the terms of the GNU General Public License as published by |
| 30 | * the Free Software Foundation; either version 2 of the License, or | 30 | * the Free Software Foundation; either version 2 of the License, or |
| 31 | * (at your option) any later version. | 31 | * (at your option) any later version. |
| 32 | * | 32 | * |
| 33 | * This program is distributed in the hope that it will be useful, | 33 | * This program is distributed in the hope that it will be useful, |
| 34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 34 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 35 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 36 | * GNU General Public License for more details. | 36 | * GNU General Public License for more details. |
| 37 | * | 37 | * |
| 38 | * You should have received a copy of the GNU General Public License | 38 | * You should have received a copy of the GNU General Public License |
| 39 | * along with this program; if not, write to the Free Software | 39 | * along with this program; if not, write to the Free Software |
| 40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 40 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 41 | * | 41 | * |
| 42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * | 42 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 43 | * | 43 | * |
| 44 | * Hardware & software notes | 44 | * Hardware & software notes |
| 45 | * | 45 | * |
| 46 | * These remote controls are distributed by ATI as part of their | 46 | * These remote controls are distributed by ATI as part of their |
| 47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a | 47 | * "All-In-Wonder" video card packages. The receiver self-identifies as a |
| 48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". | 48 | * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". |
| 49 | * | 49 | * |
| 50 | * The "Lola" remote is available from X10. See: | 50 | * The "Lola" remote is available from X10. See: |
| 51 | * http://www.x10.com/products/lola_sg1.htm | 51 | * http://www.x10.com/products/lola_sg1.htm |
| 52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly | 52 | * The Lola is similar to the ATI remote but has no mouse support, and slightly |
| 53 | * different keys. | 53 | * different keys. |
| 54 | * | 54 | * |
| 55 | * It is possible to use multiple receivers and remotes on multiple computers | 55 | * It is possible to use multiple receivers and remotes on multiple computers |
| 56 | * simultaneously by configuring them to use specific channels. | 56 | * simultaneously by configuring them to use specific channels. |
| 57 | * | 57 | * |
| 58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. | 58 | * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. |
| 59 | * Actually, it may even support more, at least in some revisions of the | 59 | * Actually, it may even support more, at least in some revisions of the |
| 60 | * hardware. | 60 | * hardware. |
| 61 | * | 61 | * |
| 62 | * Each remote can be configured to transmit on one channel as follows: | 62 | * Each remote can be configured to transmit on one channel as follows: |
| 63 | * - Press and hold the "hand icon" button. | 63 | * - Press and hold the "hand icon" button. |
| 64 | * - When the red LED starts to blink, let go of the "hand icon" button. | 64 | * - When the red LED starts to blink, let go of the "hand icon" button. |
| 65 | * - When it stops blinking, input the channel code as two digits, from 01 | 65 | * - When it stops blinking, input the channel code as two digits, from 01 |
| 66 | * to 16, and press the hand icon again. | 66 | * to 16, and press the hand icon again. |
| 67 | * | 67 | * |
| 68 | * The timing can be a little tricky. Try loading the module with debug=1 | 68 | * The timing can be a little tricky. Try loading the module with debug=1 |
| 69 | * to have the kernel print out messages about the remote control number | 69 | * to have the kernel print out messages about the remote control number |
| 70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. | 70 | * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. |
| 71 | * | 71 | * |
| 72 | * The driver has a "channel_mask" parameter. This bitmask specifies which | 72 | * The driver has a "channel_mask" parameter. This bitmask specifies which |
| 73 | * channels will be ignored by the module. To mask out channels, just add | 73 | * channels will be ignored by the module. To mask out channels, just add |
| 74 | * all the 2^channel_number values together. | 74 | * all the 2^channel_number values together. |
| 75 | * | 75 | * |
| 76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote | 76 | * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote |
| 77 | * ignore signals coming from remote controls transmitting on channel 4, but | 77 | * ignore signals coming from remote controls transmitting on channel 4, but |
| 78 | * accept all other channels. | 78 | * accept all other channels. |
| 79 | * | 79 | * |
| 80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be | 80 | * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be |
| 81 | * ignored. | 81 | * ignored. |
| 82 | * | 82 | * |
| 83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this | 83 | * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this |
| 84 | * parameter are unused. | 84 | * parameter are unused. |
| 85 | * | 85 | * |
| 86 | */ | 86 | */ |
| @@ -99,13 +99,13 @@ | |||
| 99 | /* | 99 | /* |
| 100 | * Module and Version Information, Module Parameters | 100 | * Module and Version Information, Module Parameters |
| 101 | */ | 101 | */ |
| 102 | 102 | ||
| 103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | 103 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 |
| 104 | #define ATI_REMOTE_PRODUCT_ID 0x004 | 104 | #define ATI_REMOTE_PRODUCT_ID 0x004 |
| 105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | 105 | #define LOLA_REMOTE_PRODUCT_ID 0x002 |
| 106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | 106 | #define MEDION_REMOTE_PRODUCT_ID 0x006 |
| 107 | 107 | ||
| 108 | #define DRIVER_VERSION "2.2.1" | 108 | #define DRIVER_VERSION "2.2.1" |
| 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" |
| 110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" | 110 | #define DRIVER_DESC "ATI/X10 RF USB Remote Control" |
| 111 | 111 | ||
| @@ -113,18 +113,18 @@ | |||
| 113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | 113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ |
| 114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ | 114 | #define ATI_INPUTNUM 1 /* Which input device to register as */ |
| 115 | 115 | ||
| 116 | static unsigned long channel_mask = 0; | 116 | static unsigned long channel_mask; |
| 117 | module_param(channel_mask, ulong, 0444); | 117 | module_param(channel_mask, ulong, 0444); |
| 118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | 118 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); |
| 119 | 119 | ||
| 120 | static int debug = 0; | 120 | static int debug; |
| 121 | module_param(debug, int, 0444); | 121 | module_param(debug, int, 0444); |
| 122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | 122 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); |
| 123 | 123 | ||
| 124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | 124 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) |
| 125 | #undef err | 125 | #undef err |
| 126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 126 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
| 127 | 127 | ||
| 128 | static struct usb_device_id ati_remote_table[] = { | 128 | static struct usb_device_id ati_remote_table[] = { |
| 129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | 129 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, |
| 130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | 130 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, |
| @@ -148,7 +148,7 @@ static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | |||
| 148 | /* Acceleration curve for directional control pad */ | 148 | /* Acceleration curve for directional control pad */ |
| 149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | 149 | static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; |
| 150 | 150 | ||
| 151 | /* Duplicate event filtering time. | 151 | /* Duplicate event filtering time. |
| 152 | * Sequential, identical KIND_FILTERED inputs with less than | 152 | * Sequential, identical KIND_FILTERED inputs with less than |
| 153 | * FILTER_TIME jiffies between them are considered as repeat | 153 | * FILTER_TIME jiffies between them are considered as repeat |
| 154 | * events. The hardware generates 5 events for the first keypress | 154 | * events. The hardware generates 5 events for the first keypress |
| @@ -161,10 +161,10 @@ static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | |||
| 161 | static DECLARE_MUTEX(disconnect_sem); | 161 | static DECLARE_MUTEX(disconnect_sem); |
| 162 | 162 | ||
| 163 | struct ati_remote { | 163 | struct ati_remote { |
| 164 | struct input_dev idev; | 164 | struct input_dev idev; |
| 165 | struct usb_device *udev; | 165 | struct usb_device *udev; |
| 166 | struct usb_interface *interface; | 166 | struct usb_interface *interface; |
| 167 | 167 | ||
| 168 | struct urb *irq_urb; | 168 | struct urb *irq_urb; |
| 169 | struct urb *out_urb; | 169 | struct urb *out_urb; |
| 170 | struct usb_endpoint_descriptor *endpoint_in; | 170 | struct usb_endpoint_descriptor *endpoint_in; |
| @@ -174,13 +174,11 @@ struct ati_remote { | |||
| 174 | dma_addr_t inbuf_dma; | 174 | dma_addr_t inbuf_dma; |
| 175 | dma_addr_t outbuf_dma; | 175 | dma_addr_t outbuf_dma; |
| 176 | 176 | ||
| 177 | int open; /* open counter */ | ||
| 178 | |||
| 179 | unsigned char old_data[2]; /* Detect duplicate events */ | 177 | unsigned char old_data[2]; /* Detect duplicate events */ |
| 180 | unsigned long old_jiffies; | 178 | unsigned long old_jiffies; |
| 181 | unsigned long acc_jiffies; /* handle acceleration */ | 179 | unsigned long acc_jiffies; /* handle acceleration */ |
| 182 | unsigned int repeat_count; | 180 | unsigned int repeat_count; |
| 183 | 181 | ||
| 184 | char name[NAME_BUFSIZE]; | 182 | char name[NAME_BUFSIZE]; |
| 185 | char phys[NAME_BUFSIZE]; | 183 | char phys[NAME_BUFSIZE]; |
| 186 | 184 | ||
| @@ -206,14 +204,14 @@ static struct | |||
| 206 | int type; | 204 | int type; |
| 207 | unsigned int code; | 205 | unsigned int code; |
| 208 | int value; | 206 | int value; |
| 209 | } ati_remote_tbl[] = | 207 | } ati_remote_tbl[] = |
| 210 | { | 208 | { |
| 211 | /* Directional control pad axes */ | 209 | /* Directional control pad axes */ |
| 212 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ | 210 | {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ |
| 213 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ | 211 | {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ |
| 214 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ | 212 | {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ |
| 215 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ | 213 | {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ |
| 216 | /* Directional control pad diagonals */ | 214 | /* Directional control pad diagonals */ |
| 217 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ | 215 | {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ |
| 218 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ | 216 | {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ |
| 219 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ | 217 | {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ |
| @@ -225,7 +223,7 @@ static struct | |||
| 225 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ | 223 | {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ |
| 226 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ | 224 | {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ |
| 227 | 225 | ||
| 228 | /* Artificial "doubleclick" events are generated by the hardware. | 226 | /* Artificial "doubleclick" events are generated by the hardware. |
| 229 | * They are mapped to the "side" and "extra" mouse buttons here. */ | 227 | * They are mapped to the "side" and "extra" mouse buttons here. */ |
| 230 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ | 228 | {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ |
| 231 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ | 229 | {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ |
| @@ -273,15 +271,15 @@ static struct | |||
| 273 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ | 271 | {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1}, /* ( >) */ |
| 274 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ | 272 | {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ |
| 275 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ | 273 | {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ |
| 276 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ | 274 | {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ |
| 277 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ | 275 | {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ |
| 278 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ | 276 | {KIND_FILTERED, 0xf0, 0x2b, EV_KEY, KEY_PREVIOUS, 1}, /* (<-) */ |
| 279 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ | 277 | {KIND_FILTERED, 0xef, 0x2a, EV_KEY, KEY_NEXT, 1}, /* (>+) */ |
| 280 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ | 278 | {KIND_FILTERED, 0xf2, 0x2D, EV_KEY, KEY_INFO, 1}, /* PLAYING */ |
| 281 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ | 279 | {KIND_FILTERED, 0xf3, 0x2E, EV_KEY, KEY_HOME, 1}, /* TOP */ |
| 282 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ | 280 | {KIND_FILTERED, 0xf4, 0x2F, EV_KEY, KEY_END, 1}, /* END */ |
| 283 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ | 281 | {KIND_FILTERED, 0xf5, 0x30, EV_KEY, KEY_SELECT, 1}, /* SELECT */ |
| 284 | 282 | ||
| 285 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} | 283 | {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} |
| 286 | }; | 284 | }; |
| 287 | 285 | ||
| @@ -315,7 +313,7 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
| 315 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) | 313 | if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) |
| 316 | warn("Weird byte 0x%02x", data[0]); | 314 | warn("Weird byte 0x%02x", data[0]); |
| 317 | else if (len == 4) | 315 | else if (len == 4) |
| 318 | warn("Weird key %02x %02x %02x %02x", | 316 | warn("Weird key %02x %02x %02x %02x", |
| 319 | data[0], data[1], data[2], data[3]); | 317 | data[0], data[1], data[2], data[3]); |
| 320 | else | 318 | else |
| 321 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", | 319 | warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...", |
| @@ -328,25 +326,16 @@ static void ati_remote_dump(unsigned char *data, unsigned int len) | |||
| 328 | static int ati_remote_open(struct input_dev *inputdev) | 326 | static int ati_remote_open(struct input_dev *inputdev) |
| 329 | { | 327 | { |
| 330 | struct ati_remote *ati_remote = inputdev->private; | 328 | struct ati_remote *ati_remote = inputdev->private; |
| 331 | int retval = 0; | ||
| 332 | |||
| 333 | down(&disconnect_sem); | ||
| 334 | |||
| 335 | if (ati_remote->open++) | ||
| 336 | goto exit; | ||
| 337 | 329 | ||
| 338 | /* On first open, submit the read urb which was set up previously. */ | 330 | /* On first open, submit the read urb which was set up previously. */ |
| 339 | ati_remote->irq_urb->dev = ati_remote->udev; | 331 | ati_remote->irq_urb->dev = ati_remote->udev; |
| 340 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { | 332 | if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { |
| 341 | dev_err(&ati_remote->interface->dev, | 333 | dev_err(&ati_remote->interface->dev, |
| 342 | "%s: usb_submit_urb failed!\n", __FUNCTION__); | 334 | "%s: usb_submit_urb failed!\n", __FUNCTION__); |
| 343 | ati_remote->open--; | 335 | return -EIO; |
| 344 | retval = -EIO; | ||
| 345 | } | 336 | } |
| 346 | 337 | ||
| 347 | exit: | 338 | return 0; |
| 348 | up(&disconnect_sem); | ||
| 349 | return retval; | ||
| 350 | } | 339 | } |
| 351 | 340 | ||
| 352 | /* | 341 | /* |
| @@ -355,9 +344,8 @@ exit: | |||
| 355 | static void ati_remote_close(struct input_dev *inputdev) | 344 | static void ati_remote_close(struct input_dev *inputdev) |
| 356 | { | 345 | { |
| 357 | struct ati_remote *ati_remote = inputdev->private; | 346 | struct ati_remote *ati_remote = inputdev->private; |
| 358 | 347 | ||
| 359 | if (!--ati_remote->open) | 348 | usb_kill_urb(ati_remote->irq_urb); |
| 360 | usb_kill_urb(ati_remote->irq_urb); | ||
| 361 | } | 349 | } |
| 362 | 350 | ||
| 363 | /* | 351 | /* |
| @@ -366,13 +354,13 @@ static void ati_remote_close(struct input_dev *inputdev) | |||
| 366 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | 354 | static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) |
| 367 | { | 355 | { |
| 368 | struct ati_remote *ati_remote = urb->context; | 356 | struct ati_remote *ati_remote = urb->context; |
| 369 | 357 | ||
| 370 | if (urb->status) { | 358 | if (urb->status) { |
| 371 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", | 359 | dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", |
| 372 | __FUNCTION__, urb->status); | 360 | __FUNCTION__, urb->status); |
| 373 | return; | 361 | return; |
| 374 | } | 362 | } |
| 375 | 363 | ||
| 376 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; | 364 | ati_remote->send_flags |= SEND_FLAG_COMPLETE; |
| 377 | wmb(); | 365 | wmb(); |
| 378 | wake_up(&ati_remote->wait); | 366 | wake_up(&ati_remote->wait); |
| @@ -380,16 +368,16 @@ static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) | |||
| 380 | 368 | ||
| 381 | /* | 369 | /* |
| 382 | * ati_remote_sendpacket | 370 | * ati_remote_sendpacket |
| 383 | * | 371 | * |
| 384 | * Used to send device initialization strings | 372 | * Used to send device initialization strings |
| 385 | */ | 373 | */ |
| 386 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) | 374 | static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) |
| 387 | { | 375 | { |
| 388 | int retval = 0; | 376 | int retval = 0; |
| 389 | 377 | ||
| 390 | /* Set up out_urb */ | 378 | /* Set up out_urb */ |
| 391 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); | 379 | memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); |
| 392 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); | 380 | ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); |
| 393 | 381 | ||
| 394 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; | 382 | ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; |
| 395 | ati_remote->out_urb->dev = ati_remote->udev; | 383 | ati_remote->out_urb->dev = ati_remote->udev; |
| @@ -397,17 +385,17 @@ static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigne | |||
| 397 | 385 | ||
| 398 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); | 386 | retval = usb_submit_urb(ati_remote->out_urb, GFP_ATOMIC); |
| 399 | if (retval) { | 387 | if (retval) { |
| 400 | dev_dbg(&ati_remote->interface->dev, | 388 | dev_dbg(&ati_remote->interface->dev, |
| 401 | "sendpacket: usb_submit_urb failed: %d\n", retval); | 389 | "sendpacket: usb_submit_urb failed: %d\n", retval); |
| 402 | return retval; | 390 | return retval; |
| 403 | } | 391 | } |
| 404 | 392 | ||
| 405 | wait_event_timeout(ati_remote->wait, | 393 | wait_event_timeout(ati_remote->wait, |
| 406 | ((ati_remote->out_urb->status != -EINPROGRESS) || | 394 | ((ati_remote->out_urb->status != -EINPROGRESS) || |
| 407 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), | 395 | (ati_remote->send_flags & SEND_FLAG_COMPLETE)), |
| 408 | HZ); | 396 | HZ); |
| 409 | usb_kill_urb(ati_remote->out_urb); | 397 | usb_kill_urb(ati_remote->out_urb); |
| 410 | 398 | ||
| 411 | return retval; | 399 | return retval; |
| 412 | } | 400 | } |
| 413 | 401 | ||
| @@ -419,15 +407,15 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
| 419 | int i; | 407 | int i; |
| 420 | 408 | ||
| 421 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { | 409 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { |
| 422 | /* | 410 | /* |
| 423 | * Decide if the table entry matches the remote input. | 411 | * Decide if the table entry matches the remote input. |
| 424 | */ | 412 | */ |
| 425 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && | 413 | if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && |
| 426 | ((((ati_remote_tbl[i].data1 >> 4) - | 414 | ((((ati_remote_tbl[i].data1 >> 4) - |
| 427 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && | 415 | (d1 >> 4) + rem) & 0x0f) == 0x0f) && |
| 428 | (ati_remote_tbl[i].data2 == d2)) | 416 | (ati_remote_tbl[i].data2 == d2)) |
| 429 | return i; | 417 | return i; |
| 430 | 418 | ||
| 431 | } | 419 | } |
| 432 | return -1; | 420 | return -1; |
| 433 | } | 421 | } |
| @@ -435,16 +423,16 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
| 435 | /* | 423 | /* |
| 436 | * ati_remote_report_input | 424 | * ati_remote_report_input |
| 437 | */ | 425 | */ |
| 438 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | 426 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) |
| 439 | { | 427 | { |
| 440 | struct ati_remote *ati_remote = urb->context; | 428 | struct ati_remote *ati_remote = urb->context; |
| 441 | unsigned char *data= ati_remote->inbuf; | 429 | unsigned char *data= ati_remote->inbuf; |
| 442 | struct input_dev *dev = &ati_remote->idev; | 430 | struct input_dev *dev = &ati_remote->idev; |
| 443 | int index, acc; | 431 | int index, acc; |
| 444 | int remote_num; | 432 | int remote_num; |
| 445 | 433 | ||
| 446 | /* Deal with strange looking inputs */ | 434 | /* Deal with strange looking inputs */ |
| 447 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || | 435 | if ( (urb->actual_length != 4) || (data[0] != 0x14) || |
| 448 | ((data[3] & 0x0f) != 0x00) ) { | 436 | ((data[3] & 0x0f) != 0x00) ) { |
| 449 | ati_remote_dump(data, urb->actual_length); | 437 | ati_remote_dump(data, urb->actual_length); |
| 450 | return; | 438 | return; |
| @@ -453,7 +441,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
| 453 | /* Mask unwanted remote channels. */ | 441 | /* Mask unwanted remote channels. */ |
| 454 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ | 442 | /* note: remote_num is 0-based, channel 1 on remote == 0 here */ |
| 455 | remote_num = (data[3] >> 4) & 0x0f; | 443 | remote_num = (data[3] >> 4) & 0x0f; |
| 456 | if (channel_mask & (1 << (remote_num + 1))) { | 444 | if (channel_mask & (1 << (remote_num + 1))) { |
| 457 | dbginfo(&ati_remote->interface->dev, | 445 | dbginfo(&ati_remote->interface->dev, |
| 458 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", | 446 | "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", |
| 459 | remote_num, data[1], data[2], channel_mask); | 447 | remote_num, data[1], data[2], channel_mask); |
| @@ -463,37 +451,36 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
| 463 | /* Look up event code index in translation table */ | 451 | /* Look up event code index in translation table */ |
| 464 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); | 452 | index = ati_remote_event_lookup(remote_num, data[1], data[2]); |
| 465 | if (index < 0) { | 453 | if (index < 0) { |
| 466 | dev_warn(&ati_remote->interface->dev, | 454 | dev_warn(&ati_remote->interface->dev, |
| 467 | "Unknown input from channel 0x%02x: data %02x,%02x\n", | 455 | "Unknown input from channel 0x%02x: data %02x,%02x\n", |
| 468 | remote_num, data[1], data[2]); | 456 | remote_num, data[1], data[2]); |
| 469 | return; | 457 | return; |
| 470 | } | 458 | } |
| 471 | dbginfo(&ati_remote->interface->dev, | 459 | dbginfo(&ati_remote->interface->dev, |
| 472 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", | 460 | "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", |
| 473 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); | 461 | remote_num, data[1], data[2], index, ati_remote_tbl[index].code); |
| 474 | 462 | ||
| 475 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { | 463 | if (ati_remote_tbl[index].kind == KIND_LITERAL) { |
| 476 | input_regs(dev, regs); | 464 | input_regs(dev, regs); |
| 477 | input_event(dev, ati_remote_tbl[index].type, | 465 | input_event(dev, ati_remote_tbl[index].type, |
| 478 | ati_remote_tbl[index].code, | 466 | ati_remote_tbl[index].code, |
| 479 | ati_remote_tbl[index].value); | 467 | ati_remote_tbl[index].value); |
| 480 | input_sync(dev); | 468 | input_sync(dev); |
| 481 | 469 | ||
| 482 | ati_remote->old_jiffies = jiffies; | 470 | ati_remote->old_jiffies = jiffies; |
| 483 | return; | 471 | return; |
| 484 | } | 472 | } |
| 485 | 473 | ||
| 486 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | 474 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { |
| 487 | /* Filter duplicate events which happen "too close" together. */ | 475 | /* Filter duplicate events which happen "too close" together. */ |
| 488 | if ((ati_remote->old_data[0] == data[1]) && | 476 | if ((ati_remote->old_data[0] == data[1]) && |
| 489 | (ati_remote->old_data[1] == data[2]) && | 477 | (ati_remote->old_data[1] == data[2]) && |
| 490 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { | 478 | ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { |
| 491 | ati_remote->repeat_count++; | 479 | ati_remote->repeat_count++; |
| 492 | } | 480 | } else { |
| 493 | else { | ||
| 494 | ati_remote->repeat_count = 0; | 481 | ati_remote->repeat_count = 0; |
| 495 | } | 482 | } |
| 496 | 483 | ||
| 497 | ati_remote->old_data[0] = data[1]; | 484 | ati_remote->old_data[0] = data[1]; |
| 498 | ati_remote->old_data[1] = data[2]; | 485 | ati_remote->old_data[1] = data[2]; |
| 499 | ati_remote->old_jiffies = jiffies; | 486 | ati_remote->old_jiffies = jiffies; |
| @@ -501,7 +488,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
| 501 | if ((ati_remote->repeat_count > 0) | 488 | if ((ati_remote->repeat_count > 0) |
| 502 | && (ati_remote->repeat_count < 5)) | 489 | && (ati_remote->repeat_count < 5)) |
| 503 | return; | 490 | return; |
| 504 | 491 | ||
| 505 | 492 | ||
| 506 | input_regs(dev, regs); | 493 | input_regs(dev, regs); |
| 507 | input_event(dev, ati_remote_tbl[index].type, | 494 | input_event(dev, ati_remote_tbl[index].type, |
| @@ -511,13 +498,13 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
| 511 | input_sync(dev); | 498 | input_sync(dev); |
| 512 | 499 | ||
| 513 | return; | 500 | return; |
| 514 | } | 501 | } |
| 515 | 502 | ||
| 516 | /* | 503 | /* |
| 517 | * Other event kinds are from the directional control pad, and have an | 504 | * Other event kinds are from the directional control pad, and have an |
| 518 | * acceleration factor applied to them. Without this acceleration, the | 505 | * acceleration factor applied to them. Without this acceleration, the |
| 519 | * control pad is mostly unusable. | 506 | * control pad is mostly unusable. |
| 520 | * | 507 | * |
| 521 | * If elapsed time since last event is > 1/4 second, user "stopped", | 508 | * If elapsed time since last event is > 1/4 second, user "stopped", |
| 522 | * so reset acceleration. Otherwise, user is probably holding the control | 509 | * so reset acceleration. Otherwise, user is probably holding the control |
| 523 | * pad down, so we increase acceleration, ramping up over two seconds to | 510 | * pad down, so we increase acceleration, ramping up over two seconds to |
| @@ -559,7 +546,7 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
| 559 | input_report_rel(dev, REL_Y, acc); | 546 | input_report_rel(dev, REL_Y, acc); |
| 560 | break; | 547 | break; |
| 561 | default: | 548 | default: |
| 562 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | 549 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", |
| 563 | ati_remote_tbl[index].kind); | 550 | ati_remote_tbl[index].kind); |
| 564 | } | 551 | } |
| 565 | input_sync(dev); | 552 | input_sync(dev); |
| @@ -586,12 +573,12 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
| 586 | case -ESHUTDOWN: | 573 | case -ESHUTDOWN: |
| 587 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", | 574 | dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", |
| 588 | __FUNCTION__); | 575 | __FUNCTION__); |
| 589 | return; | 576 | return; |
| 590 | default: /* error */ | 577 | default: /* error */ |
| 591 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", | 578 | dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", |
| 592 | __FUNCTION__, urb->status); | 579 | __FUNCTION__, urb->status); |
| 593 | } | 580 | } |
| 594 | 581 | ||
| 595 | retval = usb_submit_urb(urb, SLAB_ATOMIC); | 582 | retval = usb_submit_urb(urb, SLAB_ATOMIC); |
| 596 | if (retval) | 583 | if (retval) |
| 597 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", | 584 | dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", |
| @@ -603,8 +590,6 @@ static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) | |||
| 603 | */ | 590 | */ |
| 604 | static void ati_remote_delete(struct ati_remote *ati_remote) | 591 | static void ati_remote_delete(struct ati_remote *ati_remote) |
| 605 | { | 592 | { |
| 606 | if (!ati_remote) return; | ||
| 607 | |||
| 608 | if (ati_remote->irq_urb) | 593 | if (ati_remote->irq_urb) |
| 609 | usb_kill_urb(ati_remote->irq_urb); | 594 | usb_kill_urb(ati_remote->irq_urb); |
| 610 | 595 | ||
| @@ -614,16 +599,16 @@ static void ati_remote_delete(struct ati_remote *ati_remote) | |||
| 614 | input_unregister_device(&ati_remote->idev); | 599 | input_unregister_device(&ati_remote->idev); |
| 615 | 600 | ||
| 616 | if (ati_remote->inbuf) | 601 | if (ati_remote->inbuf) |
| 617 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 602 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
| 618 | ati_remote->inbuf, ati_remote->inbuf_dma); | 603 | ati_remote->inbuf, ati_remote->inbuf_dma); |
| 619 | 604 | ||
| 620 | if (ati_remote->outbuf) | 605 | if (ati_remote->outbuf) |
| 621 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, | 606 | usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, |
| 622 | ati_remote->outbuf, ati_remote->outbuf_dma); | 607 | ati_remote->outbuf, ati_remote->outbuf_dma); |
| 623 | 608 | ||
| 624 | if (ati_remote->irq_urb) | 609 | if (ati_remote->irq_urb) |
| 625 | usb_free_urb(ati_remote->irq_urb); | 610 | usb_free_urb(ati_remote->irq_urb); |
| 626 | 611 | ||
| 627 | if (ati_remote->out_urb) | 612 | if (ati_remote->out_urb) |
| 628 | usb_free_urb(ati_remote->out_urb); | 613 | usb_free_urb(ati_remote->out_urb); |
| 629 | 614 | ||
| @@ -636,21 +621,21 @@ static void ati_remote_input_init(struct ati_remote *ati_remote) | |||
| 636 | int i; | 621 | int i; |
| 637 | 622 | ||
| 638 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); | 623 | idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); |
| 639 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | | 624 | idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | |
| 640 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); | 625 | BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); |
| 641 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); | 626 | idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); |
| 642 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) | 627 | for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) |
| 643 | if (ati_remote_tbl[i].type == EV_KEY) | 628 | if (ati_remote_tbl[i].type == EV_KEY) |
| 644 | set_bit(ati_remote_tbl[i].code, idev->keybit); | 629 | set_bit(ati_remote_tbl[i].code, idev->keybit); |
| 645 | 630 | ||
| 646 | idev->private = ati_remote; | 631 | idev->private = ati_remote; |
| 647 | idev->open = ati_remote_open; | 632 | idev->open = ati_remote_open; |
| 648 | idev->close = ati_remote_close; | 633 | idev->close = ati_remote_close; |
| 649 | 634 | ||
| 650 | idev->name = ati_remote->name; | 635 | idev->name = ati_remote->name; |
| 651 | idev->phys = ati_remote->phys; | 636 | idev->phys = ati_remote->phys; |
| 652 | 637 | ||
| 653 | idev->id.bustype = BUS_USB; | 638 | idev->id.bustype = BUS_USB; |
| 654 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); | 639 | idev->id.vendor = le16_to_cpu(ati_remote->udev->descriptor.idVendor); |
| 655 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); | 640 | idev->id.product = le16_to_cpu(ati_remote->udev->descriptor.idProduct); |
| 656 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); | 641 | idev->id.version = le16_to_cpu(ati_remote->udev->descriptor.bcdDevice); |
| @@ -660,27 +645,27 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
| 660 | { | 645 | { |
| 661 | struct usb_device *udev = ati_remote->udev; | 646 | struct usb_device *udev = ati_remote->udev; |
| 662 | int pipe, maxp; | 647 | int pipe, maxp; |
| 663 | 648 | ||
| 664 | init_waitqueue_head(&ati_remote->wait); | 649 | init_waitqueue_head(&ati_remote->wait); |
| 665 | 650 | ||
| 666 | /* Set up irq_urb */ | 651 | /* Set up irq_urb */ |
| 667 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); | 652 | pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); |
| 668 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 653 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
| 669 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 654 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
| 670 | 655 | ||
| 671 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, | 656 | usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, |
| 672 | maxp, ati_remote_irq_in, ati_remote, | 657 | maxp, ati_remote_irq_in, ati_remote, |
| 673 | ati_remote->endpoint_in->bInterval); | 658 | ati_remote->endpoint_in->bInterval); |
| 674 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; | 659 | ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; |
| 675 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 660 | ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 676 | 661 | ||
| 677 | /* Set up out_urb */ | 662 | /* Set up out_urb */ |
| 678 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); | 663 | pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); |
| 679 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 664 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
| 680 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; | 665 | maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; |
| 681 | 666 | ||
| 682 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, | 667 | usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, |
| 683 | maxp, ati_remote_irq_out, ati_remote, | 668 | maxp, ati_remote_irq_out, ati_remote, |
| 684 | ati_remote->endpoint_out->bInterval); | 669 | ati_remote->endpoint_out->bInterval); |
| 685 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; | 670 | ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; |
| 686 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 671 | ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| @@ -688,11 +673,11 @@ static int ati_remote_initialize(struct ati_remote *ati_remote) | |||
| 688 | /* send initialization strings */ | 673 | /* send initialization strings */ |
| 689 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || | 674 | if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || |
| 690 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { | 675 | (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { |
| 691 | dev_err(&ati_remote->interface->dev, | 676 | dev_err(&ati_remote->interface->dev, |
| 692 | "Initializing ati_remote hardware failed.\n"); | 677 | "Initializing ati_remote hardware failed.\n"); |
| 693 | return 1; | 678 | return 1; |
| 694 | } | 679 | } |
| 695 | 680 | ||
| 696 | return 0; | 681 | return 0; |
| 697 | } | 682 | } |
| 698 | 683 | ||
| @@ -769,7 +754,7 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
| 769 | 754 | ||
| 770 | if (!strlen(ati_remote->name)) | 755 | if (!strlen(ati_remote->name)) |
| 771 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", | 756 | sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", |
| 772 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), | 757 | le16_to_cpu(ati_remote->udev->descriptor.idVendor), |
| 773 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); | 758 | le16_to_cpu(ati_remote->udev->descriptor.idProduct)); |
| 774 | 759 | ||
| 775 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ | 760 | /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ |
| @@ -781,11 +766,11 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
| 781 | ati_remote_input_init(ati_remote); | 766 | ati_remote_input_init(ati_remote); |
| 782 | input_register_device(&ati_remote->idev); | 767 | input_register_device(&ati_remote->idev); |
| 783 | 768 | ||
| 784 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", | 769 | dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", |
| 785 | ati_remote->name, path); | 770 | ati_remote->name, path); |
| 786 | 771 | ||
| 787 | usb_set_intfdata(interface, ati_remote); | 772 | usb_set_intfdata(interface, ati_remote); |
| 788 | 773 | ||
| 789 | error: | 774 | error: |
| 790 | if (retval) | 775 | if (retval) |
| 791 | ati_remote_delete(ati_remote); | 776 | ati_remote_delete(ati_remote); |
| @@ -800,18 +785,14 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
| 800 | { | 785 | { |
| 801 | struct ati_remote *ati_remote; | 786 | struct ati_remote *ati_remote; |
| 802 | 787 | ||
| 803 | down(&disconnect_sem); | ||
| 804 | |||
| 805 | ati_remote = usb_get_intfdata(interface); | 788 | ati_remote = usb_get_intfdata(interface); |
| 806 | usb_set_intfdata(interface, NULL); | 789 | usb_set_intfdata(interface, NULL); |
| 807 | if (!ati_remote) { | 790 | if (!ati_remote) { |
| 808 | warn("%s - null device?\n", __FUNCTION__); | 791 | warn("%s - null device?\n", __FUNCTION__); |
| 809 | return; | 792 | return; |
| 810 | } | 793 | } |
| 811 | |||
| 812 | ati_remote_delete(ati_remote); | ||
| 813 | 794 | ||
| 814 | up(&disconnect_sem); | 795 | ati_remote_delete(ati_remote); |
| 815 | } | 796 | } |
| 816 | 797 | ||
| 817 | /* | 798 | /* |
| @@ -820,7 +801,7 @@ static void ati_remote_disconnect(struct usb_interface *interface) | |||
| 820 | static int __init ati_remote_init(void) | 801 | static int __init ati_remote_init(void) |
| 821 | { | 802 | { |
| 822 | int result; | 803 | int result; |
| 823 | 804 | ||
| 824 | result = usb_register(&ati_remote_driver); | 805 | result = usb_register(&ati_remote_driver); |
| 825 | if (result) | 806 | if (result) |
| 826 | err("usb_register error #%d\n", result); | 807 | err("usb_register error #%d\n", result); |
| @@ -838,8 +819,8 @@ static void __exit ati_remote_exit(void) | |||
| 838 | usb_deregister(&ati_remote_driver); | 819 | usb_deregister(&ati_remote_driver); |
| 839 | } | 820 | } |
| 840 | 821 | ||
| 841 | /* | 822 | /* |
| 842 | * module specification | 823 | * module specification |
| 843 | */ | 824 | */ |
| 844 | 825 | ||
| 845 | module_init(ati_remote_init); | 826 | module_init(ati_remote_init); |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 2d8bd9dcc6ed..96959ec590a3 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
| @@ -232,7 +232,7 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign | |||
| 232 | report->size += parser->global.report_size * parser->global.report_count; | 232 | report->size += parser->global.report_size * parser->global.report_count; |
| 233 | 233 | ||
| 234 | if (!parser->local.usage_index) /* Ignore padding fields */ | 234 | if (!parser->local.usage_index) /* Ignore padding fields */ |
| 235 | return 0; | 235 | return 0; |
| 236 | 236 | ||
| 237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); | 237 | usages = max_t(int, parser->local.usage_index, parser->global.report_count); |
| 238 | 238 | ||
| @@ -765,7 +765,7 @@ static __inline__ __u32 s32ton(__s32 value, unsigned n) | |||
| 765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) | 765 | static __inline__ __u32 extract(__u8 *report, unsigned offset, unsigned n) |
| 766 | { | 766 | { |
| 767 | report += (offset >> 5) << 2; offset &= 31; | 767 | report += (offset >> 5) << 2; offset &= 31; |
| 768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1 << n) - 1); | 768 | return (le64_to_cpu(get_unaligned((__le64*)report)) >> offset) & ((1ULL << n) - 1); |
| 769 | } | 769 | } |
| 770 | 770 | ||
| 771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) | 771 | static __inline__ void implement(__u8 *report, unsigned offset, unsigned n, __u32 value) |
| @@ -1233,6 +1233,13 @@ int hid_wait_io(struct hid_device *hid) | |||
| 1233 | return 0; | 1233 | return 0; |
| 1234 | } | 1234 | } |
| 1235 | 1235 | ||
| 1236 | static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) | ||
| 1237 | { | ||
| 1238 | return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | ||
| 1239 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report, | ||
| 1240 | ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 1241 | } | ||
| 1242 | |||
| 1236 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, | 1243 | static int hid_get_class_descriptor(struct usb_device *dev, int ifnum, |
| 1237 | unsigned char type, void *buf, int size) | 1244 | unsigned char type, void *buf, int size) |
| 1238 | { | 1245 | { |
| @@ -1301,10 +1308,6 @@ void hid_init_reports(struct hid_device *hid) | |||
| 1301 | 1308 | ||
| 1302 | if (err) | 1309 | if (err) |
| 1303 | warn("timeout initializing reports\n"); | 1310 | warn("timeout initializing reports\n"); |
| 1304 | |||
| 1305 | usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0), | ||
| 1306 | HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, | ||
| 1307 | hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 1308 | } | 1311 | } |
| 1309 | 1312 | ||
| 1310 | #define USB_VENDOR_ID_WACOM 0x056a | 1313 | #define USB_VENDOR_ID_WACOM 0x056a |
| @@ -1590,6 +1593,8 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
| 1590 | return NULL; | 1593 | return NULL; |
| 1591 | } | 1594 | } |
| 1592 | 1595 | ||
| 1596 | hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0); | ||
| 1597 | |||
| 1593 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { | 1598 | if ((n = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber, HID_DT_REPORT, rdesc, rsize)) < 0) { |
| 1594 | dbg("reading report descriptor failed"); | 1599 | dbg("reading report descriptor failed"); |
| 1595 | kfree(rdesc); | 1600 | kfree(rdesc); |
| @@ -1635,7 +1640,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
| 1635 | /* Change the polling interval of mice. */ | 1640 | /* Change the polling interval of mice. */ |
| 1636 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) | 1641 | if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) |
| 1637 | interval = hid_mousepoll_interval; | 1642 | interval = hid_mousepoll_interval; |
| 1638 | 1643 | ||
| 1639 | if (endpoint->bEndpointAddress & USB_DIR_IN) { | 1644 | if (endpoint->bEndpointAddress & USB_DIR_IN) { |
| 1640 | if (hid->urbin) | 1645 | if (hid->urbin) |
| 1641 | continue; | 1646 | continue; |
diff --git a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h index 2b91705740a7..52437e5e2e78 100644 --- a/drivers/usb/input/hid-debug.h +++ b/drivers/usb/input/hid-debug.h | |||
| @@ -67,7 +67,7 @@ static const struct hid_usage_entry hid_usage_table[] = { | |||
| 67 | {0, 0x44, "Vbry"}, | 67 | {0, 0x44, "Vbry"}, |
| 68 | {0, 0x45, "Vbrz"}, | 68 | {0, 0x45, "Vbrz"}, |
| 69 | {0, 0x46, "Vno"}, | 69 | {0, 0x46, "Vno"}, |
| 70 | {0, 0x80, "SystemControl"}, | 70 | {0, 0x80, "SystemControl"}, |
| 71 | {0, 0x81, "SystemPowerDown"}, | 71 | {0, 0x81, "SystemPowerDown"}, |
| 72 | {0, 0x82, "SystemSleep"}, | 72 | {0, 0x82, "SystemSleep"}, |
| 73 | {0, 0x83, "SystemWakeUp"}, | 73 | {0, 0x83, "SystemWakeUp"}, |
| @@ -347,7 +347,7 @@ __inline__ static void tab(int n) { | |||
| 347 | 347 | ||
| 348 | static void hid_dump_field(struct hid_field *field, int n) { | 348 | static void hid_dump_field(struct hid_field *field, int n) { |
| 349 | int j; | 349 | int j; |
| 350 | 350 | ||
| 351 | if (field->physical) { | 351 | if (field->physical) { |
| 352 | tab(n); | 352 | tab(n); |
| 353 | printk("Physical("); | 353 | printk("Physical("); |
| @@ -408,7 +408,7 @@ static void hid_dump_field(struct hid_field *field, int n) { | |||
| 408 | printk("%s", units[sys][i]); | 408 | printk("%s", units[sys][i]); |
| 409 | if(nibble != 1) { | 409 | if(nibble != 1) { |
| 410 | /* This is a _signed_ nibble(!) */ | 410 | /* This is a _signed_ nibble(!) */ |
| 411 | 411 | ||
| 412 | int val = nibble & 0x7; | 412 | int val = nibble & 0x7; |
| 413 | if(nibble & 0x08) | 413 | if(nibble & 0x08) |
| 414 | val = -((0x7 & ~val) +1); | 414 | val = -((0x7 & ~val) +1); |
| @@ -443,7 +443,7 @@ static void __attribute__((unused)) hid_dump_device(struct hid_device *device) { | |||
| 443 | struct list_head *list; | 443 | struct list_head *list; |
| 444 | unsigned i,k; | 444 | unsigned i,k; |
| 445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; | 445 | static char *table[] = {"INPUT", "OUTPUT", "FEATURE"}; |
| 446 | 446 | ||
| 447 | for (i = 0; i < HID_REPORT_TYPES; i++) { | 447 | for (i = 0; i < HID_REPORT_TYPES; i++) { |
| 448 | report_enum = device->report_enum + i; | 448 | report_enum = device->report_enum + i; |
| 449 | list = report_enum->report_list.next; | 449 | list = report_enum->report_list.next; |
| @@ -664,8 +664,8 @@ static char *keys[KEY_MAX + 1] = { | |||
| 664 | static char *relatives[REL_MAX + 1] = { | 664 | static char *relatives[REL_MAX + 1] = { |
| 665 | [REL_X] = "X", [REL_Y] = "Y", | 665 | [REL_X] = "X", [REL_Y] = "Y", |
| 666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", | 666 | [REL_Z] = "Z", [REL_HWHEEL] = "HWheel", |
| 667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", | 667 | [REL_DIAL] = "Dial", [REL_WHEEL] = "Wheel", |
| 668 | [REL_MISC] = "Misc", | 668 | [REL_MISC] = "Misc", |
| 669 | }; | 669 | }; |
| 670 | 670 | ||
| 671 | static char *absolutes[ABS_MAX + 1] = { | 671 | static char *absolutes[ABS_MAX + 1] = { |
| @@ -690,9 +690,9 @@ static char *misc[MSC_MAX + 1] = { | |||
| 690 | }; | 690 | }; |
| 691 | 691 | ||
| 692 | static char *leds[LED_MAX + 1] = { | 692 | static char *leds[LED_MAX + 1] = { |
| 693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", | 693 | [LED_NUML] = "NumLock", [LED_CAPSL] = "CapsLock", |
| 694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", | 694 | [LED_SCROLLL] = "ScrollLock", [LED_COMPOSE] = "Compose", |
| 695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", | 695 | [LED_KANA] = "Kana", [LED_SLEEP] = "Sleep", |
| 696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", | 696 | [LED_SUSPEND] = "Suspend", [LED_MUTE] = "Mute", |
| 697 | [LED_MISC] = "Misc", | 697 | [LED_MISC] = "Misc", |
| 698 | }; | 698 | }; |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 5553c3553e9d..9ac1e9095334 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
| @@ -164,7 +164,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: | 164 | case HID_GD_X: case HID_GD_Y: case HID_GD_Z: |
| 165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: | 165 | case HID_GD_RX: case HID_GD_RY: case HID_GD_RZ: |
| 166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: | 166 | case HID_GD_SLIDER: case HID_GD_DIAL: case HID_GD_WHEEL: |
| 167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) | 167 | if (field->flags & HID_MAIN_ITEM_RELATIVE) |
| 168 | map_rel(usage->hid & 0xf); | 168 | map_rel(usage->hid & 0xf); |
| 169 | else | 169 | else |
| 170 | map_abs(usage->hid & 0xf); | 170 | map_abs(usage->hid & 0xf); |
| @@ -297,7 +297,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 297 | case HID_UP_MSVENDOR: | 297 | case HID_UP_MSVENDOR: |
| 298 | 298 | ||
| 299 | goto ignore; | 299 | goto ignore; |
| 300 | 300 | ||
| 301 | case HID_UP_PID: | 301 | case HID_UP_PID: |
| 302 | 302 | ||
| 303 | set_bit(EV_FF, input->evbit); | 303 | set_bit(EV_FF, input->evbit); |
| @@ -349,7 +349,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 349 | goto ignore; | 349 | goto ignore; |
| 350 | 350 | ||
| 351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && | 351 | if ((device->quirks & (HID_QUIRK_2WHEEL_MOUSE_HACK_7 | HID_QUIRK_2WHEEL_MOUSE_HACK_5)) && |
| 352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) | 352 | (usage->type == EV_REL) && (usage->code == REL_WHEEL)) |
| 353 | set_bit(REL_HWHEEL, bit); | 353 | set_bit(REL_HWHEEL, bit); |
| 354 | 354 | ||
| 355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) | 355 | if (((device->quirks & HID_QUIRK_2WHEEL_MOUSE_HACK_5) && (usage->hid == 0x00090005)) |
| @@ -365,11 +365,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
| 365 | a = field->logical_minimum = 0; | 365 | a = field->logical_minimum = 0; |
| 366 | b = field->logical_maximum = 255; | 366 | b = field->logical_maximum = 255; |
| 367 | } | 367 | } |
| 368 | 368 | ||
| 369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) | 369 | if (field->application == HID_GD_GAMEPAD || field->application == HID_GD_JOYSTICK) |
| 370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); | 370 | input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); |
| 371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); | 371 | else input_set_abs_params(input, usage->code, a, b, 0, 0); |
| 372 | 372 | ||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 375 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
| @@ -420,7 +420,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
| 420 | return; | 420 | return; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 423 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
| 424 | int hat_dir = usage->hat_dir; | 424 | int hat_dir = usage->hat_dir; |
| 425 | if (!hat_dir) | 425 | if (!hat_dir) |
| 426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; | 426 | hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; |
| @@ -551,7 +551,7 @@ int hidinput_connect(struct hid_device *hid) | |||
| 551 | for (i = 0; i < hid->maxcollection; i++) | 551 | for (i = 0; i < hid->maxcollection; i++) |
| 552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || | 552 | if (hid->collection[i].type == HID_COLLECTION_APPLICATION || |
| 553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) | 553 | hid->collection[i].type == HID_COLLECTION_PHYSICAL) |
| 554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) | 554 | if (IS_INPUT_APPLICATION(hid->collection[i].usage)) |
| 555 | break; | 555 | break; |
| 556 | 556 | ||
| 557 | if (i == hid->maxcollection) | 557 | if (i == hid->maxcollection) |
| @@ -592,7 +592,7 @@ int hidinput_connect(struct hid_device *hid) | |||
| 592 | for (j = 0; j < report->field[i]->maxusage; j++) | 592 | for (j = 0; j < report->field[i]->maxusage; j++) |
| 593 | hidinput_configure_usage(hidinput, report->field[i], | 593 | hidinput_configure_usage(hidinput, report->field[i], |
| 594 | report->field[i]->usage + j); | 594 | report->field[i]->usage + j); |
| 595 | 595 | ||
| 596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { | 596 | if (hid->quirks & HID_QUIRK_MULTI_INPUT) { |
| 597 | /* This will leave hidinput NULL, so that it | 597 | /* This will leave hidinput NULL, so that it |
| 598 | * allocates another one if we have more inputs on | 598 | * allocates another one if we have more inputs on |
diff --git a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c index 0d7404bab92f..0c4c77aa31ea 100644 --- a/drivers/usb/input/hid-lgff.c +++ b/drivers/usb/input/hid-lgff.c | |||
| @@ -94,7 +94,7 @@ struct lgff_device { | |||
| 94 | isn't really necessary */ | 94 | isn't really necessary */ |
| 95 | 95 | ||
| 96 | unsigned long flags[1]; /* Contains various information about the | 96 | unsigned long flags[1]; /* Contains various information about the |
| 97 | state of the driver for this device */ | 97 | state of the driver for this device */ |
| 98 | 98 | ||
| 99 | struct timer_list timer; | 99 | struct timer_list timer; |
| 100 | }; | 100 | }; |
| @@ -234,7 +234,7 @@ static struct hid_report* hid_lgff_duplicate_report(struct hid_report* report) | |||
| 234 | kfree(ret); | 234 | kfree(ret); |
| 235 | return NULL; | 235 | return NULL; |
| 236 | } | 236 | } |
| 237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); | 237 | memset(ret->field[0]->value, 0, sizeof(s32[8])); |
| 238 | 238 | ||
| 239 | return ret; | 239 | return ret; |
| 240 | } | 240 | } |
| @@ -295,11 +295,11 @@ static int hid_lgff_event(struct hid_device *hid, struct input_dev* input, | |||
| 295 | unsigned long flags; | 295 | unsigned long flags; |
| 296 | 296 | ||
| 297 | if (type != EV_FF) return -EINVAL; | 297 | if (type != EV_FF) return -EINVAL; |
| 298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; | 298 | if (!LGFF_CHECK_OWNERSHIP(code, lgff)) return -EACCES; |
| 299 | if (value < 0) return -EINVAL; | 299 | if (value < 0) return -EINVAL; |
| 300 | 300 | ||
| 301 | spin_lock_irqsave(&lgff->lock, flags); | 301 | spin_lock_irqsave(&lgff->lock, flags); |
| 302 | 302 | ||
| 303 | if (value > 0) { | 303 | if (value > 0) { |
| 304 | if (test_bit(EFFECT_STARTED, effect->flags)) { | 304 | if (test_bit(EFFECT_STARTED, effect->flags)) { |
| 305 | spin_unlock_irqrestore(&lgff->lock, flags); | 305 | spin_unlock_irqrestore(&lgff->lock, flags); |
| @@ -345,7 +345,7 @@ static int hid_lgff_flush(struct input_dev *dev, struct file *file) | |||
| 345 | and perform ioctls on the same fd all at the same time */ | 345 | and perform ioctls on the same fd all at the same time */ |
| 346 | if ( current->pid == lgff->effects[i].owner | 346 | if ( current->pid == lgff->effects[i].owner |
| 347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { | 347 | && test_bit(EFFECT_USED, lgff->effects[i].flags)) { |
| 348 | 348 | ||
| 349 | if (hid_lgff_erase(dev, i)) | 349 | if (hid_lgff_erase(dev, i)) |
| 350 | warn("erase effect %d failed", i); | 350 | warn("erase effect %d failed", i); |
| 351 | } | 351 | } |
| @@ -378,7 +378,7 @@ static int hid_lgff_upload_effect(struct input_dev* input, | |||
| 378 | struct lgff_effect new; | 378 | struct lgff_effect new; |
| 379 | int id; | 379 | int id; |
| 380 | unsigned long flags; | 380 | unsigned long flags; |
| 381 | 381 | ||
| 382 | dbg("ioctl rumble"); | 382 | dbg("ioctl rumble"); |
| 383 | 383 | ||
| 384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; | 384 | if (!test_bit(effect->type, input->ffbit)) return -EINVAL; |
| @@ -441,7 +441,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
| 441 | 441 | ||
| 442 | spin_lock_irqsave(&lgff->lock, flags); | 442 | spin_lock_irqsave(&lgff->lock, flags); |
| 443 | 443 | ||
| 444 | for (i=0; i<LGFF_EFFECTS; ++i) { | 444 | for (i=0; i<LGFF_EFFECTS; ++i) { |
| 445 | struct lgff_effect* effect = lgff->effects +i; | 445 | struct lgff_effect* effect = lgff->effects +i; |
| 446 | 446 | ||
| 447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { | 447 | if (test_bit(EFFECT_PLAYING, effect->flags)) { |
| @@ -491,7 +491,7 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
| 491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); | 491 | set_bit(EFFECT_PLAYING, lgff->effects[i].flags); |
| 492 | } | 492 | } |
| 493 | } | 493 | } |
| 494 | } | 494 | } |
| 495 | 495 | ||
| 496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff | 496 | #define CLAMP(x) if (x < 0) x = 0; if (x > 0xff) x = 0xff |
| 497 | 497 | ||
| @@ -524,5 +524,5 @@ static void hid_lgff_timer(unsigned long timer_data) | |||
| 524 | add_timer(&lgff->timer); | 524 | add_timer(&lgff->timer); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | spin_unlock_irqrestore(&lgff->lock, flags); | 527 | spin_unlock_irqrestore(&lgff->lock, flags); |
| 528 | } | 528 | } |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index 6d9329c698d9..c1b6b69bc4a4 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
| @@ -118,7 +118,7 @@ struct hid_item { | |||
| 118 | #define HID_MAIN_ITEM_CONSTANT 0x001 | 118 | #define HID_MAIN_ITEM_CONSTANT 0x001 |
| 119 | #define HID_MAIN_ITEM_VARIABLE 0x002 | 119 | #define HID_MAIN_ITEM_VARIABLE 0x002 |
| 120 | #define HID_MAIN_ITEM_RELATIVE 0x004 | 120 | #define HID_MAIN_ITEM_RELATIVE 0x004 |
| 121 | #define HID_MAIN_ITEM_WRAP 0x008 | 121 | #define HID_MAIN_ITEM_WRAP 0x008 |
| 122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 | 122 | #define HID_MAIN_ITEM_NONLINEAR 0x010 |
| 123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 | 123 | #define HID_MAIN_ITEM_NO_PREFERRED 0x020 |
| 124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 | 124 | #define HID_MAIN_ITEM_NULL_STATE 0x040 |
| @@ -172,14 +172,14 @@ struct hid_item { | |||
| 172 | #define HID_USAGE_PAGE 0xffff0000 | 172 | #define HID_USAGE_PAGE 0xffff0000 |
| 173 | 173 | ||
| 174 | #define HID_UP_UNDEFINED 0x00000000 | 174 | #define HID_UP_UNDEFINED 0x00000000 |
| 175 | #define HID_UP_GENDESK 0x00010000 | 175 | #define HID_UP_GENDESK 0x00010000 |
| 176 | #define HID_UP_KEYBOARD 0x00070000 | 176 | #define HID_UP_KEYBOARD 0x00070000 |
| 177 | #define HID_UP_LED 0x00080000 | 177 | #define HID_UP_LED 0x00080000 |
| 178 | #define HID_UP_BUTTON 0x00090000 | 178 | #define HID_UP_BUTTON 0x00090000 |
| 179 | #define HID_UP_ORDINAL 0x000a0000 | 179 | #define HID_UP_ORDINAL 0x000a0000 |
| 180 | #define HID_UP_CONSUMER 0x000c0000 | 180 | #define HID_UP_CONSUMER 0x000c0000 |
| 181 | #define HID_UP_DIGITIZER 0x000d0000 | 181 | #define HID_UP_DIGITIZER 0x000d0000 |
| 182 | #define HID_UP_PID 0x000f0000 | 182 | #define HID_UP_PID 0x000f0000 |
| 183 | #define HID_UP_HPVENDOR 0xff7f0000 | 183 | #define HID_UP_HPVENDOR 0xff7f0000 |
| 184 | #define HID_UP_MSVENDOR 0xff000000 | 184 | #define HID_UP_MSVENDOR 0xff000000 |
| 185 | 185 | ||
| @@ -406,7 +406,7 @@ struct hid_device { /* device report descriptor */ | |||
| 406 | dma_addr_t outbuf_dma; /* Output buffer dma */ | 406 | dma_addr_t outbuf_dma; /* Output buffer dma */ |
| 407 | spinlock_t outlock; /* Output fifo spinlock */ | 407 | spinlock_t outlock; /* Output fifo spinlock */ |
| 408 | 408 | ||
| 409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ | 409 | unsigned claimed; /* Claimed by hidinput, hiddev? */ |
| 410 | unsigned quirks; /* Various quirks the device can pull on us */ | 410 | unsigned quirks; /* Various quirks the device can pull on us */ |
| 411 | 411 | ||
| 412 | struct list_head inputs; /* The list of inputs */ | 412 | struct list_head inputs; /* The list of inputs */ |
diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 96b7c9067951..4c13331b5f41 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c | |||
| @@ -95,7 +95,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
| 95 | return NULL; | 95 | return NULL; |
| 96 | rinfo->report_id = ((struct hid_report *) list)->id; | 96 | rinfo->report_id = ((struct hid_report *) list)->id; |
| 97 | break; | 97 | break; |
| 98 | 98 | ||
| 99 | case HID_REPORT_ID_NEXT: | 99 | case HID_REPORT_ID_NEXT: |
| 100 | list = (struct list_head *) | 100 | list = (struct list_head *) |
| 101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; | 101 | report_enum->report_id_hash[rinfo->report_id & HID_REPORT_ID_MASK]; |
| @@ -106,7 +106,7 @@ hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo) | |||
| 106 | return NULL; | 106 | return NULL; |
| 107 | rinfo->report_id = ((struct hid_report *) list)->id; | 107 | rinfo->report_id = ((struct hid_report *) list)->id; |
| 108 | break; | 108 | break; |
| 109 | 109 | ||
| 110 | default: | 110 | default: |
| 111 | return NULL; | 111 | return NULL; |
| 112 | } | 112 | } |
| @@ -158,7 +158,7 @@ static void hiddev_send_event(struct hid_device *hid, | |||
| 158 | if (uref->field_index != HID_FIELD_INDEX_NONE || | 158 | if (uref->field_index != HID_FIELD_INDEX_NONE || |
| 159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { | 159 | (list->flags & HIDDEV_FLAG_REPORT) != 0) { |
| 160 | list->buffer[list->head] = *uref; | 160 | list->buffer[list->head] = *uref; |
| 161 | list->head = (list->head + 1) & | 161 | list->head = (list->head + 1) & |
| 162 | (HIDDEV_BUFFER_SIZE - 1); | 162 | (HIDDEV_BUFFER_SIZE - 1); |
| 163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); | 163 | kill_fasync(&list->fasync, SIGIO, POLL_IN); |
| 164 | } | 164 | } |
| @@ -179,9 +179,9 @@ void hiddev_hid_event(struct hid_device *hid, struct hid_field *field, | |||
| 179 | unsigned type = field->report_type; | 179 | unsigned type = field->report_type; |
| 180 | struct hiddev_usage_ref uref; | 180 | struct hiddev_usage_ref uref; |
| 181 | 181 | ||
| 182 | uref.report_type = | 182 | uref.report_type = |
| 183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 183 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
| 184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 184 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
| 185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 185 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
| 186 | uref.report_id = field->report->id; | 186 | uref.report_id = field->report->id; |
| 187 | uref.field_index = field->index; | 187 | uref.field_index = field->index; |
| @@ -199,9 +199,9 @@ void hiddev_report_event(struct hid_device *hid, struct hid_report *report) | |||
| 199 | struct hiddev_usage_ref uref; | 199 | struct hiddev_usage_ref uref; |
| 200 | 200 | ||
| 201 | memset(&uref, 0, sizeof(uref)); | 201 | memset(&uref, 0, sizeof(uref)); |
| 202 | uref.report_type = | 202 | uref.report_type = |
| 203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : | 203 | (type == HID_INPUT_REPORT) ? HID_REPORT_TYPE_INPUT : |
| 204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : | 204 | ((type == HID_OUTPUT_REPORT) ? HID_REPORT_TYPE_OUTPUT : |
| 205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); | 205 | ((type == HID_FEATURE_REPORT) ? HID_REPORT_TYPE_FEATURE:0)); |
| 206 | uref.report_id = report->id; | 206 | uref.report_id = report->id; |
| 207 | uref.field_index = HID_FIELD_INDEX_NONE; | 207 | uref.field_index = HID_FIELD_INDEX_NONE; |
| @@ -236,7 +236,7 @@ static int hiddev_release(struct inode * inode, struct file * file) | |||
| 236 | *listptr = (*listptr)->next; | 236 | *listptr = (*listptr)->next; |
| 237 | 237 | ||
| 238 | if (!--list->hiddev->open) { | 238 | if (!--list->hiddev->open) { |
| 239 | if (list->hiddev->exist) | 239 | if (list->hiddev->exist) |
| 240 | hid_close(list->hiddev->hid); | 240 | hid_close(list->hiddev->hid); |
| 241 | else | 241 | else |
| 242 | kfree(list->hiddev); | 242 | kfree(list->hiddev); |
| @@ -303,7 +303,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
| 303 | if (list->head == list->tail) { | 303 | if (list->head == list->tail) { |
| 304 | add_wait_queue(&list->hiddev->wait, &wait); | 304 | add_wait_queue(&list->hiddev->wait, &wait); |
| 305 | set_current_state(TASK_INTERRUPTIBLE); | 305 | set_current_state(TASK_INTERRUPTIBLE); |
| 306 | 306 | ||
| 307 | while (list->head == list->tail) { | 307 | while (list->head == list->tail) { |
| 308 | if (file->f_flags & O_NONBLOCK) { | 308 | if (file->f_flags & O_NONBLOCK) { |
| 309 | retval = -EAGAIN; | 309 | retval = -EAGAIN; |
| @@ -317,7 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
| 317 | retval = -EIO; | 317 | retval = -EIO; |
| 318 | break; | 318 | break; |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | schedule(); | 321 | schedule(); |
| 322 | } | 322 | } |
| 323 | 323 | ||
| @@ -329,7 +329,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun | |||
| 329 | return retval; | 329 | return retval; |
| 330 | 330 | ||
| 331 | 331 | ||
| 332 | while (list->head != list->tail && | 332 | while (list->head != list->tail && |
| 333 | retval + event_size <= count) { | 333 | retval + event_size <= count) { |
| 334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { | 334 | if ((list->flags & HIDDEV_FLAG_UREF) == 0) { |
| 335 | if (list->buffer[list->tail].field_index != | 335 | if (list->buffer[list->tail].field_index != |
| @@ -405,10 +405,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 405 | return -EINVAL; | 405 | return -EINVAL; |
| 406 | 406 | ||
| 407 | for (i = 0; i < hid->maxcollection; i++) | 407 | for (i = 0; i < hid->maxcollection; i++) |
| 408 | if (hid->collection[i].type == | 408 | if (hid->collection[i].type == |
| 409 | HID_COLLECTION_APPLICATION && arg-- == 0) | 409 | HID_COLLECTION_APPLICATION && arg-- == 0) |
| 410 | break; | 410 | break; |
| 411 | 411 | ||
| 412 | if (i == hid->maxcollection) | 412 | if (i == hid->maxcollection) |
| 413 | return -EINVAL; | 413 | return -EINVAL; |
| 414 | 414 | ||
| @@ -562,7 +562,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 562 | if (!uref_multi) | 562 | if (!uref_multi) |
| 563 | return -ENOMEM; | 563 | return -ENOMEM; |
| 564 | uref = &uref_multi->uref; | 564 | uref = &uref_multi->uref; |
| 565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) | 565 | if (copy_from_user(uref, user_arg, sizeof(*uref))) |
| 566 | goto fault; | 566 | goto fault; |
| 567 | 567 | ||
| 568 | rinfo.report_type = uref->report_type; | 568 | rinfo.report_type = uref->report_type; |
| @@ -595,7 +595,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 595 | return -ENOMEM; | 595 | return -ENOMEM; |
| 596 | uref = &uref_multi->uref; | 596 | uref = &uref_multi->uref; |
| 597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | 597 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { |
| 598 | if (copy_from_user(uref_multi, user_arg, | 598 | if (copy_from_user(uref_multi, user_arg, |
| 599 | sizeof(*uref_multi))) | 599 | sizeof(*uref_multi))) |
| 600 | goto fault; | 600 | goto fault; |
| 601 | } else { | 601 | } else { |
| @@ -603,7 +603,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 603 | goto fault; | 603 | goto fault; |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | if (cmd != HIDIOCGUSAGE && | 606 | if (cmd != HIDIOCGUSAGE && |
| 607 | cmd != HIDIOCGUSAGES && | 607 | cmd != HIDIOCGUSAGES && |
| 608 | uref->report_type == HID_REPORT_TYPE_INPUT) | 608 | uref->report_type == HID_REPORT_TYPE_INPUT) |
| 609 | goto inval; | 609 | goto inval; |
| @@ -651,16 +651,16 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 651 | return field->usage[uref->usage_index].collection_index; | 651 | return field->usage[uref->usage_index].collection_index; |
| 652 | case HIDIOCGUSAGES: | 652 | case HIDIOCGUSAGES: |
| 653 | for (i = 0; i < uref_multi->num_values; i++) | 653 | for (i = 0; i < uref_multi->num_values; i++) |
| 654 | uref_multi->values[i] = | 654 | uref_multi->values[i] = |
| 655 | field->value[uref->usage_index + i]; | 655 | field->value[uref->usage_index + i]; |
| 656 | if (copy_to_user(user_arg, uref_multi, | 656 | if (copy_to_user(user_arg, uref_multi, |
| 657 | sizeof(*uref_multi))) | 657 | sizeof(*uref_multi))) |
| 658 | goto fault; | 658 | goto fault; |
| 659 | goto goodreturn; | 659 | goto goodreturn; |
| 660 | case HIDIOCSUSAGES: | 660 | case HIDIOCSUSAGES: |
| 661 | for (i = 0; i < uref_multi->num_values; i++) | 661 | for (i = 0; i < uref_multi->num_values; i++) |
| 662 | field->value[uref->usage_index + i] = | 662 | field->value[uref->usage_index + i] = |
| 663 | uref_multi->values[i]; | 663 | uref_multi->values[i]; |
| 664 | goto goodreturn; | 664 | goto goodreturn; |
| 665 | } | 665 | } |
| 666 | 666 | ||
| @@ -670,7 +670,7 @@ goodreturn: | |||
| 670 | fault: | 670 | fault: |
| 671 | kfree(uref_multi); | 671 | kfree(uref_multi); |
| 672 | return -EFAULT; | 672 | return -EFAULT; |
| 673 | inval: | 673 | inval: |
| 674 | kfree(uref_multi); | 674 | kfree(uref_multi); |
| 675 | return -EINVAL; | 675 | return -EINVAL; |
| 676 | 676 | ||
| @@ -734,7 +734,7 @@ static struct usb_class_driver hiddev_class = { | |||
| 734 | .name = "usb/hid/hiddev%d", | 734 | .name = "usb/hid/hiddev%d", |
| 735 | .fops = &hiddev_fops, | 735 | .fops = &hiddev_fops, |
| 736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, | 736 | .mode = S_IFCHR | S_IRUGO | S_IWUSR, |
| 737 | .minor_base = HIDDEV_MINOR_BASE, | 737 | .minor_base = HIDDEV_MINOR_BASE, |
| 738 | }; | 738 | }; |
| 739 | 739 | ||
| 740 | /* | 740 | /* |
| @@ -747,7 +747,7 @@ int hiddev_connect(struct hid_device *hid) | |||
| 747 | int retval; | 747 | int retval; |
| 748 | 748 | ||
| 749 | for (i = 0; i < hid->maxcollection; i++) | 749 | for (i = 0; i < hid->maxcollection; i++) |
| 750 | if (hid->collection[i].type == | 750 | if (hid->collection[i].type == |
| 751 | HID_COLLECTION_APPLICATION && | 751 | HID_COLLECTION_APPLICATION && |
| 752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) | 752 | !IS_INPUT_APPLICATION(hid->collection[i].usage)) |
| 753 | break; | 753 | break; |
| @@ -755,11 +755,11 @@ int hiddev_connect(struct hid_device *hid) | |||
| 755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) | 755 | if (i == hid->maxcollection && (hid->quirks & HID_QUIRK_HIDDEV) == 0) |
| 756 | return -1; | 756 | return -1; |
| 757 | 757 | ||
| 758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) | 758 | if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL))) |
| 759 | return -1; | 759 | return -1; |
| 760 | memset(hiddev, 0, sizeof(struct hiddev)); | 760 | memset(hiddev, 0, sizeof(struct hiddev)); |
| 761 | 761 | ||
| 762 | retval = usb_register_dev(hid->intf, &hiddev_class); | 762 | retval = usb_register_dev(hid->intf, &hiddev_class); |
| 763 | if (retval) { | 763 | if (retval) { |
| 764 | err("Not able to get a minor for this device."); | 764 | err("Not able to get a minor for this device."); |
| 765 | kfree(hiddev); | 765 | kfree(hiddev); |
| @@ -768,12 +768,12 @@ int hiddev_connect(struct hid_device *hid) | |||
| 768 | 768 | ||
| 769 | init_waitqueue_head(&hiddev->wait); | 769 | init_waitqueue_head(&hiddev->wait); |
| 770 | 770 | ||
| 771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; | 771 | hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev; |
| 772 | 772 | ||
| 773 | hiddev->hid = hid; | 773 | hiddev->hid = hid; |
| 774 | hiddev->exist = 1; | 774 | hiddev->exist = 1; |
| 775 | 775 | ||
| 776 | hid->minor = hid->intf->minor; | 776 | hid->minor = hid->intf->minor; |
| 777 | hid->hiddev = hiddev; | 777 | hid->hiddev = hiddev; |
| 778 | 778 | ||
| 779 | return 0; | 779 | return 0; |
| @@ -818,7 +818,7 @@ void hiddev_disconnect(struct hid_device *hid) | |||
| 818 | /* We never attach in this manner, and rely on HID to connect us. This | 818 | /* We never attach in this manner, and rely on HID to connect us. This |
| 819 | * is why there is no disconnect routine defined in the usb_driver either. | 819 | * is why there is no disconnect routine defined in the usb_driver either. |
| 820 | */ | 820 | */ |
| 821 | static int hiddev_usbd_probe(struct usb_interface *intf, | 821 | static int hiddev_usbd_probe(struct usb_interface *intf, |
| 822 | const struct usb_device_id *hiddev_info) | 822 | const struct usb_device_id *hiddev_info) |
| 823 | { | 823 | { |
| 824 | return -ENODEV; | 824 | return -ENODEV; |
diff --git a/drivers/usb/input/itmtouch.c b/drivers/usb/input/itmtouch.c new file mode 100644 index 000000000000..47dec6a1b344 --- /dev/null +++ b/drivers/usb/input/itmtouch.c | |||
| @@ -0,0 +1,268 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * itmtouch.c -- Driver for ITM touchscreen panel | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License as | ||
| 6 | * published by the Free Software Foundation; either version 2 of the | ||
| 7 | * License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 17 | * | ||
| 18 | * Based upon original work by Chris Collins <xfire-itmtouch@xware.cx>. | ||
| 19 | * | ||
| 20 | * Kudos to ITM for providing me with the datasheet for the panel, | ||
| 21 | * even though it was a day later than I had finished writing this | ||
| 22 | * driver. | ||
| 23 | * | ||
| 24 | * It has meant that I've been able to correct my interpretation of the | ||
| 25 | * protocol packets however. | ||
| 26 | * | ||
| 27 | * CC -- 2003/9/29 | ||
| 28 | * | ||
| 29 | * History | ||
| 30 | * 1.0 & 1.1 2003 (CC) vojtech@suse.cz | ||
| 31 | * Original version for 2.4.x kernels | ||
| 32 | * | ||
| 33 | * 1.2 02/03/2005 (HCE) hc@mivu.no | ||
| 34 | * Complete rewrite to support Linux 2.6.10, thanks to mtouchusb.c for hints. | ||
| 35 | * Unfortunately no calibration support at this time. | ||
| 36 | * | ||
| 37 | * 1.2.1 09/03/2005 (HCE) hc@mivu.no | ||
| 38 | * Code cleanup and adjusting syntax to start matching kernel standards | ||
| 39 | * | ||
| 40 | *****************************************************************************/ | ||
| 41 | |||
| 42 | #include <linux/config.h> | ||
| 43 | |||
| 44 | #ifdef CONFIG_USB_DEBUG | ||
| 45 | #define DEBUG | ||
| 46 | #else | ||
| 47 | #undef DEBUG | ||
| 48 | #endif | ||
| 49 | |||
| 50 | #include <linux/kernel.h> | ||
| 51 | #include <linux/slab.h> | ||
| 52 | #include <linux/input.h> | ||
| 53 | #include <linux/module.h> | ||
| 54 | #include <linux/init.h> | ||
| 55 | #include <linux/usb.h> | ||
| 56 | |||
| 57 | /* only an 8 byte buffer necessary for a single packet */ | ||
| 58 | #define ITM_BUFSIZE 8 | ||
| 59 | #define PATH_SIZE 64 | ||
| 60 | |||
| 61 | #define USB_VENDOR_ID_ITMINC 0x0403 | ||
| 62 | #define USB_PRODUCT_ID_TOUCHPANEL 0xf9e9 | ||
| 63 | |||
| 64 | #define DRIVER_AUTHOR "Hans-Christian Egtvedt <hc@mivu.no>" | ||
| 65 | #define DRIVER_VERSION "v1.2.1" | ||
| 66 | #define DRIVER_DESC "USB ITM Inc Touch Panel Driver" | ||
| 67 | #define DRIVER_LICENSE "GPL" | ||
| 68 | |||
| 69 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
| 70 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
| 71 | MODULE_LICENSE( DRIVER_LICENSE ); | ||
| 72 | |||
| 73 | struct itmtouch_dev { | ||
| 74 | struct usb_device *usbdev; /* usb device */ | ||
| 75 | struct input_dev inputdev; /* input device */ | ||
| 76 | struct urb *readurb; /* urb */ | ||
| 77 | char rbuf[ITM_BUFSIZE]; /* data */ | ||
| 78 | int users; | ||
| 79 | char name[128]; | ||
| 80 | char phys[64]; | ||
| 81 | }; | ||
| 82 | |||
| 83 | static struct usb_device_id itmtouch_ids [] = { | ||
| 84 | { USB_DEVICE(USB_VENDOR_ID_ITMINC, USB_PRODUCT_ID_TOUCHPANEL) }, | ||
| 85 | { } | ||
| 86 | }; | ||
| 87 | |||
| 88 | static void itmtouch_irq(struct urb *urb, struct pt_regs *regs) | ||
| 89 | { | ||
| 90 | struct itmtouch_dev * itmtouch = urb->context; | ||
| 91 | unsigned char *data = urb->transfer_buffer; | ||
| 92 | struct input_dev *dev = &itmtouch->inputdev; | ||
| 93 | int retval; | ||
| 94 | |||
| 95 | switch (urb->status) { | ||
| 96 | case 0: | ||
| 97 | /* success */ | ||
| 98 | break; | ||
| 99 | case -ETIMEDOUT: | ||
| 100 | /* this urb is timing out */ | ||
| 101 | dbg("%s - urb timed out - was the device unplugged?", | ||
| 102 | __FUNCTION__); | ||
| 103 | return; | ||
| 104 | case -ECONNRESET: | ||
| 105 | case -ENOENT: | ||
| 106 | case -ESHUTDOWN: | ||
| 107 | /* this urb is terminated, clean up */ | ||
| 108 | dbg("%s - urb shutting down with status: %d", | ||
| 109 | __FUNCTION__, urb->status); | ||
| 110 | return; | ||
| 111 | default: | ||
| 112 | dbg("%s - nonzero urb status received: %d", | ||
| 113 | __FUNCTION__, urb->status); | ||
| 114 | goto exit; | ||
| 115 | } | ||
| 116 | |||
| 117 | input_regs(dev, regs); | ||
| 118 | |||
| 119 | /* if pressure has been released, then don't report X/Y */ | ||
| 120 | if (data[7] & 0x20) { | ||
| 121 | input_report_abs(dev, ABS_X, (data[0] & 0x1F) << 7 | (data[3] & 0x7F)); | ||
| 122 | input_report_abs(dev, ABS_Y, (data[1] & 0x1F) << 7 | (data[4] & 0x7F)); | ||
| 123 | } | ||
| 124 | |||
| 125 | input_report_abs(dev, ABS_PRESSURE, (data[2] & 1) << 7 | (data[5] & 0x7F)); | ||
| 126 | input_report_key(dev, BTN_TOUCH, ~data[7] & 0x20); | ||
| 127 | input_sync(dev); | ||
| 128 | |||
| 129 | exit: | ||
| 130 | retval = usb_submit_urb (urb, GFP_ATOMIC); | ||
| 131 | if (retval) | ||
| 132 | printk(KERN_ERR "%s - usb_submit_urb failed with result: %d", | ||
| 133 | __FUNCTION__, retval); | ||
| 134 | } | ||
| 135 | |||
| 136 | static int itmtouch_open(struct input_dev *input) | ||
| 137 | { | ||
| 138 | struct itmtouch_dev *itmtouch = input->private; | ||
| 139 | |||
| 140 | itmtouch->readurb->dev = itmtouch->usbdev; | ||
| 141 | |||
| 142 | if (usb_submit_urb(itmtouch->readurb, GFP_KERNEL)) | ||
| 143 | return -EIO; | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static void itmtouch_close(struct input_dev *input) | ||
| 149 | { | ||
| 150 | struct itmtouch_dev *itmtouch = input->private; | ||
| 151 | |||
| 152 | usb_kill_urb(itmtouch->readurb); | ||
| 153 | } | ||
| 154 | |||
| 155 | static int itmtouch_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 156 | { | ||
| 157 | struct itmtouch_dev *itmtouch; | ||
| 158 | struct usb_host_interface *interface; | ||
| 159 | struct usb_endpoint_descriptor *endpoint; | ||
| 160 | struct usb_device *udev = interface_to_usbdev(intf); | ||
| 161 | unsigned int pipe; | ||
| 162 | unsigned int maxp; | ||
| 163 | char path[PATH_SIZE]; | ||
| 164 | |||
| 165 | interface = intf->cur_altsetting; | ||
| 166 | endpoint = &interface->endpoint[0].desc; | ||
| 167 | |||
| 168 | if (!(itmtouch = kcalloc(1, sizeof(struct itmtouch_dev), GFP_KERNEL))) { | ||
| 169 | err("%s - Out of memory.", __FUNCTION__); | ||
| 170 | return -ENOMEM; | ||
| 171 | } | ||
| 172 | |||
| 173 | itmtouch->usbdev = udev; | ||
| 174 | |||
| 175 | itmtouch->inputdev.private = itmtouch; | ||
| 176 | itmtouch->inputdev.open = itmtouch_open; | ||
| 177 | itmtouch->inputdev.close = itmtouch_close; | ||
| 178 | |||
| 179 | usb_make_path(udev, path, PATH_SIZE); | ||
| 180 | |||
| 181 | itmtouch->inputdev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
| 182 | itmtouch->inputdev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE); | ||
| 183 | itmtouch->inputdev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
| 184 | |||
| 185 | itmtouch->inputdev.name = itmtouch->name; | ||
| 186 | itmtouch->inputdev.phys = itmtouch->phys; | ||
| 187 | itmtouch->inputdev.id.bustype = BUS_USB; | ||
| 188 | itmtouch->inputdev.id.vendor = udev->descriptor.idVendor; | ||
| 189 | itmtouch->inputdev.id.product = udev->descriptor.idProduct; | ||
| 190 | itmtouch->inputdev.id.version = udev->descriptor.bcdDevice; | ||
| 191 | itmtouch->inputdev.dev = &intf->dev; | ||
| 192 | |||
| 193 | if (!strlen(itmtouch->name)) | ||
| 194 | sprintf(itmtouch->name, "USB ITM touchscreen"); | ||
| 195 | |||
| 196 | /* device limits */ | ||
| 197 | /* as specified by the ITM datasheet, X and Y are 12bit, | ||
| 198 | * Z (pressure) is 8 bit. However, the fields are defined up | ||
| 199 | * to 14 bits for future possible expansion. | ||
| 200 | */ | ||
| 201 | input_set_abs_params(&itmtouch->inputdev, ABS_X, 0, 0x0FFF, 2, 0); | ||
| 202 | input_set_abs_params(&itmtouch->inputdev, ABS_Y, 0, 0x0FFF, 2, 0); | ||
| 203 | input_set_abs_params(&itmtouch->inputdev, ABS_PRESSURE, 0, 0xFF, 2, 0); | ||
| 204 | |||
| 205 | /* initialise the URB so we can read from the transport stream */ | ||
| 206 | pipe = usb_rcvintpipe(itmtouch->usbdev, endpoint->bEndpointAddress); | ||
| 207 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | ||
| 208 | |||
| 209 | if (maxp > ITM_BUFSIZE) | ||
| 210 | maxp = ITM_BUFSIZE; | ||
| 211 | |||
| 212 | itmtouch->readurb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 213 | |||
| 214 | if (!itmtouch->readurb) { | ||
| 215 | dbg("%s - usb_alloc_urb failed: itmtouch->readurb", __FUNCTION__); | ||
| 216 | kfree(itmtouch); | ||
| 217 | return -ENOMEM; | ||
| 218 | } | ||
| 219 | |||
| 220 | usb_fill_int_urb(itmtouch->readurb, itmtouch->usbdev, pipe, itmtouch->rbuf, | ||
| 221 | maxp, itmtouch_irq, itmtouch, endpoint->bInterval); | ||
| 222 | |||
| 223 | input_register_device(&itmtouch->inputdev); | ||
| 224 | |||
| 225 | printk(KERN_INFO "itmtouch: %s registered on %s\n", itmtouch->name, path); | ||
| 226 | usb_set_intfdata(intf, itmtouch); | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static void itmtouch_disconnect(struct usb_interface *intf) | ||
| 232 | { | ||
| 233 | struct itmtouch_dev *itmtouch = usb_get_intfdata(intf); | ||
| 234 | |||
| 235 | usb_set_intfdata(intf, NULL); | ||
| 236 | |||
| 237 | if (itmtouch) { | ||
| 238 | input_unregister_device(&itmtouch->inputdev); | ||
| 239 | usb_kill_urb(itmtouch->readurb); | ||
| 240 | usb_free_urb(itmtouch->readurb); | ||
| 241 | kfree(itmtouch); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 245 | MODULE_DEVICE_TABLE(usb, itmtouch_ids); | ||
| 246 | |||
| 247 | static struct usb_driver itmtouch_driver = { | ||
| 248 | .owner = THIS_MODULE, | ||
| 249 | .name = "itmtouch", | ||
| 250 | .probe = itmtouch_probe, | ||
| 251 | .disconnect = itmtouch_disconnect, | ||
| 252 | .id_table = itmtouch_ids, | ||
| 253 | }; | ||
| 254 | |||
| 255 | static int __init itmtouch_init(void) | ||
| 256 | { | ||
| 257 | info(DRIVER_DESC " " DRIVER_VERSION); | ||
| 258 | info(DRIVER_AUTHOR); | ||
| 259 | return usb_register(&itmtouch_driver); | ||
| 260 | } | ||
| 261 | |||
| 262 | static void __exit itmtouch_exit(void) | ||
| 263 | { | ||
| 264 | usb_deregister(&itmtouch_driver); | ||
| 265 | } | ||
| 266 | |||
| 267 | module_init(itmtouch_init); | ||
| 268 | module_exit(itmtouch_exit); | ||
diff --git a/drivers/usb/input/kbtab.c b/drivers/usb/input/kbtab.c index a68c5b4e7b37..d2f0f90a9bcd 100644 --- a/drivers/usb/input/kbtab.c +++ b/drivers/usb/input/kbtab.c | |||
| @@ -36,7 +36,6 @@ struct kbtab { | |||
| 36 | struct input_dev dev; | 36 | struct input_dev dev; |
| 37 | struct usb_device *usbdev; | 37 | struct usb_device *usbdev; |
| 38 | struct urb *irq; | 38 | struct urb *irq; |
| 39 | int open; | ||
| 40 | int x, y; | 39 | int x, y; |
| 41 | int button; | 40 | int button; |
| 42 | int pressure; | 41 | int pressure; |
| @@ -79,12 +78,12 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) | |||
| 79 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ | 78 | /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ |
| 80 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); | 79 | input_report_key(dev, BTN_RIGHT, data[0] & 0x02); |
| 81 | 80 | ||
| 82 | if( -1 == kb_pressure_click){ | 81 | if (-1 == kb_pressure_click) { |
| 83 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); | 82 | input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); |
| 84 | } else { | 83 | } else { |
| 85 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); | 84 | input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); |
| 86 | }; | 85 | }; |
| 87 | 86 | ||
| 88 | input_sync(dev); | 87 | input_sync(dev); |
| 89 | 88 | ||
| 90 | exit: | 89 | exit: |
| @@ -105,14 +104,9 @@ static int kbtab_open(struct input_dev *dev) | |||
| 105 | { | 104 | { |
| 106 | struct kbtab *kbtab = dev->private; | 105 | struct kbtab *kbtab = dev->private; |
| 107 | 106 | ||
| 108 | if (kbtab->open++) | ||
| 109 | return 0; | ||
| 110 | |||
| 111 | kbtab->irq->dev = kbtab->usbdev; | 107 | kbtab->irq->dev = kbtab->usbdev; |
| 112 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) { | 108 | if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) |
| 113 | kbtab->open--; | ||
| 114 | return -EIO; | 109 | return -EIO; |
| 115 | } | ||
| 116 | 110 | ||
| 117 | return 0; | 111 | return 0; |
| 118 | } | 112 | } |
| @@ -121,8 +115,7 @@ static void kbtab_close(struct input_dev *dev) | |||
| 121 | { | 115 | { |
| 122 | struct kbtab *kbtab = dev->private; | 116 | struct kbtab *kbtab = dev->private; |
| 123 | 117 | ||
| 124 | if (!--kbtab->open) | 118 | usb_kill_urb(kbtab->irq); |
| 125 | usb_kill_urb(kbtab->irq); | ||
| 126 | } | 119 | } |
| 127 | 120 | ||
| 128 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) | 121 | static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| @@ -161,7 +154,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 161 | kbtab->dev.absmax[ABS_X] = 0x2000; | 154 | kbtab->dev.absmax[ABS_X] = 0x2000; |
| 162 | kbtab->dev.absmax[ABS_Y] = 0x1750; | 155 | kbtab->dev.absmax[ABS_Y] = 0x1750; |
| 163 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; | 156 | kbtab->dev.absmax[ABS_PRESSURE] = 0xff; |
| 164 | 157 | ||
| 165 | kbtab->dev.absfuzz[ABS_X] = 4; | 158 | kbtab->dev.absfuzz[ABS_X] = 4; |
| 166 | kbtab->dev.absfuzz[ABS_Y] = 4; | 159 | kbtab->dev.absfuzz[ABS_Y] = 4; |
| 167 | 160 | ||
diff --git a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c index ab1a2a30ce7c..09b5cc7c66de 100644 --- a/drivers/usb/input/mtouchusb.c +++ b/drivers/usb/input/mtouchusb.c | |||
| @@ -42,9 +42,9 @@ | |||
| 42 | #include <linux/config.h> | 42 | #include <linux/config.h> |
| 43 | 43 | ||
| 44 | #ifdef CONFIG_USB_DEBUG | 44 | #ifdef CONFIG_USB_DEBUG |
| 45 | #define DEBUG | 45 | #define DEBUG |
| 46 | #else | 46 | #else |
| 47 | #undef DEBUG | 47 | #undef DEBUG |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | #include <linux/kernel.h> | 50 | #include <linux/kernel.h> |
| @@ -93,275 +93,255 @@ module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR); | |||
| 93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); | 93 | MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)"); |
| 94 | 94 | ||
| 95 | struct mtouch_usb { | 95 | struct mtouch_usb { |
| 96 | unsigned char *data; | 96 | unsigned char *data; |
| 97 | dma_addr_t data_dma; | 97 | dma_addr_t data_dma; |
| 98 | struct urb *irq; | 98 | struct urb *irq; |
| 99 | struct usb_device *udev; | 99 | struct usb_device *udev; |
| 100 | struct input_dev input; | 100 | struct input_dev input; |
| 101 | int open; | 101 | char name[128]; |
| 102 | char name[128]; | 102 | char phys[64]; |
| 103 | char phys[64]; | ||
| 104 | }; | 103 | }; |
| 105 | 104 | ||
| 106 | static struct usb_device_id mtouchusb_devices [] = { | 105 | static struct usb_device_id mtouchusb_devices[] = { |
| 107 | { USB_DEVICE(0x0596, 0x0001) }, | 106 | { USB_DEVICE(0x0596, 0x0001) }, |
| 108 | { } | 107 | { } |
| 109 | }; | 108 | }; |
| 110 | 109 | ||
| 111 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) | 110 | static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) |
| 112 | { | 111 | { |
| 113 | struct mtouch_usb *mtouch = urb->context; | 112 | struct mtouch_usb *mtouch = urb->context; |
| 114 | int retval; | 113 | int retval; |
| 115 | 114 | ||
| 116 | switch (urb->status) { | 115 | switch (urb->status) { |
| 117 | case 0: | 116 | case 0: |
| 118 | /* success */ | 117 | /* success */ |
| 119 | break; | 118 | break; |
| 120 | case -ETIMEDOUT: | 119 | case -ETIMEDOUT: |
| 121 | /* this urb is timing out */ | 120 | /* this urb is timing out */ |
| 122 | dbg("%s - urb timed out - was the device unplugged?", | 121 | dbg("%s - urb timed out - was the device unplugged?", |
| 123 | __FUNCTION__); | 122 | __FUNCTION__); |
| 124 | return; | 123 | return; |
| 125 | case -ECONNRESET: | 124 | case -ECONNRESET: |
| 126 | case -ENOENT: | 125 | case -ENOENT: |
| 127 | case -ESHUTDOWN: | 126 | case -ESHUTDOWN: |
| 128 | /* this urb is terminated, clean up */ | 127 | /* this urb is terminated, clean up */ |
| 129 | dbg("%s - urb shutting down with status: %d", | 128 | dbg("%s - urb shutting down with status: %d", |
| 130 | __FUNCTION__, urb->status); | 129 | __FUNCTION__, urb->status); |
| 131 | return; | 130 | return; |
| 132 | default: | 131 | default: |
| 133 | dbg("%s - nonzero urb status received: %d", | 132 | dbg("%s - nonzero urb status received: %d", |
| 134 | __FUNCTION__, urb->status); | 133 | __FUNCTION__, urb->status); |
| 135 | goto exit; | 134 | goto exit; |
| 136 | } | 135 | } |
| 137 | 136 | ||
| 138 | input_regs(&mtouch->input, regs); | 137 | input_regs(&mtouch->input, regs); |
| 139 | input_report_key(&mtouch->input, BTN_TOUCH, | 138 | input_report_key(&mtouch->input, BTN_TOUCH, |
| 140 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); | 139 | MTOUCHUSB_GET_TOUCHED(mtouch->data)); |
| 141 | input_report_abs(&mtouch->input, ABS_X, | 140 | input_report_abs(&mtouch->input, ABS_X, MTOUCHUSB_GET_XC(mtouch->data)); |
| 142 | MTOUCHUSB_GET_XC(mtouch->data)); | 141 | input_report_abs(&mtouch->input, ABS_Y, |
| 143 | input_report_abs(&mtouch->input, ABS_Y, | ||
| 144 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) | 142 | (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC) |
| 145 | - MTOUCHUSB_GET_YC(mtouch->data)); | 143 | - MTOUCHUSB_GET_YC(mtouch->data)); |
| 146 | input_sync(&mtouch->input); | 144 | input_sync(&mtouch->input); |
| 147 | 145 | ||
| 148 | exit: | 146 | exit: |
| 149 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 147 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| 150 | if (retval) | 148 | if (retval) |
| 151 | err ("%s - usb_submit_urb failed with result: %d", | 149 | err("%s - usb_submit_urb failed with result: %d", |
| 152 | __FUNCTION__, retval); | 150 | __FUNCTION__, retval); |
| 153 | } | 151 | } |
| 154 | 152 | ||
| 155 | static int mtouchusb_open (struct input_dev *input) | 153 | static int mtouchusb_open(struct input_dev *input) |
| 156 | { | 154 | { |
| 157 | struct mtouch_usb *mtouch = input->private; | 155 | struct mtouch_usb *mtouch = input->private; |
| 158 | 156 | ||
| 159 | if (mtouch->open++) | 157 | mtouch->irq->dev = mtouch->udev; |
| 160 | return 0; | ||
| 161 | 158 | ||
| 162 | mtouch->irq->dev = mtouch->udev; | 159 | if (usb_submit_urb(mtouch->irq, GFP_ATOMIC)) |
| 160 | return -EIO; | ||
| 163 | 161 | ||
| 164 | if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) { | 162 | return 0; |
| 165 | mtouch->open--; | ||
| 166 | return -EIO; | ||
| 167 | } | ||
| 168 | |||
| 169 | return 0; | ||
| 170 | } | 163 | } |
| 171 | 164 | ||
| 172 | static void mtouchusb_close (struct input_dev *input) | 165 | static void mtouchusb_close(struct input_dev *input) |
| 173 | { | 166 | { |
| 174 | struct mtouch_usb *mtouch = input->private; | 167 | struct mtouch_usb *mtouch = input->private; |
| 175 | 168 | ||
| 176 | if (!--mtouch->open) | 169 | usb_kill_urb(mtouch->irq); |
| 177 | usb_kill_urb (mtouch->irq); | ||
| 178 | } | 170 | } |
| 179 | 171 | ||
| 180 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 172 | static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
| 181 | { | 173 | { |
| 182 | dbg("%s - called", __FUNCTION__); | 174 | dbg("%s - called", __FUNCTION__); |
| 183 | 175 | ||
| 184 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 176 | mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
| 185 | SLAB_ATOMIC, &mtouch->data_dma); | 177 | SLAB_ATOMIC, &mtouch->data_dma); |
| 186 | 178 | ||
| 187 | if (!mtouch->data) | 179 | if (!mtouch->data) |
| 188 | return -1; | 180 | return -1; |
| 189 | 181 | ||
| 190 | return 0; | 182 | return 0; |
| 191 | } | 183 | } |
| 192 | 184 | ||
| 193 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) | 185 | static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) |
| 194 | { | 186 | { |
| 195 | dbg("%s - called", __FUNCTION__); | 187 | dbg("%s - called", __FUNCTION__); |
| 196 | 188 | ||
| 197 | if (mtouch->data) | 189 | if (mtouch->data) |
| 198 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, | 190 | usb_buffer_free(udev, MTOUCHUSB_REPORT_DATA_SIZE, |
| 199 | mtouch->data, mtouch->data_dma); | 191 | mtouch->data, mtouch->data_dma); |
| 200 | } | 192 | } |
| 201 | 193 | ||
| 202 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) | 194 | static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 203 | { | 195 | { |
| 204 | struct mtouch_usb *mtouch; | 196 | struct mtouch_usb *mtouch; |
| 205 | struct usb_host_interface *interface; | 197 | struct usb_host_interface *interface; |
| 206 | struct usb_endpoint_descriptor *endpoint; | 198 | struct usb_endpoint_descriptor *endpoint; |
| 207 | struct usb_device *udev = interface_to_usbdev (intf); | 199 | struct usb_device *udev = interface_to_usbdev(intf); |
| 208 | char path[64]; | 200 | char path[64]; |
| 209 | int nRet; | 201 | int nRet; |
| 210 | 202 | ||
| 211 | dbg("%s - called", __FUNCTION__); | 203 | dbg("%s - called", __FUNCTION__); |
| 212 | 204 | ||
| 213 | dbg("%s - setting interface", __FUNCTION__); | 205 | dbg("%s - setting interface", __FUNCTION__); |
| 214 | interface = intf->cur_altsetting; | 206 | interface = intf->cur_altsetting; |
| 215 | 207 | ||
| 216 | dbg("%s - setting endpoint", __FUNCTION__); | 208 | dbg("%s - setting endpoint", __FUNCTION__); |
| 217 | endpoint = &interface->endpoint[0].desc; | 209 | endpoint = &interface->endpoint[0].desc; |
| 218 | 210 | ||
| 219 | if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { | 211 | if (!(mtouch = kmalloc(sizeof(struct mtouch_usb), GFP_KERNEL))) { |
| 220 | err("%s - Out of memory.", __FUNCTION__); | 212 | err("%s - Out of memory.", __FUNCTION__); |
| 221 | return -ENOMEM; | 213 | return -ENOMEM; |
| 222 | } | 214 | } |
| 223 | 215 | ||
| 224 | memset(mtouch, 0, sizeof(struct mtouch_usb)); | 216 | memset(mtouch, 0, sizeof(struct mtouch_usb)); |
| 225 | mtouch->udev = udev; | 217 | mtouch->udev = udev; |
| 226 | 218 | ||
| 227 | dbg("%s - allocating buffers", __FUNCTION__); | 219 | dbg("%s - allocating buffers", __FUNCTION__); |
| 228 | if (mtouchusb_alloc_buffers(udev, mtouch)) { | 220 | if (mtouchusb_alloc_buffers(udev, mtouch)) { |
| 229 | mtouchusb_free_buffers(udev, mtouch); | 221 | mtouchusb_free_buffers(udev, mtouch); |
| 230 | kfree(mtouch); | 222 | kfree(mtouch); |
| 231 | return -ENOMEM; | 223 | return -ENOMEM; |
| 232 | } | 224 | } |
| 233 | 225 | ||
| 234 | mtouch->input.private = mtouch; | 226 | mtouch->input.private = mtouch; |
| 235 | mtouch->input.open = mtouchusb_open; | 227 | mtouch->input.open = mtouchusb_open; |
| 236 | mtouch->input.close = mtouchusb_close; | 228 | mtouch->input.close = mtouchusb_close; |
| 237 | 229 | ||
| 238 | usb_make_path(udev, path, 64); | 230 | usb_make_path(udev, path, 64); |
| 239 | sprintf(mtouch->phys, "%s/input0", path); | 231 | sprintf(mtouch->phys, "%s/input0", path); |
| 240 | 232 | ||
| 241 | mtouch->input.name = mtouch->name; | 233 | mtouch->input.name = mtouch->name; |
| 242 | mtouch->input.phys = mtouch->phys; | 234 | mtouch->input.phys = mtouch->phys; |
| 243 | mtouch->input.id.bustype = BUS_USB; | 235 | mtouch->input.id.bustype = BUS_USB; |
| 244 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 236 | mtouch->input.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
| 245 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); | 237 | mtouch->input.id.product = le16_to_cpu(udev->descriptor.idProduct); |
| 246 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); | 238 | mtouch->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice); |
| 247 | mtouch->input.dev = &intf->dev; | 239 | mtouch->input.dev = &intf->dev; |
| 248 | 240 | ||
| 249 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 241 | mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
| 250 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); | 242 | mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); |
| 251 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | 243 | mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); |
| 252 | 244 | ||
| 253 | /* Used to Scale Compensated Data and Flip Y */ | 245 | /* Used to Scale Compensated Data and Flip Y */ |
| 254 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; | 246 | mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; |
| 255 | mtouch->input.absmax[ABS_X] = raw_coordinates ? \ | 247 | mtouch->input.absmax[ABS_X] = raw_coordinates ? |
| 256 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; | 248 | MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC; |
| 257 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; | 249 | mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; |
| 258 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; | 250 | mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; |
| 259 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; | 251 | mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MIN_YC; |
| 260 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? \ | 252 | mtouch->input.absmax[ABS_Y] = raw_coordinates ? |
| 261 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; | 253 | MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC; |
| 262 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; | 254 | mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; |
| 263 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; | 255 | mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; |
| 264 | 256 | ||
| 265 | if (udev->manufacturer) | 257 | if (udev->manufacturer) |
| 266 | strcat(mtouch->name, udev->manufacturer); | 258 | strcat(mtouch->name, udev->manufacturer); |
| 267 | if (udev->product) | 259 | if (udev->product) |
| 268 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); | 260 | sprintf(mtouch->name, "%s %s", mtouch->name, udev->product); |
| 269 | 261 | ||
| 270 | if (!strlen(mtouch->name)) | 262 | if (!strlen(mtouch->name)) |
| 271 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", | 263 | sprintf(mtouch->name, "USB Touchscreen %04x:%04x", |
| 272 | mtouch->input.id.vendor, mtouch->input.id.product); | 264 | mtouch->input.id.vendor, mtouch->input.id.product); |
| 273 | 265 | ||
| 274 | nRet = usb_control_msg(mtouch->udev, | 266 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
| 275 | usb_rcvctrlpipe(udev, 0), | 267 | MTOUCHUSB_RESET, |
| 276 | MTOUCHUSB_RESET, | 268 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 277 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 269 | 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 278 | 1, | 270 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", |
| 279 | 0, | 271 | __FUNCTION__, nRet); |
| 280 | NULL, | 272 | |
| 281 | 0, | 273 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); |
| 282 | USB_CTRL_SET_TIMEOUT); | 274 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); |
| 283 | dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d", | 275 | if (!mtouch->irq) { |
| 284 | __FUNCTION__, nRet); | 276 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); |
| 285 | 277 | mtouchusb_free_buffers(udev, mtouch); | |
| 286 | dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); | 278 | kfree(mtouch); |
| 287 | mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); | 279 | return -ENOMEM; |
| 288 | if (!mtouch->irq) { | 280 | } |
| 289 | dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); | 281 | |
| 290 | mtouchusb_free_buffers(udev, mtouch); | 282 | dbg("%s - usb_fill_int_urb", __FUNCTION__); |
| 291 | kfree(mtouch); | 283 | usb_fill_int_urb(mtouch->irq, mtouch->udev, |
| 292 | return -ENOMEM; | 284 | usb_rcvintpipe(mtouch->udev, 0x81), |
| 293 | } | 285 | mtouch->data, MTOUCHUSB_REPORT_DATA_SIZE, |
| 294 | 286 | mtouchusb_irq, mtouch, endpoint->bInterval); | |
| 295 | dbg("%s - usb_fill_int_urb", __FUNCTION__); | 287 | |
| 296 | usb_fill_int_urb(mtouch->irq, | 288 | dbg("%s - input_register_device", __FUNCTION__); |
| 297 | mtouch->udev, | 289 | input_register_device(&mtouch->input); |
| 298 | usb_rcvintpipe(mtouch->udev, 0x81), | 290 | |
| 299 | mtouch->data, | 291 | nRet = usb_control_msg(mtouch->udev, usb_rcvctrlpipe(udev, 0), |
| 300 | MTOUCHUSB_REPORT_DATA_SIZE, | 292 | MTOUCHUSB_ASYNC_REPORT, |
| 301 | mtouchusb_irq, | 293 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
| 302 | mtouch, | 294 | 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 303 | endpoint->bInterval); | 295 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", |
| 304 | 296 | __FUNCTION__, nRet); | |
| 305 | dbg("%s - input_register_device", __FUNCTION__); | 297 | |
| 306 | input_register_device(&mtouch->input); | 298 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); |
| 307 | 299 | usb_set_intfdata(intf, mtouch); | |
| 308 | nRet = usb_control_msg(mtouch->udev, | 300 | |
| 309 | usb_rcvctrlpipe(udev, 0), | 301 | return 0; |
| 310 | MTOUCHUSB_ASYNC_REPORT, | ||
| 311 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
| 312 | 1, | ||
| 313 | 1, | ||
| 314 | NULL, | ||
| 315 | 0, | ||
| 316 | USB_CTRL_SET_TIMEOUT); | ||
| 317 | dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d", | ||
| 318 | __FUNCTION__, nRet); | ||
| 319 | |||
| 320 | printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); | ||
| 321 | usb_set_intfdata(intf, mtouch); | ||
| 322 | |||
| 323 | return 0; | ||
| 324 | } | 302 | } |
| 325 | 303 | ||
| 326 | static void mtouchusb_disconnect(struct usb_interface *intf) | 304 | static void mtouchusb_disconnect(struct usb_interface *intf) |
| 327 | { | 305 | { |
| 328 | struct mtouch_usb *mtouch = usb_get_intfdata (intf); | 306 | struct mtouch_usb *mtouch = usb_get_intfdata(intf); |
| 329 | 307 | ||
| 330 | dbg("%s - called", __FUNCTION__); | 308 | dbg("%s - called", __FUNCTION__); |
| 331 | usb_set_intfdata(intf, NULL); | 309 | usb_set_intfdata(intf, NULL); |
| 332 | if (mtouch) { | 310 | if (mtouch) { |
| 333 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); | 311 | dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); |
| 334 | usb_kill_urb(mtouch->irq); | 312 | usb_kill_urb(mtouch->irq); |
| 335 | input_unregister_device(&mtouch->input); | 313 | input_unregister_device(&mtouch->input); |
| 336 | usb_free_urb(mtouch->irq); | 314 | usb_free_urb(mtouch->irq); |
| 337 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); | 315 | mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); |
| 338 | kfree(mtouch); | 316 | kfree(mtouch); |
| 339 | } | 317 | } |
| 340 | } | 318 | } |
| 341 | 319 | ||
| 342 | MODULE_DEVICE_TABLE (usb, mtouchusb_devices); | 320 | MODULE_DEVICE_TABLE(usb, mtouchusb_devices); |
| 343 | 321 | ||
| 344 | static struct usb_driver mtouchusb_driver = { | 322 | static struct usb_driver mtouchusb_driver = { |
| 345 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
| 346 | .name = "mtouchusb", | 324 | .name = "mtouchusb", |
| 347 | .probe = mtouchusb_probe, | 325 | .probe = mtouchusb_probe, |
| 348 | .disconnect = mtouchusb_disconnect, | 326 | .disconnect = mtouchusb_disconnect, |
| 349 | .id_table = mtouchusb_devices, | 327 | .id_table = mtouchusb_devices, |
| 350 | }; | 328 | }; |
| 351 | 329 | ||
| 352 | static int __init mtouchusb_init(void) { | 330 | static int __init mtouchusb_init(void) |
| 353 | dbg("%s - called", __FUNCTION__); | 331 | { |
| 354 | return usb_register(&mtouchusb_driver); | 332 | dbg("%s - called", __FUNCTION__); |
| 333 | return usb_register(&mtouchusb_driver); | ||
| 355 | } | 334 | } |
| 356 | 335 | ||
| 357 | static void __exit mtouchusb_cleanup(void) { | 336 | static void __exit mtouchusb_cleanup(void) |
| 358 | dbg("%s - called", __FUNCTION__); | 337 | { |
| 359 | usb_deregister(&mtouchusb_driver); | 338 | dbg("%s - called", __FUNCTION__); |
| 339 | usb_deregister(&mtouchusb_driver); | ||
| 360 | } | 340 | } |
| 361 | 341 | ||
| 362 | module_init(mtouchusb_init); | 342 | module_init(mtouchusb_init); |
| 363 | module_exit(mtouchusb_cleanup); | 343 | module_exit(mtouchusb_cleanup); |
| 364 | 344 | ||
| 365 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 345 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| 366 | MODULE_DESCRIPTION( DRIVER_DESC ); | 346 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 367 | MODULE_LICENSE("GPL"); | 347 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c index 7fa2f9b9fb69..3975b309d55f 100644 --- a/drivers/usb/input/powermate.c +++ b/drivers/usb/input/powermate.c | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | * back to the host when polled by the USB controller. | 10 | * back to the host when polled by the USB controller. |
| 11 | * | 11 | * |
| 12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" | 12 | * Testing with the knob I have has shown that it measures approximately 94 "clicks" |
| 13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was | 13 | * for one full rotation. Testing with my High Speed Rotation Actuator (ok, it was |
| 14 | * a variable speed cordless electric drill) has shown that the device can measure | 14 | * a variable speed cordless electric drill) has shown that the device can measure |
| 15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from | 15 | * speeds of up to 7 clicks either clockwise or anticlockwise between pollings from |
| 16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back | 16 | * the host. If it counts more than 7 clicks before it is polled, it will wrap back |
| @@ -120,9 +120,9 @@ exit: | |||
| 120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ | 120 | /* Decide if we need to issue a control message and do so. Must be called with pm->lock taken */ |
| 121 | static void powermate_sync_state(struct powermate_device *pm) | 121 | static void powermate_sync_state(struct powermate_device *pm) |
| 122 | { | 122 | { |
| 123 | if (pm->requires_update == 0) | 123 | if (pm->requires_update == 0) |
| 124 | return; /* no updates are required */ | 124 | return; /* no updates are required */ |
| 125 | if (pm->config->status == -EINPROGRESS) | 125 | if (pm->config->status == -EINPROGRESS) |
| 126 | return; /* an update is already in progress; it'll issue this update when it completes */ | 126 | return; /* an update is already in progress; it'll issue this update when it completes */ |
| 127 | 127 | ||
| 128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ | 128 | if (pm->requires_update & UPDATE_PULSE_ASLEEP){ |
| @@ -142,7 +142,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
| 142 | 2: multiply the speed | 142 | 2: multiply the speed |
| 143 | the argument only has an effect for operations 0 and 2, and ranges between | 143 | the argument only has an effect for operations 0 and 2, and ranges between |
| 144 | 1 (least effect) to 255 (maximum effect). | 144 | 1 (least effect) to 255 (maximum effect). |
| 145 | 145 | ||
| 146 | thus, several states are equivalent and are coalesced into one state. | 146 | thus, several states are equivalent and are coalesced into one state. |
| 147 | 147 | ||
| 148 | we map this onto a range from 0 to 510, with: | 148 | we map this onto a range from 0 to 510, with: |
| @@ -151,7 +151,7 @@ static void powermate_sync_state(struct powermate_device *pm) | |||
| 151 | 256 -- 510 -- use multiple (510 = fastest). | 151 | 256 -- 510 -- use multiple (510 = fastest). |
| 152 | 152 | ||
| 153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. | 153 | Only values of 'arg' quite close to 255 are particularly useful/spectacular. |
| 154 | */ | 154 | */ |
| 155 | if (pm->pulse_speed < 255){ | 155 | if (pm->pulse_speed < 255){ |
| 156 | op = 0; // divide | 156 | op = 0; // divide |
| 157 | arg = 255 - pm->pulse_speed; | 157 | arg = 255 - pm->pulse_speed; |
| @@ -199,14 +199,14 @@ static void powermate_config_complete(struct urb *urb, struct pt_regs *regs) | |||
| 199 | 199 | ||
| 200 | if (urb->status) | 200 | if (urb->status) |
| 201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); | 201 | printk(KERN_ERR "powermate: config urb returned %d\n", urb->status); |
| 202 | 202 | ||
| 203 | spin_lock_irqsave(&pm->lock, flags); | 203 | spin_lock_irqsave(&pm->lock, flags); |
| 204 | powermate_sync_state(pm); | 204 | powermate_sync_state(pm); |
| 205 | spin_unlock_irqrestore(&pm->lock, flags); | 205 | spin_unlock_irqrestore(&pm->lock, flags); |
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | /* Set the LED up as described and begin the sync with the hardware if required */ | 208 | /* Set the LED up as described and begin the sync with the hardware if required */ |
| 209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, | 209 | static void powermate_pulse_led(struct powermate_device *pm, int static_brightness, int pulse_speed, |
| 210 | int pulse_table, int pulse_asleep, int pulse_awake) | 210 | int pulse_table, int pulse_asleep, int pulse_awake) |
| 211 | { | 211 | { |
| 212 | unsigned long flags; | 212 | unsigned long flags; |
| @@ -229,7 +229,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
| 229 | /* mark state updates which are required */ | 229 | /* mark state updates which are required */ |
| 230 | if (static_brightness != pm->static_brightness){ | 230 | if (static_brightness != pm->static_brightness){ |
| 231 | pm->static_brightness = static_brightness; | 231 | pm->static_brightness = static_brightness; |
| 232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; | 232 | pm->requires_update |= UPDATE_STATIC_BRIGHTNESS; |
| 233 | } | 233 | } |
| 234 | if (pulse_asleep != pm->pulse_asleep){ | 234 | if (pulse_asleep != pm->pulse_asleep){ |
| 235 | pm->pulse_asleep = pulse_asleep; | 235 | pm->pulse_asleep = pulse_asleep; |
| @@ -246,7 +246,7 @@ static void powermate_pulse_led(struct powermate_device *pm, int static_brightne | |||
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | powermate_sync_state(pm); | 248 | powermate_sync_state(pm); |
| 249 | 249 | ||
| 250 | spin_unlock_irqrestore(&pm->lock, flags); | 250 | spin_unlock_irqrestore(&pm->lock, flags); |
| 251 | } | 251 | } |
| 252 | 252 | ||
| @@ -257,19 +257,19 @@ static int powermate_input_event(struct input_dev *dev, unsigned int type, unsig | |||
| 257 | struct powermate_device *pm = dev->private; | 257 | struct powermate_device *pm = dev->private; |
| 258 | 258 | ||
| 259 | if (type == EV_MSC && code == MSC_PULSELED){ | 259 | if (type == EV_MSC && code == MSC_PULSELED){ |
| 260 | /* | 260 | /* |
| 261 | bits 0- 7: 8 bits: LED brightness | 261 | bits 0- 7: 8 bits: LED brightness |
| 262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. | 262 | bits 8-16: 9 bits: pulsing speed modifier (0 ... 510); 0-254 = slower, 255 = standard, 256-510 = faster. |
| 263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) | 263 | bits 17-18: 2 bits: pulse table (0, 1, 2 valid) |
| 264 | bit 19: 1 bit : pulse whilst asleep? | 264 | bit 19: 1 bit : pulse whilst asleep? |
| 265 | bit 20: 1 bit : pulse constantly? | 265 | bit 20: 1 bit : pulse constantly? |
| 266 | */ | 266 | */ |
| 267 | int static_brightness = command & 0xFF; // bits 0-7 | 267 | int static_brightness = command & 0xFF; // bits 0-7 |
| 268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 | 268 | int pulse_speed = (command >> 8) & 0x1FF; // bits 8-16 |
| 269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 | 269 | int pulse_table = (command >> 17) & 0x3; // bits 17-18 |
| 270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 | 270 | int pulse_asleep = (command >> 19) & 0x1; // bit 19 |
| 271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 | 271 | int pulse_awake = (command >> 20) & 0x1; // bit 20 |
| 272 | 272 | ||
| 273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); | 273 | powermate_pulse_led(pm, static_brightness, pulse_speed, pulse_table, pulse_asleep, pulse_awake); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| @@ -378,7 +378,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
| 378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { | 378 | switch (le16_to_cpu(udev->descriptor.idProduct)) { |
| 379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; | 379 | case POWERMATE_PRODUCT_NEW: pm->input.name = pm_name_powermate; break; |
| 380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; | 380 | case POWERMATE_PRODUCT_OLD: pm->input.name = pm_name_soundknob; break; |
| 381 | default: | 381 | default: |
| 382 | pm->input.name = pm_name_soundknob; | 382 | pm->input.name = pm_name_soundknob; |
| 383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", | 383 | printk(KERN_WARNING "powermate: unknown product id %04x\n", |
| 384 | le16_to_cpu(udev->descriptor.idProduct)); | 384 | le16_to_cpu(udev->descriptor.idProduct)); |
| @@ -402,11 +402,11 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i | |||
| 402 | usb_make_path(udev, path, 64); | 402 | usb_make_path(udev, path, 64); |
| 403 | snprintf(pm->phys, 64, "%s/input0", path); | 403 | snprintf(pm->phys, 64, "%s/input0", path); |
| 404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); | 404 | printk(KERN_INFO "input: %s on %s\n", pm->input.name, pm->input.phys); |
| 405 | 405 | ||
| 406 | /* force an update of everything */ | 406 | /* force an update of everything */ |
| 407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; | 407 | pm->requires_update = UPDATE_PULSE_ASLEEP | UPDATE_PULSE_AWAKE | UPDATE_PULSE_MODE | UPDATE_STATIC_BRIGHTNESS; |
| 408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters | 408 | powermate_pulse_led(pm, 0x80, 255, 0, 1, 0); // set default pulse parameters |
| 409 | 409 | ||
| 410 | usb_set_intfdata(intf, pm); | 410 | usb_set_intfdata(intf, pm); |
| 411 | return 0; | 411 | return 0; |
| 412 | } | 412 | } |
diff --git a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c index a71f1bbd0a17..386595ee21c0 100644 --- a/drivers/usb/input/touchkitusb.c +++ b/drivers/usb/input/touchkitusb.c | |||
| @@ -69,7 +69,6 @@ struct touchkit_usb { | |||
| 69 | struct urb *irq; | 69 | struct urb *irq; |
| 70 | struct usb_device *udev; | 70 | struct usb_device *udev; |
| 71 | struct input_dev input; | 71 | struct input_dev input; |
| 72 | int open; | ||
| 73 | char name[128]; | 72 | char name[128]; |
| 74 | char phys[64]; | 73 | char phys[64]; |
| 75 | }; | 74 | }; |
| @@ -134,15 +133,10 @@ static int touchkit_open(struct input_dev *input) | |||
| 134 | { | 133 | { |
| 135 | struct touchkit_usb *touchkit = input->private; | 134 | struct touchkit_usb *touchkit = input->private; |
| 136 | 135 | ||
| 137 | if (touchkit->open++) | ||
| 138 | return 0; | ||
| 139 | |||
| 140 | touchkit->irq->dev = touchkit->udev; | 136 | touchkit->irq->dev = touchkit->udev; |
| 141 | 137 | ||
| 142 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) { | 138 | if (usb_submit_urb(touchkit->irq, GFP_ATOMIC)) |
| 143 | touchkit->open--; | ||
| 144 | return -EIO; | 139 | return -EIO; |
| 145 | } | ||
| 146 | 140 | ||
| 147 | return 0; | 141 | return 0; |
| 148 | } | 142 | } |
| @@ -151,8 +145,7 @@ static void touchkit_close(struct input_dev *input) | |||
| 151 | { | 145 | { |
| 152 | struct touchkit_usb *touchkit = input->private; | 146 | struct touchkit_usb *touchkit = input->private; |
| 153 | 147 | ||
| 154 | if (!--touchkit->open) | 148 | usb_kill_urb(touchkit->irq); |
| 155 | usb_kill_urb(touchkit->irq); | ||
| 156 | } | 149 | } |
| 157 | 150 | ||
| 158 | static int touchkit_alloc_buffers(struct usb_device *udev, | 151 | static int touchkit_alloc_buffers(struct usb_device *udev, |
diff --git a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c index 7038fb9d1ced..f35db1974c42 100644 --- a/drivers/usb/input/usbkbd.c +++ b/drivers/usb/input/usbkbd.c | |||
| @@ -9,18 +9,18 @@ | |||
| 9 | /* | 9 | /* |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
| 12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
| 14 | * | 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
| 19 | * | 19 | * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 23 | * | 23 | * |
| 24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
| 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
| 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| @@ -72,7 +72,6 @@ struct usb_kbd { | |||
| 72 | unsigned char newleds; | 72 | unsigned char newleds; |
| 73 | char name[128]; | 73 | char name[128]; |
| 74 | char phys[64]; | 74 | char phys[64]; |
| 75 | int open; | ||
| 76 | 75 | ||
| 77 | unsigned char *new; | 76 | unsigned char *new; |
| 78 | struct usb_ctrlrequest *cr; | 77 | struct usb_ctrlrequest *cr; |
| @@ -166,7 +165,7 @@ static void usb_kbd_led(struct urb *urb, struct pt_regs *regs) | |||
| 166 | 165 | ||
| 167 | if (urb->status) | 166 | if (urb->status) |
| 168 | warn("led urb status %d received", urb->status); | 167 | warn("led urb status %d received", urb->status); |
| 169 | 168 | ||
| 170 | if (*(kbd->leds) == kbd->newleds) | 169 | if (*(kbd->leds) == kbd->newleds) |
| 171 | return; | 170 | return; |
| 172 | 171 | ||
| @@ -180,14 +179,9 @@ static int usb_kbd_open(struct input_dev *dev) | |||
| 180 | { | 179 | { |
| 181 | struct usb_kbd *kbd = dev->private; | 180 | struct usb_kbd *kbd = dev->private; |
| 182 | 181 | ||
| 183 | if (kbd->open++) | ||
| 184 | return 0; | ||
| 185 | |||
| 186 | kbd->irq->dev = kbd->usbdev; | 182 | kbd->irq->dev = kbd->usbdev; |
| 187 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) { | 183 | if (usb_submit_urb(kbd->irq, GFP_KERNEL)) |
| 188 | kbd->open--; | ||
| 189 | return -EIO; | 184 | return -EIO; |
| 190 | } | ||
| 191 | 185 | ||
| 192 | return 0; | 186 | return 0; |
| 193 | } | 187 | } |
| @@ -196,8 +190,7 @@ static void usb_kbd_close(struct input_dev *dev) | |||
| 196 | { | 190 | { |
| 197 | struct usb_kbd *kbd = dev->private; | 191 | struct usb_kbd *kbd = dev->private; |
| 198 | 192 | ||
| 199 | if (!--kbd->open) | 193 | usb_kill_urb(kbd->irq); |
| 200 | usb_kill_urb(kbd->irq); | ||
| 201 | } | 194 | } |
| 202 | 195 | ||
| 203 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) | 196 | static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd) |
| @@ -230,7 +223,7 @@ static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) | |||
| 230 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); | 223 | usb_buffer_free(dev, 1, kbd->leds, kbd->leds_dma); |
| 231 | } | 224 | } |
| 232 | 225 | ||
| 233 | static int usb_kbd_probe(struct usb_interface *iface, | 226 | static int usb_kbd_probe(struct usb_interface *iface, |
| 234 | const struct usb_device_id *id) | 227 | const struct usb_device_id *id) |
| 235 | { | 228 | { |
| 236 | struct usb_device * dev = interface_to_usbdev(iface); | 229 | struct usb_device * dev = interface_to_usbdev(iface); |
| @@ -272,7 +265,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
| 272 | for (i = 0; i < 255; i++) | 265 | for (i = 0; i < 255; i++) |
| 273 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); | 266 | set_bit(usb_kbd_keycode[i], kbd->dev.keybit); |
| 274 | clear_bit(0, kbd->dev.keybit); | 267 | clear_bit(0, kbd->dev.keybit); |
| 275 | 268 | ||
| 276 | kbd->dev.private = kbd; | 269 | kbd->dev.private = kbd; |
| 277 | kbd->dev.event = usb_kbd_event; | 270 | kbd->dev.event = usb_kbd_event; |
| 278 | kbd->dev.open = usb_kbd_open; | 271 | kbd->dev.open = usb_kbd_open; |
| @@ -294,7 +287,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
| 294 | sprintf(kbd->phys, "%s/input0", path); | 287 | sprintf(kbd->phys, "%s/input0", path); |
| 295 | 288 | ||
| 296 | kbd->dev.name = kbd->name; | 289 | kbd->dev.name = kbd->name; |
| 297 | kbd->dev.phys = kbd->phys; | 290 | kbd->dev.phys = kbd->phys; |
| 298 | kbd->dev.id.bustype = BUS_USB; | 291 | kbd->dev.id.bustype = BUS_USB; |
| 299 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); | 292 | kbd->dev.id.vendor = le16_to_cpu(dev->descriptor.idVendor); |
| 300 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); | 293 | kbd->dev.id.product = le16_to_cpu(dev->descriptor.idProduct); |
| @@ -329,7 +322,7 @@ static int usb_kbd_probe(struct usb_interface *iface, | |||
| 329 | static void usb_kbd_disconnect(struct usb_interface *intf) | 322 | static void usb_kbd_disconnect(struct usb_interface *intf) |
| 330 | { | 323 | { |
| 331 | struct usb_kbd *kbd = usb_get_intfdata (intf); | 324 | struct usb_kbd *kbd = usb_get_intfdata (intf); |
| 332 | 325 | ||
| 333 | usb_set_intfdata(intf, NULL); | 326 | usb_set_intfdata(intf, NULL); |
| 334 | if (kbd) { | 327 | if (kbd) { |
| 335 | usb_kill_urb(kbd->irq); | 328 | usb_kill_urb(kbd->irq); |
diff --git a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c index 01155bbddd43..1ec41b5effe6 100644 --- a/drivers/usb/input/usbmouse.c +++ b/drivers/usb/input/usbmouse.c | |||
| @@ -9,18 +9,18 @@ | |||
| 9 | /* | 9 | /* |
| 10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
| 11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
| 12 | * the Free Software Foundation; either version 2 of the License, or | 12 | * the Free Software Foundation; either version 2 of the License, or |
| 13 | * (at your option) any later version. | 13 | * (at your option) any later version. |
| 14 | * | 14 | * |
| 15 | * This program is distributed in the hope that it will be useful, | 15 | * This program is distributed in the hope that it will be useful, |
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 18 | * GNU General Public License for more details. | 18 | * GNU General Public License for more details. |
| 19 | * | 19 | * |
| 20 | * You should have received a copy of the GNU General Public License | 20 | * You should have received a copy of the GNU General Public License |
| 21 | * along with this program; if not, write to the Free Software | 21 | * along with this program; if not, write to the Free Software |
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 23 | * | 23 | * |
| 24 | * Should you need to contact me, the author, you can do so either by | 24 | * Should you need to contact me, the author, you can do so either by |
| 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: | 25 | * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: |
| 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic | 26 | * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic |
| @@ -51,7 +51,6 @@ struct usb_mouse { | |||
| 51 | struct usb_device *usbdev; | 51 | struct usb_device *usbdev; |
| 52 | struct input_dev dev; | 52 | struct input_dev dev; |
| 53 | struct urb *irq; | 53 | struct urb *irq; |
| 54 | int open; | ||
| 55 | 54 | ||
| 56 | signed char *data; | 55 | signed char *data; |
| 57 | dma_addr_t data_dma; | 56 | dma_addr_t data_dma; |
| @@ -101,14 +100,9 @@ static int usb_mouse_open(struct input_dev *dev) | |||
| 101 | { | 100 | { |
| 102 | struct usb_mouse *mouse = dev->private; | 101 | struct usb_mouse *mouse = dev->private; |
| 103 | 102 | ||
| 104 | if (mouse->open++) | ||
| 105 | return 0; | ||
| 106 | |||
| 107 | mouse->irq->dev = mouse->usbdev; | 103 | mouse->irq->dev = mouse->usbdev; |
| 108 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) { | 104 | if (usb_submit_urb(mouse->irq, GFP_KERNEL)) |
| 109 | mouse->open--; | ||
| 110 | return -EIO; | 105 | return -EIO; |
| 111 | } | ||
| 112 | 106 | ||
| 113 | return 0; | 107 | return 0; |
| 114 | } | 108 | } |
| @@ -117,8 +111,7 @@ static void usb_mouse_close(struct input_dev *dev) | |||
| 117 | { | 111 | { |
| 118 | struct usb_mouse *mouse = dev->private; | 112 | struct usb_mouse *mouse = dev->private; |
| 119 | 113 | ||
| 120 | if (!--mouse->open) | 114 | usb_kill_urb(mouse->irq); |
| 121 | usb_kill_urb(mouse->irq); | ||
| 122 | } | 115 | } |
| 123 | 116 | ||
| 124 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) | 117 | static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_id * id) |
| @@ -132,19 +125,19 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
| 132 | 125 | ||
| 133 | interface = intf->cur_altsetting; | 126 | interface = intf->cur_altsetting; |
| 134 | 127 | ||
| 135 | if (interface->desc.bNumEndpoints != 1) | 128 | if (interface->desc.bNumEndpoints != 1) |
| 136 | return -ENODEV; | 129 | return -ENODEV; |
| 137 | 130 | ||
| 138 | endpoint = &interface->endpoint[0].desc; | 131 | endpoint = &interface->endpoint[0].desc; |
| 139 | if (!(endpoint->bEndpointAddress & 0x80)) | 132 | if (!(endpoint->bEndpointAddress & 0x80)) |
| 140 | return -ENODEV; | 133 | return -ENODEV; |
| 141 | if ((endpoint->bmAttributes & 3) != 3) | 134 | if ((endpoint->bmAttributes & 3) != 3) |
| 142 | return -ENODEV; | 135 | return -ENODEV; |
| 143 | 136 | ||
| 144 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); | 137 | pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); |
| 145 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); | 138 | maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); |
| 146 | 139 | ||
| 147 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) | 140 | if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) |
| 148 | return -ENOMEM; | 141 | return -ENOMEM; |
| 149 | memset(mouse, 0, sizeof(struct usb_mouse)); | 142 | memset(mouse, 0, sizeof(struct usb_mouse)); |
| 150 | 143 | ||
| @@ -209,7 +202,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_ | |||
| 209 | static void usb_mouse_disconnect(struct usb_interface *intf) | 202 | static void usb_mouse_disconnect(struct usb_interface *intf) |
| 210 | { | 203 | { |
| 211 | struct usb_mouse *mouse = usb_get_intfdata (intf); | 204 | struct usb_mouse *mouse = usb_get_intfdata (intf); |
| 212 | 205 | ||
| 213 | usb_set_intfdata(intf, NULL); | 206 | usb_set_intfdata(intf, NULL); |
| 214 | if (mouse) { | 207 | if (mouse) { |
| 215 | usb_kill_urb(mouse->irq); | 208 | usb_kill_urb(mouse->irq); |
| @@ -238,7 +231,7 @@ static struct usb_driver usb_mouse_driver = { | |||
| 238 | static int __init usb_mouse_init(void) | 231 | static int __init usb_mouse_init(void) |
| 239 | { | 232 | { |
| 240 | int retval = usb_register(&usb_mouse_driver); | 233 | int retval = usb_register(&usb_mouse_driver); |
| 241 | if (retval == 0) | 234 | if (retval == 0) |
| 242 | info(DRIVER_VERSION ":" DRIVER_DESC); | 235 | info(DRIVER_VERSION ":" DRIVER_DESC); |
| 243 | return retval; | 236 | return retval; |
| 244 | } | 237 | } |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index fec04dda088e..e37d31b57b23 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | * v0.4 (sm) - Support for more Intuos models, menustrip | 18 | * v0.4 (sm) - Support for more Intuos models, menustrip |
| 19 | * relative mode, proximity. | 19 | * relative mode, proximity. |
| 20 | * v0.5 (vp) - Big cleanup, nifty features removed, | 20 | * v0.5 (vp) - Big cleanup, nifty features removed, |
| 21 | * they belong in userspace | 21 | * they belong in userspace |
| 22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, | 22 | * v1.8 (vp) - Submit URB only when operating, moved to CVS, |
| 23 | * use input_report_key instead of report_btn and | 23 | * use input_report_key instead of report_btn and |
| 24 | * other cleanups | 24 | * other cleanups |
| @@ -102,7 +102,6 @@ struct wacom { | |||
| 102 | struct urb *irq; | 102 | struct urb *irq; |
| 103 | struct wacom_features *features; | 103 | struct wacom_features *features; |
| 104 | int tool[2]; | 104 | int tool[2]; |
| 105 | int open; | ||
| 106 | __u32 serial[2]; | 105 | __u32 serial[2]; |
| 107 | char phys[32]; | 106 | char phys[32]; |
| 108 | }; | 107 | }; |
| @@ -149,7 +148,7 @@ static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs) | |||
| 149 | prox = data[1] & 0x40; | 148 | prox = data[1] & 0x40; |
| 150 | 149 | ||
| 151 | input_regs(dev, regs); | 150 | input_regs(dev, regs); |
| 152 | 151 | ||
| 153 | if (prox) { | 152 | if (prox) { |
| 154 | 153 | ||
| 155 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); | 154 | pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); |
| @@ -545,7 +544,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
| 545 | 544 | ||
| 546 | /* process general packets */ | 545 | /* process general packets */ |
| 547 | wacom_intuos_general(urb); | 546 | wacom_intuos_general(urb); |
| 548 | 547 | ||
| 549 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ | 548 | if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */ |
| 550 | 549 | ||
| 551 | if (data[1] & 0x02) { /* Rotation packet */ | 550 | if (data[1] & 0x02) { /* Rotation packet */ |
| @@ -555,7 +554,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
| 555 | 554 | ||
| 556 | } else { | 555 | } else { |
| 557 | 556 | ||
| 558 | if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ | 557 | if ((data[1] & 0x10) == 0) { /* 4D mouse packets */ |
| 559 | 558 | ||
| 560 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); | 559 | input_report_key(dev, BTN_LEFT, data[8] & 0x01); |
| 561 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); | 560 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); |
| @@ -567,11 +566,11 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
| 567 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); | 566 | input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t); |
| 568 | 567 | ||
| 569 | } else { | 568 | } else { |
| 570 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ | 569 | if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* 2D mouse packets */ |
| 571 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); | 570 | input_report_key(dev, BTN_LEFT, data[8] & 0x04); |
| 572 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); | 571 | input_report_key(dev, BTN_MIDDLE, data[8] & 0x08); |
| 573 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); | 572 | input_report_key(dev, BTN_RIGHT, data[8] & 0x10); |
| 574 | input_report_rel(dev, REL_WHEEL, | 573 | input_report_rel(dev, REL_WHEEL, |
| 575 | (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); | 574 | (-(__u32)(data[8] & 0x01) + (__u32)((data[8] & 0x02) >> 1))); |
| 576 | } | 575 | } |
| 577 | else { /* Lens cursor packets */ | 576 | else { /* Lens cursor packets */ |
| @@ -584,7 +583,7 @@ static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs) | |||
| 584 | } | 583 | } |
| 585 | } | 584 | } |
| 586 | } | 585 | } |
| 587 | 586 | ||
| 588 | input_report_key(dev, wacom->tool[idx], 1); | 587 | input_report_key(dev, wacom->tool[idx], 1); |
| 589 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); | 588 | input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]); |
| 590 | input_sync(dev); | 589 | input_sync(dev); |
| @@ -705,20 +704,20 @@ static struct wacom_features wacom_features[] = { | |||
| 705 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, | 704 | { "Wacom Penpartner", 7, 5040, 3780, 255, 32, 0, wacom_penpartner_irq }, |
| 706 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 705 | { "Wacom Graphire", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, |
| 707 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, | 706 | { "Wacom Graphire2 4x5", 8, 10206, 7422, 511, 32, 1, wacom_graphire_irq }, |
| 708 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, | 707 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, 1, wacom_graphire_irq }, |
| 709 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, | 708 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, 1, wacom_graphire_irq }, |
| 710 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, | 709 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, 1, wacom_graphire_irq }, |
| 711 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 710 | { "Wacom Intuos 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, |
| 712 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 711 | { "Wacom Intuos 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, |
| 713 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 712 | { "Wacom Intuos 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, |
| 714 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, | 713 | { "Wacom Intuos 12x12", 10, 30480, 31680, 1023, 15, 2, wacom_intuos_irq }, |
| 715 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, | 714 | { "Wacom Intuos 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq }, |
| 716 | { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, | 715 | { "Wacom PL400", 8, 5408, 4056, 255, 32, 3, wacom_pl_irq }, |
| 717 | { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, | 716 | { "Wacom PL500", 8, 6144, 4608, 255, 32, 3, wacom_pl_irq }, |
| 718 | { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, | 717 | { "Wacom PL600", 8, 6126, 4604, 255, 32, 3, wacom_pl_irq }, |
| 719 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, | 718 | { "Wacom PL600SX", 8, 6260, 5016, 255, 32, 3, wacom_pl_irq }, |
| 720 | { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, | 719 | { "Wacom PL550", 8, 6144, 4608, 511, 32, 3, wacom_pl_irq }, |
| 721 | { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, | 720 | { "Wacom PL800", 8, 7220, 5780, 511, 32, 3, wacom_pl_irq }, |
| 722 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, | 721 | { "Wacom Intuos2 4x5", 10, 12700, 10600, 1023, 15, 2, wacom_intuos_irq }, |
| 723 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 722 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, |
| 724 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, | 723 | { "Wacom Intuos2 9x12", 10, 30480, 24060, 1023, 15, 2, wacom_intuos_irq }, |
| @@ -730,7 +729,7 @@ static struct wacom_features wacom_features[] = { | |||
| 730 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, | 729 | { "Wacom Intuos3 6x8", 10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq }, |
| 731 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, | 730 | { "Wacom Intuos3 9x12", 10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq }, |
| 732 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, | 731 | { "Wacom Intuos2 6x8", 10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq }, |
| 733 | { } | 732 | { } |
| 734 | }; | 733 | }; |
| 735 | 734 | ||
| 736 | static struct usb_device_id wacom_ids[] = { | 735 | static struct usb_device_id wacom_ids[] = { |
| @@ -771,14 +770,9 @@ static int wacom_open(struct input_dev *dev) | |||
| 771 | { | 770 | { |
| 772 | struct wacom *wacom = dev->private; | 771 | struct wacom *wacom = dev->private; |
| 773 | 772 | ||
| 774 | if (wacom->open++) | ||
| 775 | return 0; | ||
| 776 | |||
| 777 | wacom->irq->dev = wacom->usbdev; | 773 | wacom->irq->dev = wacom->usbdev; |
| 778 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { | 774 | if (usb_submit_urb(wacom->irq, GFP_KERNEL)) |
| 779 | wacom->open--; | ||
| 780 | return -EIO; | 775 | return -EIO; |
| 781 | } | ||
| 782 | 776 | ||
| 783 | return 0; | 777 | return 0; |
| 784 | } | 778 | } |
| @@ -787,8 +781,7 @@ static void wacom_close(struct input_dev *dev) | |||
| 787 | { | 781 | { |
| 788 | struct wacom *wacom = dev->private; | 782 | struct wacom *wacom = dev->private; |
| 789 | 783 | ||
| 790 | if (!--wacom->open) | 784 | usb_kill_urb(wacom->irq); |
| 791 | usb_kill_urb(wacom->irq); | ||
| 792 | } | 785 | } |
| 793 | 786 | ||
| 794 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) | 787 | static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| @@ -828,7 +821,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 828 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 821 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
| 829 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); | 822 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE); |
| 830 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); | 823 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); |
| 831 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); | 824 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2); |
| 832 | break; | 825 | break; |
| 833 | 826 | ||
| 834 | case 4: /* new functions for Intuos3 */ | 827 | case 4: /* new functions for Intuos3 */ |
| @@ -842,13 +835,13 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
| 842 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); | 835 | wacom->dev.mscbit[0] |= BIT(MSC_SERIAL); |
| 843 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); | 836 | wacom->dev.relbit[0] |= BIT(REL_WHEEL); |
| 844 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); | 837 | wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | BIT(BTN_SIDE) | BIT(BTN_EXTRA); |
| 845 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) | 838 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOOL_BRUSH) |
| 846 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); | 839 | | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS) | BIT(BTN_STYLUS2); |
| 847 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); | 840 | wacom->dev.absbit[0] |= BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE); |
| 848 | break; | 841 | break; |
| 849 | 842 | ||
| 850 | case 3: | 843 | case 3: |
| 851 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); | 844 | wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER); |
| 852 | break; | 845 | break; |
| 853 | } | 846 | } |
| 854 | 847 | ||
diff --git a/drivers/usb/input/xpad.c b/drivers/usb/input/xpad.c index d65edb22e545..a7fa1b17dcfe 100644 --- a/drivers/usb/input/xpad.c +++ b/drivers/usb/input/xpad.c | |||
| @@ -104,13 +104,12 @@ MODULE_DEVICE_TABLE (usb, xpad_table); | |||
| 104 | struct usb_xpad { | 104 | struct usb_xpad { |
| 105 | struct input_dev dev; /* input device interface */ | 105 | struct input_dev dev; /* input device interface */ |
| 106 | struct usb_device *udev; /* usb device */ | 106 | struct usb_device *udev; /* usb device */ |
| 107 | 107 | ||
| 108 | struct urb *irq_in; /* urb for interrupt in report */ | 108 | struct urb *irq_in; /* urb for interrupt in report */ |
| 109 | unsigned char *idata; /* input data */ | 109 | unsigned char *idata; /* input data */ |
| 110 | dma_addr_t idata_dma; | 110 | dma_addr_t idata_dma; |
| 111 | 111 | ||
| 112 | char phys[65]; /* physical device path */ | 112 | char phys[65]; /* physical device path */ |
| 113 | int open_count; /* reference count */ | ||
| 114 | }; | 113 | }; |
| 115 | 114 | ||
| 116 | /* | 115 | /* |
| @@ -128,35 +127,35 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d | |||
| 128 | struct input_dev *dev = &xpad->dev; | 127 | struct input_dev *dev = &xpad->dev; |
| 129 | 128 | ||
| 130 | input_regs(dev, regs); | 129 | input_regs(dev, regs); |
| 131 | 130 | ||
| 132 | /* left stick */ | 131 | /* left stick */ |
| 133 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); | 132 | input_report_abs(dev, ABS_X, (__s16) (((__s16)data[13] << 8) | data[12])); |
| 134 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); | 133 | input_report_abs(dev, ABS_Y, (__s16) (((__s16)data[15] << 8) | data[14])); |
| 135 | 134 | ||
| 136 | /* right stick */ | 135 | /* right stick */ |
| 137 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); | 136 | input_report_abs(dev, ABS_RX, (__s16) (((__s16)data[17] << 8) | data[16])); |
| 138 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); | 137 | input_report_abs(dev, ABS_RY, (__s16) (((__s16)data[19] << 8) | data[18])); |
| 139 | 138 | ||
| 140 | /* triggers left/right */ | 139 | /* triggers left/right */ |
| 141 | input_report_abs(dev, ABS_Z, data[10]); | 140 | input_report_abs(dev, ABS_Z, data[10]); |
| 142 | input_report_abs(dev, ABS_RZ, data[11]); | 141 | input_report_abs(dev, ABS_RZ, data[11]); |
| 143 | 142 | ||
| 144 | /* digital pad */ | 143 | /* digital pad */ |
| 145 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); | 144 | input_report_abs(dev, ABS_HAT0X, !!(data[2] & 0x08) - !!(data[2] & 0x04)); |
| 146 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); | 145 | input_report_abs(dev, ABS_HAT0Y, !!(data[2] & 0x02) - !!(data[2] & 0x01)); |
| 147 | 146 | ||
| 148 | /* start/back buttons and stick press left/right */ | 147 | /* start/back buttons and stick press left/right */ |
| 149 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); | 148 | input_report_key(dev, BTN_START, (data[2] & 0x10) >> 4); |
| 150 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); | 149 | input_report_key(dev, BTN_BACK, (data[2] & 0x20) >> 5); |
| 151 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); | 150 | input_report_key(dev, BTN_THUMBL, (data[2] & 0x40) >> 6); |
| 152 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); | 151 | input_report_key(dev, BTN_THUMBR, data[2] >> 7); |
| 153 | 152 | ||
| 154 | /* "analog" buttons A, B, X, Y */ | 153 | /* "analog" buttons A, B, X, Y */ |
| 155 | input_report_key(dev, BTN_A, data[4]); | 154 | input_report_key(dev, BTN_A, data[4]); |
| 156 | input_report_key(dev, BTN_B, data[5]); | 155 | input_report_key(dev, BTN_B, data[5]); |
| 157 | input_report_key(dev, BTN_X, data[6]); | 156 | input_report_key(dev, BTN_X, data[6]); |
| 158 | input_report_key(dev, BTN_Y, data[7]); | 157 | input_report_key(dev, BTN_Y, data[7]); |
| 159 | 158 | ||
| 160 | /* "analog" buttons black, white */ | 159 | /* "analog" buttons black, white */ |
| 161 | input_report_key(dev, BTN_C, data[8]); | 160 | input_report_key(dev, BTN_C, data[8]); |
| 162 | input_report_key(dev, BTN_Z, data[9]); | 161 | input_report_key(dev, BTN_Z, data[9]); |
| @@ -168,7 +167,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
| 168 | { | 167 | { |
| 169 | struct usb_xpad *xpad = urb->context; | 168 | struct usb_xpad *xpad = urb->context; |
| 170 | int retval; | 169 | int retval; |
| 171 | 170 | ||
| 172 | switch (urb->status) { | 171 | switch (urb->status) { |
| 173 | case 0: | 172 | case 0: |
| 174 | /* success */ | 173 | /* success */ |
| @@ -183,7 +182,7 @@ static void xpad_irq_in(struct urb *urb, struct pt_regs *regs) | |||
| 183 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); | 182 | dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); |
| 184 | goto exit; | 183 | goto exit; |
| 185 | } | 184 | } |
| 186 | 185 | ||
| 187 | xpad_process_packet(xpad, 0, xpad->idata, regs); | 186 | xpad_process_packet(xpad, 0, xpad->idata, regs); |
| 188 | 187 | ||
| 189 | exit: | 188 | exit: |
| @@ -196,25 +195,19 @@ exit: | |||
| 196 | static int xpad_open (struct input_dev *dev) | 195 | static int xpad_open (struct input_dev *dev) |
| 197 | { | 196 | { |
| 198 | struct usb_xpad *xpad = dev->private; | 197 | struct usb_xpad *xpad = dev->private; |
| 199 | 198 | ||
| 200 | if (xpad->open_count++) | ||
| 201 | return 0; | ||
| 202 | |||
| 203 | xpad->irq_in->dev = xpad->udev; | 199 | xpad->irq_in->dev = xpad->udev; |
| 204 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) { | 200 | if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) |
| 205 | xpad->open_count--; | ||
| 206 | return -EIO; | 201 | return -EIO; |
| 207 | } | 202 | |
| 208 | |||
| 209 | return 0; | 203 | return 0; |
| 210 | } | 204 | } |
| 211 | 205 | ||
| 212 | static void xpad_close (struct input_dev *dev) | 206 | static void xpad_close (struct input_dev *dev) |
| 213 | { | 207 | { |
| 214 | struct usb_xpad *xpad = dev->private; | 208 | struct usb_xpad *xpad = dev->private; |
| 215 | 209 | ||
| 216 | if (!--xpad->open_count) | 210 | usb_kill_urb(xpad->irq_in); |
| 217 | usb_kill_urb(xpad->irq_in); | ||
| 218 | } | 211 | } |
| 219 | 212 | ||
| 220 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) | 213 | static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| @@ -224,19 +217,19 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 224 | struct usb_endpoint_descriptor *ep_irq_in; | 217 | struct usb_endpoint_descriptor *ep_irq_in; |
| 225 | char path[64]; | 218 | char path[64]; |
| 226 | int i; | 219 | int i; |
| 227 | 220 | ||
| 228 | for (i = 0; xpad_device[i].idVendor; i++) { | 221 | for (i = 0; xpad_device[i].idVendor; i++) { |
| 229 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && | 222 | if ((le16_to_cpu(udev->descriptor.idVendor) == xpad_device[i].idVendor) && |
| 230 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) | 223 | (le16_to_cpu(udev->descriptor.idProduct) == xpad_device[i].idProduct)) |
| 231 | break; | 224 | break; |
| 232 | } | 225 | } |
| 233 | 226 | ||
| 234 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { | 227 | if ((xpad = kmalloc (sizeof(struct usb_xpad), GFP_KERNEL)) == NULL) { |
| 235 | err("cannot allocate memory for new pad"); | 228 | err("cannot allocate memory for new pad"); |
| 236 | return -ENOMEM; | 229 | return -ENOMEM; |
| 237 | } | 230 | } |
| 238 | memset(xpad, 0, sizeof(struct usb_xpad)); | 231 | memset(xpad, 0, sizeof(struct usb_xpad)); |
| 239 | 232 | ||
| 240 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, | 233 | xpad->idata = usb_buffer_alloc(udev, XPAD_PKT_LEN, |
| 241 | SLAB_ATOMIC, &xpad->idata_dma); | 234 | SLAB_ATOMIC, &xpad->idata_dma); |
| 242 | if (!xpad->idata) { | 235 | if (!xpad->idata) { |
| @@ -251,18 +244,18 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 251 | kfree(xpad); | 244 | kfree(xpad); |
| 252 | return -ENOMEM; | 245 | return -ENOMEM; |
| 253 | } | 246 | } |
| 254 | 247 | ||
| 255 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; | 248 | ep_irq_in = &intf->cur_altsetting->endpoint[0].desc; |
| 256 | 249 | ||
| 257 | usb_fill_int_urb(xpad->irq_in, udev, | 250 | usb_fill_int_urb(xpad->irq_in, udev, |
| 258 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), | 251 | usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), |
| 259 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, | 252 | xpad->idata, XPAD_PKT_LEN, xpad_irq_in, |
| 260 | xpad, ep_irq_in->bInterval); | 253 | xpad, ep_irq_in->bInterval); |
| 261 | xpad->irq_in->transfer_dma = xpad->idata_dma; | 254 | xpad->irq_in->transfer_dma = xpad->idata_dma; |
| 262 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 255 | xpad->irq_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 263 | 256 | ||
| 264 | xpad->udev = udev; | 257 | xpad->udev = udev; |
| 265 | 258 | ||
| 266 | xpad->dev.id.bustype = BUS_USB; | 259 | xpad->dev.id.bustype = BUS_USB; |
| 267 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); | 260 | xpad->dev.id.vendor = le16_to_cpu(udev->descriptor.idVendor); |
| 268 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); | 261 | xpad->dev.id.product = le16_to_cpu(udev->descriptor.idProduct); |
| @@ -273,21 +266,21 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 273 | xpad->dev.phys = xpad->phys; | 266 | xpad->dev.phys = xpad->phys; |
| 274 | xpad->dev.open = xpad_open; | 267 | xpad->dev.open = xpad_open; |
| 275 | xpad->dev.close = xpad_close; | 268 | xpad->dev.close = xpad_close; |
| 276 | 269 | ||
| 277 | usb_make_path(udev, path, 64); | 270 | usb_make_path(udev, path, 64); |
| 278 | snprintf(xpad->phys, 64, "%s/input0", path); | 271 | snprintf(xpad->phys, 64, "%s/input0", path); |
| 279 | 272 | ||
| 280 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | 273 | xpad->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); |
| 281 | 274 | ||
| 282 | for (i = 0; xpad_btn[i] >= 0; i++) | 275 | for (i = 0; xpad_btn[i] >= 0; i++) |
| 283 | set_bit(xpad_btn[i], xpad->dev.keybit); | 276 | set_bit(xpad_btn[i], xpad->dev.keybit); |
| 284 | 277 | ||
| 285 | for (i = 0; xpad_abs[i] >= 0; i++) { | 278 | for (i = 0; xpad_abs[i] >= 0; i++) { |
| 286 | 279 | ||
| 287 | signed short t = xpad_abs[i]; | 280 | signed short t = xpad_abs[i]; |
| 288 | 281 | ||
| 289 | set_bit(t, xpad->dev.absbit); | 282 | set_bit(t, xpad->dev.absbit); |
| 290 | 283 | ||
| 291 | switch (t) { | 284 | switch (t) { |
| 292 | case ABS_X: | 285 | case ABS_X: |
| 293 | case ABS_Y: | 286 | case ABS_Y: |
| @@ -310,11 +303,11 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 310 | break; | 303 | break; |
| 311 | } | 304 | } |
| 312 | } | 305 | } |
| 313 | 306 | ||
| 314 | input_register_device(&xpad->dev); | 307 | input_register_device(&xpad->dev); |
| 315 | 308 | ||
| 316 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); | 309 | printk(KERN_INFO "input: %s on %s", xpad->dev.name, path); |
| 317 | 310 | ||
| 318 | usb_set_intfdata(intf, xpad); | 311 | usb_set_intfdata(intf, xpad); |
| 319 | return 0; | 312 | return 0; |
| 320 | } | 313 | } |
| @@ -322,7 +315,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id | |||
| 322 | static void xpad_disconnect(struct usb_interface *intf) | 315 | static void xpad_disconnect(struct usb_interface *intf) |
| 323 | { | 316 | { |
| 324 | struct usb_xpad *xpad = usb_get_intfdata (intf); | 317 | struct usb_xpad *xpad = usb_get_intfdata (intf); |
| 325 | 318 | ||
| 326 | usb_set_intfdata(intf, NULL); | 319 | usb_set_intfdata(intf, NULL); |
| 327 | if (xpad) { | 320 | if (xpad) { |
| 328 | usb_kill_urb(xpad->irq_in); | 321 | usb_kill_urb(xpad->irq_in); |
diff --git a/include/linux/input.h b/include/linux/input.h index 72731d7d189e..43e8ecec602b 100644 --- a/include/linux/input.h +++ b/include/linux/input.h | |||
| @@ -859,6 +859,10 @@ struct input_dev { | |||
| 859 | int (*erase_effect)(struct input_dev *dev, int effect_id); | 859 | int (*erase_effect)(struct input_dev *dev, int effect_id); |
| 860 | 860 | ||
| 861 | struct input_handle *grab; | 861 | struct input_handle *grab; |
| 862 | |||
| 863 | struct semaphore sem; /* serializes open and close operations */ | ||
| 864 | unsigned int users; | ||
| 865 | |||
| 862 | struct device *dev; | 866 | struct device *dev; |
| 863 | 867 | ||
| 864 | struct list_head h_list; | 868 | struct list_head h_list; |
diff --git a/include/linux/joystick.h b/include/linux/joystick.h index b7e0ab622cd7..06b9af77eb7f 100644 --- a/include/linux/joystick.h +++ b/include/linux/joystick.h | |||
| @@ -111,18 +111,35 @@ struct js_corr { | |||
| 111 | #define JS_SET_ALL 8 | 111 | #define JS_SET_ALL 8 |
| 112 | 112 | ||
| 113 | struct JS_DATA_TYPE { | 113 | struct JS_DATA_TYPE { |
| 114 | int buttons; | 114 | __s32 buttons; |
| 115 | int x; | 115 | __s32 x; |
| 116 | int y; | 116 | __s32 y; |
| 117 | }; | 117 | }; |
| 118 | 118 | ||
| 119 | struct JS_DATA_SAVE_TYPE { | 119 | struct JS_DATA_SAVE_TYPE_32 { |
| 120 | int JS_TIMEOUT; | 120 | __s32 JS_TIMEOUT; |
| 121 | int BUSY; | 121 | __s32 BUSY; |
| 122 | long JS_EXPIRETIME; | 122 | __s32 JS_EXPIRETIME; |
| 123 | long JS_TIMELIMIT; | 123 | __s32 JS_TIMELIMIT; |
| 124 | struct JS_DATA_TYPE JS_SAVE; | 124 | struct JS_DATA_TYPE JS_SAVE; |
| 125 | struct JS_DATA_TYPE JS_CORR; | 125 | struct JS_DATA_TYPE JS_CORR; |
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | struct JS_DATA_SAVE_TYPE_64 { | ||
| 129 | __s32 JS_TIMEOUT; | ||
| 130 | __s32 BUSY; | ||
| 131 | __s64 JS_EXPIRETIME; | ||
| 132 | __s64 JS_TIMELIMIT; | ||
| 133 | struct JS_DATA_TYPE JS_SAVE; | ||
| 134 | struct JS_DATA_TYPE JS_CORR; | ||
| 135 | }; | ||
| 136 | |||
| 137 | #if BITS_PER_LONG == 64 | ||
| 138 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_64 | ||
| 139 | #elif BITS_PER_LONG == 32 | ||
| 140 | #define JS_DATA_SAVE_TYPE JS_DATA_SAVE_TYPE_32 | ||
| 141 | #else | ||
| 142 | #error Unexpected BITS_PER_LONG | ||
| 143 | #endif | ||
| 144 | |||
| 128 | #endif /* _LINUX_JOYSTICK_H */ | 145 | #endif /* _LINUX_JOYSTICK_H */ |
diff --git a/include/linux/libps2.h b/include/linux/libps2.h index 923bdbc6d9e4..a710bddda4eb 100644 --- a/include/linux/libps2.h +++ b/include/linux/libps2.h | |||
| @@ -41,6 +41,7 @@ struct ps2dev { | |||
| 41 | 41 | ||
| 42 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); | 42 | void ps2_init(struct ps2dev *ps2dev, struct serio *serio); |
| 43 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); | 43 | int ps2_sendbyte(struct ps2dev *ps2dev, unsigned char byte, int timeout); |
| 44 | void ps2_drain(struct ps2dev *ps2dev, int maxbytes, int timeout); | ||
| 44 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 45 | int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 45 | int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); | 46 | int ps2_schedule_command(struct ps2dev *ps2dev, unsigned char *param, int command); |
| 46 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); | 47 | int ps2_handle_ack(struct ps2dev *ps2dev, unsigned char data); |
diff --git a/include/linux/serio.h b/include/linux/serio.h index a2d3b9ae06f4..aa4d6493a034 100644 --- a/include/linux/serio.h +++ b/include/linux/serio.h | |||
| @@ -83,6 +83,7 @@ static inline void serio_register_port(struct serio *serio) | |||
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | void serio_unregister_port(struct serio *serio); | 85 | void serio_unregister_port(struct serio *serio); |
| 86 | void serio_unregister_child_port(struct serio *serio); | ||
| 86 | void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); | 87 | void __serio_unregister_port_delayed(struct serio *serio, struct module *owner); |
| 87 | static inline void serio_unregister_port_delayed(struct serio *serio) | 88 | static inline void serio_unregister_port_delayed(struct serio *serio) |
| 88 | { | 89 | { |
| @@ -153,6 +154,11 @@ static inline int serio_pin_driver(struct serio *serio) | |||
| 153 | return down_interruptible(&serio->drv_sem); | 154 | return down_interruptible(&serio->drv_sem); |
| 154 | } | 155 | } |
| 155 | 156 | ||
| 157 | static inline void serio_pin_driver_uninterruptible(struct serio *serio) | ||
| 158 | { | ||
| 159 | down(&serio->drv_sem); | ||
| 160 | } | ||
| 161 | |||
| 156 | static inline void serio_unpin_driver(struct serio *serio) | 162 | static inline void serio_unpin_driver(struct serio *serio) |
| 157 | { | 163 | { |
| 158 | up(&serio->drv_sem); | 164 | up(&serio->drv_sem); |
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index e537bd66a707..33e28089f8d7 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig | |||
| @@ -52,7 +52,7 @@ config SOUND_CMPCI_MIDI | |||
| 52 | 52 | ||
| 53 | config SOUND_CMPCI_JOYSTICK | 53 | config SOUND_CMPCI_JOYSTICK |
| 54 | bool "Enable joystick" | 54 | bool "Enable joystick" |
| 55 | depends on SOUND_CMPCI && X86 | 55 | depends on SOUND_CMPCI && X86 && (GAMEPORT=y || SOUND_CMPCI=GAMEPORT) |
| 56 | help | 56 | help |
| 57 | Say Y here in order to enable the joystick port on a sound card using | 57 | Say Y here in order to enable the joystick port on a sound card using |
| 58 | the CMI8338 or the CMI8738 chipset. You need to config the | 58 | the CMI8338 or the CMI8738 chipset. You need to config the |
diff --git a/sound/oss/es1370.c b/sound/oss/es1370.c index 056091cff266..563a52fbdd39 100644 --- a/sound/oss/es1370.c +++ b/sound/oss/es1370.c | |||
| @@ -161,6 +161,10 @@ | |||
| 161 | #include <asm/page.h> | 161 | #include <asm/page.h> |
| 162 | #include <asm/uaccess.h> | 162 | #include <asm/uaccess.h> |
| 163 | 163 | ||
| 164 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 165 | #define SUPPORT_JOYSTICK | ||
| 166 | #endif | ||
| 167 | |||
| 164 | /* --------------------------------------------------------------------- */ | 168 | /* --------------------------------------------------------------------- */ |
| 165 | 169 | ||
| 166 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 170 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
| @@ -384,7 +388,10 @@ struct es1370_state { | |||
| 384 | unsigned char obuf[MIDIOUTBUF]; | 388 | unsigned char obuf[MIDIOUTBUF]; |
| 385 | } midi; | 389 | } midi; |
| 386 | 390 | ||
| 391 | #ifdef SUPPORT_JOYSTICK | ||
| 387 | struct gameport *gameport; | 392 | struct gameport *gameport; |
| 393 | #endif | ||
| 394 | |||
| 388 | struct semaphore sem; | 395 | struct semaphore sem; |
| 389 | }; | 396 | }; |
| 390 | 397 | ||
| @@ -2553,10 +2560,55 @@ static struct initvol { | |||
| 2553 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } | 2560 | { SOUND_MIXER_WRITE_OGAIN, 0x4040 } |
| 2554 | }; | 2561 | }; |
| 2555 | 2562 | ||
| 2563 | #ifdef SUPPORT_JOYSTICK | ||
| 2564 | |||
| 2565 | static int __devinit es1370_register_gameport(struct es1370_state *s) | ||
| 2566 | { | ||
| 2567 | struct gameport *gp; | ||
| 2568 | |||
| 2569 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
| 2570 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
| 2571 | return -EBUSY; | ||
| 2572 | } | ||
| 2573 | |||
| 2574 | s->gameport = gp = gameport_allocate_port(); | ||
| 2575 | if (!gp) { | ||
| 2576 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
| 2577 | release_region(0x200, JOY_EXTENT); | ||
| 2578 | return -ENOMEM; | ||
| 2579 | } | ||
| 2580 | |||
| 2581 | gameport_set_name(gp, "ESS1370"); | ||
| 2582 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
| 2583 | gp->dev.parent = &s->dev->dev; | ||
| 2584 | gp->io = 0x200; | ||
| 2585 | |||
| 2586 | s->ctrl |= CTRL_JYSTK_EN; | ||
| 2587 | outl(s->ctrl, s->io + ES1370_REG_CONTROL); | ||
| 2588 | |||
| 2589 | gameport_register_port(gp); | ||
| 2590 | |||
| 2591 | return 0; | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | static inline void es1370_unregister_gameport(struct es1370_state *s) | ||
| 2595 | { | ||
| 2596 | if (s->gameport) { | ||
| 2597 | int gpio = s->gameport->io; | ||
| 2598 | gameport_unregister_port(s->gameport); | ||
| 2599 | release_region(gpio, JOY_EXTENT); | ||
| 2600 | |||
| 2601 | } | ||
| 2602 | } | ||
| 2603 | |||
| 2604 | #else | ||
| 2605 | static inline int es1370_register_gameport(struct es1370_state *s) { return -ENOSYS; } | ||
| 2606 | static inline void es1370_unregister_gameport(struct es1370_state *s) { } | ||
| 2607 | #endif /* SUPPORT_JOYSTICK */ | ||
| 2608 | |||
| 2556 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2609 | static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
| 2557 | { | 2610 | { |
| 2558 | struct es1370_state *s; | 2611 | struct es1370_state *s; |
| 2559 | struct gameport *gp = NULL; | ||
| 2560 | mm_segment_t fs; | 2612 | mm_segment_t fs; |
| 2561 | int i, val, ret; | 2613 | int i, val, ret; |
| 2562 | 2614 | ||
| @@ -2605,28 +2657,14 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2605 | /* note: setting CTRL_SERR_DIS is reported to break | 2657 | /* note: setting CTRL_SERR_DIS is reported to break |
| 2606 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ | 2658 | * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */ |
| 2607 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); | 2659 | s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL); |
| 2608 | if (!request_region(0x200, JOY_EXTENT, "es1370")) { | ||
| 2609 | printk(KERN_ERR "es1370: joystick io port 0x200 in use\n"); | ||
| 2610 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
| 2611 | printk(KERN_ERR "es1370: can not allocate memory for gameport\n"); | ||
| 2612 | release_region(0x200, JOY_EXTENT); | ||
| 2613 | } else { | ||
| 2614 | gameport_set_name(gp, "ESS1370"); | ||
| 2615 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev)); | ||
| 2616 | gp->dev.parent = &s->dev->dev; | ||
| 2617 | gp->io = 0x200; | ||
| 2618 | s->ctrl |= CTRL_JYSTK_EN; | ||
| 2619 | } | ||
| 2620 | if (lineout[devindex]) | 2660 | if (lineout[devindex]) |
| 2621 | s->ctrl |= CTRL_XCTL0; | 2661 | s->ctrl |= CTRL_XCTL0; |
| 2622 | if (micbias[devindex]) | 2662 | if (micbias[devindex]) |
| 2623 | s->ctrl |= CTRL_XCTL1; | 2663 | s->ctrl |= CTRL_XCTL1; |
| 2624 | s->sctrl = 0; | 2664 | s->sctrl = 0; |
| 2625 | printk(KERN_INFO "es1370: found adapter at io %#lx irq %u\n" | 2665 | printk(KERN_INFO "es1370: adapter at io %#lx irq %u, line %s, mic impedance %s\n", |
| 2626 | KERN_INFO "es1370: features: joystick %s, line %s, mic impedance %s\n", | 2666 | s->io, s->irq, (s->ctrl & CTRL_XCTL0) ? "out" : "in", |
| 2627 | s->io, s->irq, (s->ctrl & CTRL_JYSTK_EN) ? "on" : "off", | 2667 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); |
| 2628 | (s->ctrl & CTRL_XCTL0) ? "out" : "in", | ||
| 2629 | (s->ctrl & CTRL_XCTL1) ? "1" : "0"); | ||
| 2630 | /* register devices */ | 2668 | /* register devices */ |
| 2631 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { | 2669 | if ((s->dev_audio = register_sound_dsp(&es1370_audio_fops, -1)) < 0) { |
| 2632 | ret = s->dev_audio; | 2670 | ret = s->dev_audio; |
| @@ -2672,9 +2710,7 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2672 | } | 2710 | } |
| 2673 | set_fs(fs); | 2711 | set_fs(fs); |
| 2674 | 2712 | ||
| 2675 | /* register gameport */ | 2713 | es1370_register_gameport(s); |
| 2676 | if (gp) | ||
| 2677 | gameport_register_port(gp); | ||
| 2678 | 2714 | ||
| 2679 | /* store it in the driver field */ | 2715 | /* store it in the driver field */ |
| 2680 | pci_set_drvdata(pcidev, s); | 2716 | pci_set_drvdata(pcidev, s); |
| @@ -2696,10 +2732,6 @@ static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2696 | err_dev1: | 2732 | err_dev1: |
| 2697 | printk(KERN_ERR "es1370: cannot register misc device\n"); | 2733 | printk(KERN_ERR "es1370: cannot register misc device\n"); |
| 2698 | free_irq(s->irq, s); | 2734 | free_irq(s->irq, s); |
| 2699 | if (s->gameport) { | ||
| 2700 | release_region(s->gameport->io, JOY_EXTENT); | ||
| 2701 | gameport_free_port(s->gameport); | ||
| 2702 | } | ||
| 2703 | err_irq: | 2735 | err_irq: |
| 2704 | release_region(s->io, ES1370_EXTENT); | 2736 | release_region(s->io, ES1370_EXTENT); |
| 2705 | err_region: | 2737 | err_region: |
| @@ -2718,11 +2750,7 @@ static void __devexit es1370_remove(struct pci_dev *dev) | |||
| 2718 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 2750 | outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
| 2719 | synchronize_irq(s->irq); | 2751 | synchronize_irq(s->irq); |
| 2720 | free_irq(s->irq, s); | 2752 | free_irq(s->irq, s); |
| 2721 | if (s->gameport) { | 2753 | es1370_unregister_gameport(s); |
| 2722 | int gpio = s->gameport->io; | ||
| 2723 | gameport_unregister_port(s->gameport); | ||
| 2724 | release_region(gpio, JOY_EXTENT); | ||
| 2725 | } | ||
| 2726 | release_region(s->io, ES1370_EXTENT); | 2754 | release_region(s->io, ES1370_EXTENT); |
| 2727 | unregister_sound_dsp(s->dev_audio); | 2755 | unregister_sound_dsp(s->dev_audio); |
| 2728 | unregister_sound_mixer(s->dev_mixer); | 2756 | unregister_sound_mixer(s->dev_mixer); |
diff --git a/sound/oss/es1371.c b/sound/oss/es1371.c index a50fddaeea21..c38ae1eca25f 100644 --- a/sound/oss/es1371.c +++ b/sound/oss/es1371.c | |||
| @@ -133,6 +133,10 @@ | |||
| 133 | #include <asm/page.h> | 133 | #include <asm/page.h> |
| 134 | #include <asm/uaccess.h> | 134 | #include <asm/uaccess.h> |
| 135 | 135 | ||
| 136 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 137 | #define SUPPORT_JOYSTICK | ||
| 138 | #endif | ||
| 139 | |||
| 136 | /* --------------------------------------------------------------------- */ | 140 | /* --------------------------------------------------------------------- */ |
| 137 | 141 | ||
| 138 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS | 142 | #undef OSS_DOCUMENTED_MIXER_SEMANTICS |
| @@ -453,7 +457,10 @@ struct es1371_state { | |||
| 453 | unsigned char obuf[MIDIOUTBUF]; | 457 | unsigned char obuf[MIDIOUTBUF]; |
| 454 | } midi; | 458 | } midi; |
| 455 | 459 | ||
| 460 | #ifdef SUPPORT_JOYSTICK | ||
| 456 | struct gameport *gameport; | 461 | struct gameport *gameport; |
| 462 | #endif | ||
| 463 | |||
| 457 | struct semaphore sem; | 464 | struct semaphore sem; |
| 458 | }; | 465 | }; |
| 459 | 466 | ||
| @@ -2786,12 +2793,63 @@ static struct | |||
| 2786 | { PCI_ANY_ID, PCI_ANY_ID } | 2793 | { PCI_ANY_ID, PCI_ANY_ID } |
| 2787 | }; | 2794 | }; |
| 2788 | 2795 | ||
| 2796 | #ifdef SUPPORT_JOYSTICK | ||
| 2797 | |||
| 2798 | static int __devinit es1371_register_gameport(struct es1371_state *s) | ||
| 2799 | { | ||
| 2800 | struct gameport *gp; | ||
| 2801 | int gpio; | ||
| 2802 | |||
| 2803 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
| 2804 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
| 2805 | break; | ||
| 2806 | |||
| 2807 | if (gpio < 0x200) { | ||
| 2808 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
| 2809 | return -EBUSY; | ||
| 2810 | } | ||
| 2811 | |||
| 2812 | s->gameport = gp = gameport_allocate_port(); | ||
| 2813 | if (!gp) { | ||
| 2814 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
| 2815 | release_region(gpio, JOY_EXTENT); | ||
| 2816 | return -ENOMEM; | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
| 2820 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
| 2821 | gp->dev.parent = &s->dev->dev; | ||
| 2822 | gp->io = gpio; | ||
| 2823 | |||
| 2824 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
| 2825 | outl(s->ctrl, s->io + ES1371_REG_CONTROL); | ||
| 2826 | |||
| 2827 | gameport_register_port(gp); | ||
| 2828 | |||
| 2829 | return 0; | ||
| 2830 | } | ||
| 2831 | |||
| 2832 | static inline void es1371_unregister_gameport(struct es1371_state *s) | ||
| 2833 | { | ||
| 2834 | if (s->gameport) { | ||
| 2835 | int gpio = s->gameport->io; | ||
| 2836 | gameport_unregister_port(s->gameport); | ||
| 2837 | release_region(gpio, JOY_EXTENT); | ||
| 2838 | |||
| 2839 | } | ||
| 2840 | } | ||
| 2841 | |||
| 2842 | #else | ||
| 2843 | static inline int es1371_register_gameport(struct es1371_state *s) { return -ENOSYS; } | ||
| 2844 | static inline void es1371_unregister_gameport(struct es1371_state *s) { } | ||
| 2845 | #endif /* SUPPORT_JOYSTICK */ | ||
| 2846 | |||
| 2847 | |||
| 2789 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2848 | static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
| 2790 | { | 2849 | { |
| 2791 | struct es1371_state *s; | 2850 | struct es1371_state *s; |
| 2792 | struct gameport *gp; | ||
| 2793 | mm_segment_t fs; | 2851 | mm_segment_t fs; |
| 2794 | int i, gpio, val, res = -1; | 2852 | int i, val, res = -1; |
| 2795 | int idx; | 2853 | int idx; |
| 2796 | unsigned long tmo; | 2854 | unsigned long tmo; |
| 2797 | signed long tmo2; | 2855 | signed long tmo2; |
| @@ -2882,23 +2940,6 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2882 | } | 2940 | } |
| 2883 | } | 2941 | } |
| 2884 | 2942 | ||
| 2885 | for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08) | ||
| 2886 | if (request_region(gpio, JOY_EXTENT, "es1371")) | ||
| 2887 | break; | ||
| 2888 | |||
| 2889 | if (gpio < 0x200) { | ||
| 2890 | printk(KERN_ERR PFX "no free joystick address found\n"); | ||
| 2891 | } else if (!(s->gameport = gp = gameport_allocate_port())) { | ||
| 2892 | printk(KERN_ERR PFX "can not allocate memory for gameport\n"); | ||
| 2893 | release_region(gpio, JOY_EXTENT); | ||
| 2894 | } else { | ||
| 2895 | gameport_set_name(gp, "ESS1371 Gameport"); | ||
| 2896 | gameport_set_phys(gp, "isa%04x/gameport0", gpio); | ||
| 2897 | gp->dev.parent = &s->dev->dev; | ||
| 2898 | gp->io = gpio; | ||
| 2899 | s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT); | ||
| 2900 | } | ||
| 2901 | |||
| 2902 | s->sctrl = 0; | 2943 | s->sctrl = 0; |
| 2903 | cssr = 0; | 2944 | cssr = 0; |
| 2904 | s->spdif_volume = -1; | 2945 | s->spdif_volume = -1; |
| @@ -2968,9 +3009,7 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2968 | /* turn on S/PDIF output driver if requested */ | 3009 | /* turn on S/PDIF output driver if requested */ |
| 2969 | outl(cssr, s->io+ES1371_REG_STATUS); | 3010 | outl(cssr, s->io+ES1371_REG_STATUS); |
| 2970 | 3011 | ||
| 2971 | /* register gameport */ | 3012 | es1371_register_gameport(s); |
| 2972 | if (s->gameport) | ||
| 2973 | gameport_register_port(s->gameport); | ||
| 2974 | 3013 | ||
| 2975 | /* store it in the driver field */ | 3014 | /* store it in the driver field */ |
| 2976 | pci_set_drvdata(pcidev, s); | 3015 | pci_set_drvdata(pcidev, s); |
| @@ -2979,13 +3018,9 @@ static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_devic | |||
| 2979 | /* increment devindex */ | 3018 | /* increment devindex */ |
| 2980 | if (devindex < NR_DEVICE-1) | 3019 | if (devindex < NR_DEVICE-1) |
| 2981 | devindex++; | 3020 | devindex++; |
| 2982 | return 0; | 3021 | return 0; |
| 2983 | 3022 | ||
| 2984 | err_gp: | 3023 | err_gp: |
| 2985 | if (s->gameport) { | ||
| 2986 | release_region(s->gameport->io, JOY_EXTENT); | ||
| 2987 | gameport_free_port(s->gameport); | ||
| 2988 | } | ||
| 2989 | #ifdef ES1371_DEBUG | 3024 | #ifdef ES1371_DEBUG |
| 2990 | if (s->ps) | 3025 | if (s->ps) |
| 2991 | remove_proc_entry("es1371", NULL); | 3026 | remove_proc_entry("es1371", NULL); |
| @@ -3024,11 +3059,7 @@ static void __devexit es1371_remove(struct pci_dev *dev) | |||
| 3024 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ | 3059 | outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */ |
| 3025 | synchronize_irq(s->irq); | 3060 | synchronize_irq(s->irq); |
| 3026 | free_irq(s->irq, s); | 3061 | free_irq(s->irq, s); |
| 3027 | if (s->gameport) { | 3062 | es1371_unregister_gameport(s); |
| 3028 | int gpio = s->gameport->io; | ||
| 3029 | gameport_unregister_port(s->gameport); | ||
| 3030 | release_region(gpio, JOY_EXTENT); | ||
| 3031 | } | ||
| 3032 | release_region(s->io, ES1371_EXTENT); | 3063 | release_region(s->io, ES1371_EXTENT); |
| 3033 | unregister_sound_dsp(s->dev_audio); | 3064 | unregister_sound_dsp(s->dev_audio); |
| 3034 | unregister_sound_mixer(s->codec->dev_mixer); | 3065 | unregister_sound_mixer(s->codec->dev_mixer); |
diff --git a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c index 6b3b9a99579d..a682ab1242cc 100644 --- a/sound/oss/esssolo1.c +++ b/sound/oss/esssolo1.c | |||
| @@ -149,6 +149,10 @@ | |||
| 149 | 149 | ||
| 150 | #define FMODE_DMFM 0x10 | 150 | #define FMODE_DMFM 0x10 |
| 151 | 151 | ||
| 152 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 153 | #define SUPPORT_JOYSTICK 1 | ||
| 154 | #endif | ||
| 155 | |||
| 152 | static struct pci_driver solo1_driver; | 156 | static struct pci_driver solo1_driver; |
| 153 | 157 | ||
| 154 | /* --------------------------------------------------------------------- */ | 158 | /* --------------------------------------------------------------------- */ |
| @@ -226,7 +230,9 @@ struct solo1_state { | |||
| 226 | unsigned char obuf[MIDIOUTBUF]; | 230 | unsigned char obuf[MIDIOUTBUF]; |
| 227 | } midi; | 231 | } midi; |
| 228 | 232 | ||
| 233 | #if SUPPORT_JOYSTICK | ||
| 229 | struct gameport *gameport; | 234 | struct gameport *gameport; |
| 235 | #endif | ||
| 230 | }; | 236 | }; |
| 231 | 237 | ||
| 232 | /* --------------------------------------------------------------------- */ | 238 | /* --------------------------------------------------------------------- */ |
| @@ -2280,6 +2286,7 @@ solo1_resume(struct pci_dev *pci_dev) { | |||
| 2280 | return 0; | 2286 | return 0; |
| 2281 | } | 2287 | } |
| 2282 | 2288 | ||
| 2289 | #ifdef SUPPORT_JOYSTICK | ||
| 2283 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | 2290 | static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) |
| 2284 | { | 2291 | { |
| 2285 | struct gameport *gp; | 2292 | struct gameport *gp; |
| @@ -2306,6 +2313,19 @@ static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port) | |||
| 2306 | return 0; | 2313 | return 0; |
| 2307 | } | 2314 | } |
| 2308 | 2315 | ||
| 2316 | static inline void solo1_unregister_gameport(struct solo1_state *s) | ||
| 2317 | { | ||
| 2318 | if (s->gameport) { | ||
| 2319 | int gpio = s->gameport->io; | ||
| 2320 | gameport_unregister_port(s->gameport); | ||
| 2321 | release_region(gpio, GAMEPORT_EXTENT); | ||
| 2322 | } | ||
| 2323 | } | ||
| 2324 | #else | ||
| 2325 | static inline int solo1_register_gameport(struct solo1_state *s, int io_port) { return -ENOSYS; } | ||
| 2326 | static inline void solo1_unregister_gameport(struct solo1_state *s) { } | ||
| 2327 | #endif /* SUPPORT_JOYSTICK */ | ||
| 2328 | |||
| 2309 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2329 | static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
| 2310 | { | 2330 | { |
| 2311 | struct solo1_state *s; | 2331 | struct solo1_state *s; |
| @@ -2437,11 +2457,7 @@ static void __devexit solo1_remove(struct pci_dev *dev) | |||
| 2437 | synchronize_irq(s->irq); | 2457 | synchronize_irq(s->irq); |
| 2438 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ | 2458 | pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */ |
| 2439 | free_irq(s->irq, s); | 2459 | free_irq(s->irq, s); |
| 2440 | if (s->gameport) { | 2460 | solo1_unregister_gameport(s); |
| 2441 | int gpio = s->gameport->io; | ||
| 2442 | gameport_unregister_port(s->gameport); | ||
| 2443 | release_region(gpio, GAMEPORT_EXTENT); | ||
| 2444 | } | ||
| 2445 | release_region(s->iobase, IOBASE_EXTENT); | 2461 | release_region(s->iobase, IOBASE_EXTENT); |
| 2446 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); | 2462 | release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT); |
| 2447 | release_region(s->ddmabase, DDMABASE_EXTENT); | 2463 | release_region(s->ddmabase, DDMABASE_EXTENT); |
diff --git a/sound/oss/mad16.c b/sound/oss/mad16.c index a7067f169919..aa3c50db66c4 100644 --- a/sound/oss/mad16.c +++ b/sound/oss/mad16.c | |||
| @@ -50,9 +50,12 @@ | |||
| 50 | #include "sb.h" | 50 | #include "sb.h" |
| 51 | #include "mpu401.h" | 51 | #include "mpu401.h" |
| 52 | 52 | ||
| 53 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 54 | #define SUPPORT_JOYSTICK 1 | ||
| 55 | #endif | ||
| 56 | |||
| 53 | static int mad16_conf; | 57 | static int mad16_conf; |
| 54 | static int mad16_cdsel; | 58 | static int mad16_cdsel; |
| 55 | static struct gameport *gameport; | ||
| 56 | static DEFINE_SPINLOCK(lock); | 59 | static DEFINE_SPINLOCK(lock); |
| 57 | 60 | ||
| 58 | #define C928 1 | 61 | #define C928 1 |
| @@ -902,6 +905,10 @@ static int __initdata irq_map[16] = | |||
| 902 | -1, -1, -1, -1 | 905 | -1, -1, -1, -1 |
| 903 | }; | 906 | }; |
| 904 | 907 | ||
| 908 | #ifdef SUPPORT_JOYSTICK | ||
| 909 | |||
| 910 | static struct gameport *gameport; | ||
| 911 | |||
| 905 | static int __devinit mad16_register_gameport(int io_port) | 912 | static int __devinit mad16_register_gameport(int io_port) |
| 906 | { | 913 | { |
| 907 | if (!request_region(io_port, 1, "mad16 gameport")) { | 914 | if (!request_region(io_port, 1, "mad16 gameport")) { |
| @@ -925,6 +932,20 @@ static int __devinit mad16_register_gameport(int io_port) | |||
| 925 | return 0; | 932 | return 0; |
| 926 | } | 933 | } |
| 927 | 934 | ||
| 935 | static inline void mad16_unregister_gameport(void) | ||
| 936 | { | ||
| 937 | if (gameport) { | ||
| 938 | /* the gameport was initialized so we must free it up */ | ||
| 939 | gameport_unregister_port(gameport); | ||
| 940 | gameport = NULL; | ||
| 941 | release_region(0x201, 1); | ||
| 942 | } | ||
| 943 | } | ||
| 944 | #else | ||
| 945 | static inline int mad16_register_gameport(int io_port) { return -ENOSYS; } | ||
| 946 | static inline void mad16_unregister_gameport(void) { } | ||
| 947 | #endif | ||
| 948 | |||
| 928 | static int __devinit init_mad16(void) | 949 | static int __devinit init_mad16(void) |
| 929 | { | 950 | { |
| 930 | int dmatype = 0; | 951 | int dmatype = 0; |
| @@ -1060,12 +1081,7 @@ static void __exit cleanup_mad16(void) | |||
| 1060 | { | 1081 | { |
| 1061 | if (found_mpu) | 1082 | if (found_mpu) |
| 1062 | unload_mad16_mpu(&cfg_mpu); | 1083 | unload_mad16_mpu(&cfg_mpu); |
| 1063 | if (gameport) { | 1084 | mad16_unregister_gameport(); |
| 1064 | /* the gameport was initialized so we must free it up */ | ||
| 1065 | gameport_unregister_port(gameport); | ||
| 1066 | gameport = NULL; | ||
| 1067 | release_region(0x201, 1); | ||
| 1068 | } | ||
| 1069 | unload_mad16(&cfg); | 1085 | unload_mad16(&cfg); |
| 1070 | release_region(MC0_PORT, 12); | 1086 | release_region(MC0_PORT, 12); |
| 1071 | } | 1087 | } |
diff --git a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c index 06047e7979af..17d0e461f8d8 100644 --- a/sound/oss/sonicvibes.c +++ b/sound/oss/sonicvibes.c | |||
| @@ -122,6 +122,9 @@ | |||
| 122 | 122 | ||
| 123 | #include "dm.h" | 123 | #include "dm.h" |
| 124 | 124 | ||
| 125 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 126 | #define SUPPORT_JOYSTICK 1 | ||
| 127 | #endif | ||
| 125 | 128 | ||
| 126 | /* --------------------------------------------------------------------- */ | 129 | /* --------------------------------------------------------------------- */ |
| 127 | 130 | ||
| @@ -365,7 +368,9 @@ struct sv_state { | |||
| 365 | unsigned char obuf[MIDIOUTBUF]; | 368 | unsigned char obuf[MIDIOUTBUF]; |
| 366 | } midi; | 369 | } midi; |
| 367 | 370 | ||
| 371 | #if SUPPORT_JOYSTICK | ||
| 368 | struct gameport *gameport; | 372 | struct gameport *gameport; |
| 373 | #endif | ||
| 369 | }; | 374 | }; |
| 370 | 375 | ||
| 371 | /* --------------------------------------------------------------------- */ | 376 | /* --------------------------------------------------------------------- */ |
| @@ -2485,6 +2490,7 @@ static struct initvol { | |||
| 2485 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ | 2490 | #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \ |
| 2486 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) | 2491 | (pci_resource_flags((dev), (num)) & IORESOURCE_IO)) |
| 2487 | 2492 | ||
| 2493 | #ifdef SUPPORT_JOYSTICK | ||
| 2488 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | 2494 | static int __devinit sv_register_gameport(struct sv_state *s, int io_port) |
| 2489 | { | 2495 | { |
| 2490 | struct gameport *gp; | 2496 | struct gameport *gp; |
| @@ -2511,6 +2517,19 @@ static int __devinit sv_register_gameport(struct sv_state *s, int io_port) | |||
| 2511 | return 0; | 2517 | return 0; |
| 2512 | } | 2518 | } |
| 2513 | 2519 | ||
| 2520 | static inline void sv_unregister_gameport(struct sv_state *s) | ||
| 2521 | { | ||
| 2522 | if (s->gameport) { | ||
| 2523 | int gpio = s->gameport->io; | ||
| 2524 | gameport_unregister_port(s->gameport); | ||
| 2525 | release_region(gpio, SV_EXTENT_GAME); | ||
| 2526 | } | ||
| 2527 | } | ||
| 2528 | #else | ||
| 2529 | static inline int sv_register_gameport(struct sv_state *s, int io_port) { return -ENOSYS; } | ||
| 2530 | static inline void sv_unregister_gameport(struct sv_state *s) { } | ||
| 2531 | #endif /* SUPPORT_JOYSTICK */ | ||
| 2532 | |||
| 2514 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) | 2533 | static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) |
| 2515 | { | 2534 | { |
| 2516 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; | 2535 | static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller"; |
| @@ -2711,11 +2730,7 @@ static void __devexit sv_remove(struct pci_dev *dev) | |||
| 2711 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ | 2730 | /*outb(0, s->iodmaa + SV_DMA_RESET);*/ |
| 2712 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ | 2731 | /*outb(0, s->iodmac + SV_DMA_RESET);*/ |
| 2713 | free_irq(s->irq, s); | 2732 | free_irq(s->irq, s); |
| 2714 | if (s->gameport) { | 2733 | sv_unregister_gameport(s); |
| 2715 | int gpio = s->gameport->io; | ||
| 2716 | gameport_unregister_port(s->gameport); | ||
| 2717 | release_region(gpio, SV_EXTENT_GAME); | ||
| 2718 | } | ||
| 2719 | release_region(s->iodmac, SV_EXTENT_DMA); | 2734 | release_region(s->iodmac, SV_EXTENT_DMA); |
| 2720 | release_region(s->iodmaa, SV_EXTENT_DMA); | 2735 | release_region(s->iodmaa, SV_EXTENT_DMA); |
| 2721 | release_region(s->ioenh, SV_EXTENT_ENH); | 2736 | release_region(s->ioenh, SV_EXTENT_ENH); |
diff --git a/sound/oss/trident.c b/sound/oss/trident.c index 47537f0a5b05..5f0ad6bb43b9 100644 --- a/sound/oss/trident.c +++ b/sound/oss/trident.c | |||
| @@ -228,6 +228,10 @@ | |||
| 228 | 228 | ||
| 229 | #define DRIVER_VERSION "0.14.10j-2.6" | 229 | #define DRIVER_VERSION "0.14.10j-2.6" |
| 230 | 230 | ||
| 231 | #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE)) | ||
| 232 | #define SUPPORT_JOYSTICK 1 | ||
| 233 | #endif | ||
| 234 | |||
| 231 | /* magic numbers to protect our data structures */ | 235 | /* magic numbers to protect our data structures */ |
| 232 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ | 236 | #define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */ |
| 233 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ | 237 | #define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */ |
| @@ -4252,24 +4256,25 @@ trident_ac97_init(struct trident_card *card) | |||
| 4252 | return num_ac97 + 1; | 4256 | return num_ac97 + 1; |
| 4253 | } | 4257 | } |
| 4254 | 4258 | ||
| 4259 | #ifdef SUPPORT_JOYSTICK | ||
| 4255 | /* Gameport functions for the cards ADC gameport */ | 4260 | /* Gameport functions for the cards ADC gameport */ |
| 4256 | 4261 | ||
| 4257 | static unsigned char | 4262 | static unsigned char trident_game_read(struct gameport *gameport) |
| 4258 | trident_game_read(struct gameport *gameport) | ||
| 4259 | { | 4263 | { |
| 4260 | struct trident_card *card = gameport->port_data; | 4264 | struct trident_card *card = gameport->port_data; |
| 4265 | |||
| 4261 | return inb(TRID_REG(card, T4D_GAME_LEG)); | 4266 | return inb(TRID_REG(card, T4D_GAME_LEG)); |
| 4262 | } | 4267 | } |
| 4263 | 4268 | ||
| 4264 | static void | 4269 | static void trident_game_trigger(struct gameport *gameport) |
| 4265 | trident_game_trigger(struct gameport *gameport) | ||
| 4266 | { | 4270 | { |
| 4267 | struct trident_card *card = gameport->port_data; | 4271 | struct trident_card *card = gameport->port_data; |
| 4272 | |||
| 4268 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); | 4273 | outb(0xff, TRID_REG(card, T4D_GAME_LEG)); |
| 4269 | } | 4274 | } |
| 4270 | 4275 | ||
| 4271 | static int | 4276 | static int trident_game_cooked_read(struct gameport *gameport, |
| 4272 | trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | 4277 | int *axes, int *buttons) |
| 4273 | { | 4278 | { |
| 4274 | struct trident_card *card = gameport->port_data; | 4279 | struct trident_card *card = gameport->port_data; |
| 4275 | int i; | 4280 | int i; |
| @@ -4285,8 +4290,7 @@ trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons) | |||
| 4285 | return 0; | 4290 | return 0; |
| 4286 | } | 4291 | } |
| 4287 | 4292 | ||
| 4288 | static int | 4293 | static int trident_game_open(struct gameport *gameport, int mode) |
| 4289 | trident_game_open(struct gameport *gameport, int mode) | ||
| 4290 | { | 4294 | { |
| 4291 | struct trident_card *card = gameport->port_data; | 4295 | struct trident_card *card = gameport->port_data; |
| 4292 | 4296 | ||
| @@ -4305,8 +4309,7 @@ trident_game_open(struct gameport *gameport, int mode) | |||
| 4305 | return 0; | 4309 | return 0; |
| 4306 | } | 4310 | } |
| 4307 | 4311 | ||
| 4308 | static int __devinit | 4312 | static int __devinit trident_register_gameport(struct trident_card *card) |
| 4309 | trident_register_gameport(struct trident_card *card) | ||
| 4310 | { | 4313 | { |
| 4311 | struct gameport *gp; | 4314 | struct gameport *gp; |
| 4312 | 4315 | ||
| @@ -4330,6 +4333,17 @@ trident_register_gameport(struct trident_card *card) | |||
| 4330 | return 0; | 4333 | return 0; |
| 4331 | } | 4334 | } |
| 4332 | 4335 | ||
| 4336 | static inline void trident_unregister_gameport(struct trident_card *card) | ||
| 4337 | { | ||
| 4338 | if (card->gameport) | ||
| 4339 | gameport_unregister_port(card->gameport); | ||
| 4340 | } | ||
| 4341 | |||
| 4342 | #else | ||
| 4343 | static inline int trident_register_gameport(struct trident_card *card) { return -ENOSYS; } | ||
| 4344 | static inline void trident_unregister_gameport(struct trident_card *card) { } | ||
| 4345 | #endif /* SUPPORT_JOYSTICK */ | ||
| 4346 | |||
| 4333 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ | 4347 | /* install the driver, we do not allocate hardware channel nor DMA buffer */ |
| 4334 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ | 4348 | /* now, they are defered until "ACCESS" time (in prog_dmabuf called by */ |
| 4335 | /* open/read/write/ioctl/mmap) */ | 4349 | /* open/read/write/ioctl/mmap) */ |
| @@ -4569,8 +4583,7 @@ trident_remove(struct pci_dev *pci_dev) | |||
| 4569 | } | 4583 | } |
| 4570 | 4584 | ||
| 4571 | /* Unregister gameport */ | 4585 | /* Unregister gameport */ |
| 4572 | if (card->gameport) | 4586 | trident_unregister_gameport(card); |
| 4573 | gameport_unregister_port(card->gameport); | ||
| 4574 | 4587 | ||
| 4575 | /* Kill interrupts, and SP/DIF */ | 4588 | /* Kill interrupts, and SP/DIF */ |
| 4576 | trident_disable_loop_interrupts(card); | 4589 | trident_disable_loop_interrupts(card); |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index d7e06b3caf97..0b53f7c61f86 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
| @@ -1335,11 +1335,6 @@ static inline int snd_cs4281_create_gameport(cs4281_t *chip) { return -ENOSYS; } | |||
| 1335 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } | 1335 | static inline void snd_cs4281_free_gameport(cs4281_t *chip) { } |
| 1336 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ | 1336 | #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */ |
| 1337 | 1337 | ||
| 1338 | |||
| 1339 | /* | ||
| 1340 | |||
| 1341 | */ | ||
| 1342 | |||
| 1343 | static int snd_cs4281_free(cs4281_t *chip) | 1338 | static int snd_cs4281_free(cs4281_t *chip) |
| 1344 | { | 1339 | { |
| 1345 | snd_cs4281_free_gameport(chip); | 1340 | snd_cs4281_free_gameport(chip); |
