diff options
Diffstat (limited to 'drivers/usb/input/ati_remote.c')
-rw-r--r-- | drivers/usb/input/ati_remote.c | 183 |
1 files changed, 101 insertions, 82 deletions
diff --git a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c index 07c8c0e665dd..3558d7ed99b9 100644 --- a/drivers/usb/input/ati_remote.c +++ b/drivers/usb/input/ati_remote.c | |||
@@ -85,7 +85,6 @@ | |||
85 | * | 85 | * |
86 | */ | 86 | */ |
87 | 87 | ||
88 | #include <linux/config.h> | ||
89 | #include <linux/kernel.h> | 88 | #include <linux/kernel.h> |
90 | #include <linux/errno.h> | 89 | #include <linux/errno.h> |
91 | #include <linux/init.h> | 90 | #include <linux/init.h> |
@@ -112,14 +111,28 @@ | |||
112 | #define NAME_BUFSIZE 80 /* size of product name, path buffers */ | 111 | #define NAME_BUFSIZE 80 /* size of product name, path buffers */ |
113 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ | 112 | #define DATA_BUFSIZE 63 /* size of URB data buffers */ |
114 | 113 | ||
114 | /* | ||
115 | * Duplicate event filtering time. | ||
116 | * Sequential, identical KIND_FILTERED inputs with less than | ||
117 | * FILTER_TIME milliseconds between them are considered as repeat | ||
118 | * events. The hardware generates 5 events for the first keypress | ||
119 | * and we have to take this into account for an accurate repeat | ||
120 | * behaviour. | ||
121 | */ | ||
122 | #define FILTER_TIME 60 /* msec */ | ||
123 | |||
115 | static unsigned long channel_mask; | 124 | static unsigned long channel_mask; |
116 | module_param(channel_mask, ulong, 0444); | 125 | module_param(channel_mask, ulong, 0644); |
117 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); | 126 | MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); |
118 | 127 | ||
119 | static int debug; | 128 | static int debug; |
120 | module_param(debug, int, 0444); | 129 | module_param(debug, int, 0644); |
121 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); | 130 | MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); |
122 | 131 | ||
132 | static int repeat_filter = FILTER_TIME; | ||
133 | module_param(repeat_filter, int, 0644); | ||
134 | MODULE_PARM_DESC(repeat_filter, "Repeat filter time, default = 60 msec"); | ||
135 | |||
123 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) | 136 | #define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) |
124 | #undef err | 137 | #undef err |
125 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 138 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
@@ -144,19 +157,6 @@ MODULE_DEVICE_TABLE(usb, ati_remote_table); | |||
144 | static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; | 157 | static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; |
145 | static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; | 158 | static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; |
146 | 159 | ||
147 | /* Acceleration curve for directional control pad */ | ||
148 | static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | ||
149 | |||
150 | /* Duplicate event filtering time. | ||
151 | * Sequential, identical KIND_FILTERED inputs with less than | ||
152 | * FILTER_TIME jiffies between them are considered as repeat | ||
153 | * events. The hardware generates 5 events for the first keypress | ||
154 | * and we have to take this into account for an accurate repeat | ||
155 | * behaviour. | ||
156 | * (HZ / 20) == 50 ms and works well for me. | ||
157 | */ | ||
158 | #define FILTER_TIME (HZ / 20) | ||
159 | |||
160 | struct ati_remote { | 160 | struct ati_remote { |
161 | struct input_dev *idev; | 161 | struct input_dev *idev; |
162 | struct usb_device *udev; | 162 | struct usb_device *udev; |
@@ -414,6 +414,43 @@ static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) | |||
414 | } | 414 | } |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * ati_remote_compute_accel | ||
418 | * | ||
419 | * Implements acceleration curve for directional control pad | ||
420 | * If elapsed time since last event is > 1/4 second, user "stopped", | ||
421 | * so reset acceleration. Otherwise, user is probably holding the control | ||
422 | * pad down, so we increase acceleration, ramping up over two seconds to | ||
423 | * a maximum speed. | ||
424 | */ | ||
425 | static int ati_remote_compute_accel(struct ati_remote *ati_remote) | ||
426 | { | ||
427 | static const char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; | ||
428 | unsigned long now = jiffies; | ||
429 | int acc; | ||
430 | |||
431 | if (time_after(now, ati_remote->old_jiffies + msecs_to_jiffies(250))) { | ||
432 | acc = 1; | ||
433 | ati_remote->acc_jiffies = now; | ||
434 | } | ||
435 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(125))) | ||
436 | acc = accel[0]; | ||
437 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(250))) | ||
438 | acc = accel[1]; | ||
439 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(500))) | ||
440 | acc = accel[2]; | ||
441 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1000))) | ||
442 | acc = accel[3]; | ||
443 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(1500))) | ||
444 | acc = accel[4]; | ||
445 | else if (time_before(now, ati_remote->acc_jiffies + msecs_to_jiffies(2000))) | ||
446 | acc = accel[5]; | ||
447 | else | ||
448 | acc = accel[6]; | ||
449 | |||
450 | return acc; | ||
451 | } | ||
452 | |||
453 | /* | ||
417 | * ati_remote_report_input | 454 | * ati_remote_report_input |
418 | */ | 455 | */ |
419 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | 456 | static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) |
@@ -466,9 +503,9 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
466 | 503 | ||
467 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { | 504 | if (ati_remote_tbl[index].kind == KIND_FILTERED) { |
468 | /* Filter duplicate events which happen "too close" together. */ | 505 | /* Filter duplicate events which happen "too close" together. */ |
469 | if ((ati_remote->old_data[0] == data[1]) && | 506 | if (ati_remote->old_data[0] == data[1] && |
470 | (ati_remote->old_data[1] == data[2]) && | 507 | ati_remote->old_data[1] == data[2] && |
471 | time_before(jiffies, ati_remote->old_jiffies + FILTER_TIME)) { | 508 | time_before(jiffies, ati_remote->old_jiffies + msecs_to_jiffies(repeat_filter))) { |
472 | ati_remote->repeat_count++; | 509 | ati_remote->repeat_count++; |
473 | } else { | 510 | } else { |
474 | ati_remote->repeat_count = 0; | 511 | ati_remote->repeat_count = 0; |
@@ -478,75 +515,61 @@ static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) | |||
478 | ati_remote->old_data[1] = data[2]; | 515 | ati_remote->old_data[1] = data[2]; |
479 | ati_remote->old_jiffies = jiffies; | 516 | ati_remote->old_jiffies = jiffies; |
480 | 517 | ||
481 | if ((ati_remote->repeat_count > 0) | 518 | if (ati_remote->repeat_count > 0 && |
482 | && (ati_remote->repeat_count < 5)) | 519 | ati_remote->repeat_count < 5) |
483 | return; | 520 | return; |
484 | 521 | ||
485 | 522 | ||
486 | input_regs(dev, regs); | 523 | input_regs(dev, regs); |
487 | input_event(dev, ati_remote_tbl[index].type, | 524 | input_event(dev, ati_remote_tbl[index].type, |
488 | ati_remote_tbl[index].code, 1); | 525 | ati_remote_tbl[index].code, 1); |
526 | input_sync(dev); | ||
489 | input_event(dev, ati_remote_tbl[index].type, | 527 | input_event(dev, ati_remote_tbl[index].type, |
490 | ati_remote_tbl[index].code, 0); | 528 | ati_remote_tbl[index].code, 0); |
491 | input_sync(dev); | 529 | input_sync(dev); |
492 | 530 | ||
493 | return; | 531 | } else { |
494 | } | ||
495 | 532 | ||
496 | /* | 533 | /* |
497 | * Other event kinds are from the directional control pad, and have an | 534 | * Other event kinds are from the directional control pad, and have an |
498 | * acceleration factor applied to them. Without this acceleration, the | 535 | * acceleration factor applied to them. Without this acceleration, the |
499 | * control pad is mostly unusable. | 536 | * control pad is mostly unusable. |
500 | * | 537 | */ |
501 | * If elapsed time since last event is > 1/4 second, user "stopped", | 538 | acc = ati_remote_compute_accel(ati_remote); |
502 | * so reset acceleration. Otherwise, user is probably holding the control | 539 | |
503 | * pad down, so we increase acceleration, ramping up over two seconds to | 540 | input_regs(dev, regs); |
504 | * a maximum speed. The acceleration curve is #defined above. | 541 | switch (ati_remote_tbl[index].kind) { |
505 | */ | 542 | case KIND_ACCEL: |
506 | if (time_after(jiffies, ati_remote->old_jiffies + (HZ >> 2))) { | 543 | input_event(dev, ati_remote_tbl[index].type, |
507 | acc = 1; | 544 | ati_remote_tbl[index].code, |
508 | ati_remote->acc_jiffies = jiffies; | 545 | ati_remote_tbl[index].value * acc); |
509 | } | 546 | break; |
510 | else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 3))) acc = accel[0]; | 547 | case KIND_LU: |
511 | else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 2))) acc = accel[1]; | 548 | input_report_rel(dev, REL_X, -acc); |
512 | else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ >> 1))) acc = accel[2]; | 549 | input_report_rel(dev, REL_Y, -acc); |
513 | else if (time_before(jiffies, ati_remote->acc_jiffies + HZ)) acc = accel[3]; | 550 | break; |
514 | else if (time_before(jiffies, ati_remote->acc_jiffies + HZ+(HZ>>1))) acc = accel[4]; | 551 | case KIND_RU: |
515 | else if (time_before(jiffies, ati_remote->acc_jiffies + (HZ << 1))) acc = accel[5]; | 552 | input_report_rel(dev, REL_X, acc); |
516 | else acc = accel[6]; | 553 | input_report_rel(dev, REL_Y, -acc); |
517 | 554 | break; | |
518 | input_regs(dev, regs); | 555 | case KIND_LD: |
519 | switch (ati_remote_tbl[index].kind) { | 556 | input_report_rel(dev, REL_X, -acc); |
520 | case KIND_ACCEL: | 557 | input_report_rel(dev, REL_Y, acc); |
521 | input_event(dev, ati_remote_tbl[index].type, | 558 | break; |
522 | ati_remote_tbl[index].code, | 559 | case KIND_RD: |
523 | ati_remote_tbl[index].value * acc); | 560 | input_report_rel(dev, REL_X, acc); |
524 | break; | 561 | input_report_rel(dev, REL_Y, acc); |
525 | case KIND_LU: | 562 | break; |
526 | input_report_rel(dev, REL_X, -acc); | 563 | default: |
527 | input_report_rel(dev, REL_Y, -acc); | 564 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", |
528 | break; | 565 | ati_remote_tbl[index].kind); |
529 | case KIND_RU: | 566 | } |
530 | input_report_rel(dev, REL_X, acc); | 567 | input_sync(dev); |
531 | input_report_rel(dev, REL_Y, -acc); | ||
532 | break; | ||
533 | case KIND_LD: | ||
534 | input_report_rel(dev, REL_X, -acc); | ||
535 | input_report_rel(dev, REL_Y, acc); | ||
536 | break; | ||
537 | case KIND_RD: | ||
538 | input_report_rel(dev, REL_X, acc); | ||
539 | input_report_rel(dev, REL_Y, acc); | ||
540 | break; | ||
541 | default: | ||
542 | dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", | ||
543 | ati_remote_tbl[index].kind); | ||
544 | } | ||
545 | input_sync(dev); | ||
546 | 568 | ||
547 | ati_remote->old_jiffies = jiffies; | 569 | ati_remote->old_jiffies = jiffies; |
548 | ati_remote->old_data[0] = data[1]; | 570 | ati_remote->old_data[0] = data[1]; |
549 | ati_remote->old_data[1] = data[2]; | 571 | ati_remote->old_data[1] = data[2]; |
572 | } | ||
550 | } | 573 | } |
551 | 574 | ||
552 | /* | 575 | /* |
@@ -709,12 +732,8 @@ static int ati_remote_probe(struct usb_interface *interface, const struct usb_de | |||
709 | endpoint_in = &iface_host->endpoint[0].desc; | 732 | endpoint_in = &iface_host->endpoint[0].desc; |
710 | endpoint_out = &iface_host->endpoint[1].desc; | 733 | endpoint_out = &iface_host->endpoint[1].desc; |
711 | 734 | ||
712 | if (!(endpoint_in->bEndpointAddress & USB_DIR_IN)) { | 735 | if (!usb_endpoint_is_int_in(endpoint_in)) { |
713 | err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); | 736 | err("%s: Unexpected endpoint_in\n", __FUNCTION__); |
714 | return -ENODEV; | ||
715 | } | ||
716 | if ((endpoint_in->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT) { | ||
717 | err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); | ||
718 | return -ENODEV; | 737 | return -ENODEV; |
719 | } | 738 | } |
720 | if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { | 739 | if (le16_to_cpu(endpoint_in->wMaxPacketSize) == 0) { |