diff options
author | Johannes Stezenbach <js@linuxtv.org> | 2005-09-09 16:03:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-09 16:57:44 -0400 |
commit | 6d78933c291bd0b6292e2c631e2f5e346c14d3fa (patch) | |
tree | 213258393d3cc5973b6ac2c890cf7ad9035febf8 /drivers/media/dvb/cinergyT2 | |
parent | 2d6e7322b5f63d62ec8785c5fbf469c9a233baff (diff) |
[PATCH] dvb: cinergyT2: remote control fixes
IR RC fixes:
- EVIOCSKEYCODE is not supported by this driver, fix potential crash
when it is used by not setting rc_input_dev->keycodesize
- fix key repeat handling (hopefully)
- reduce default poll internal to 50msec (necessary for key repeat handling)
Signed-off-by: Johannes Stezenbach <js@linuxtv.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/media/dvb/cinergyT2')
-rw-r--r-- | drivers/media/dvb/cinergyT2/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/dvb/cinergyT2/cinergyT2.c | 93 |
2 files changed, 57 insertions, 38 deletions
diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig index 226714085f58..7cf4c4a888ec 100644 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ b/drivers/media/dvb/cinergyT2/Kconfig | |||
@@ -77,7 +77,7 @@ config DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | |||
77 | config DVB_CINERGYT2_RC_QUERY_INTERVAL | 77 | config DVB_CINERGYT2_RC_QUERY_INTERVAL |
78 | int "Infrared Remote Controller update interval [milliseconds]" | 78 | int "Infrared Remote Controller update interval [milliseconds]" |
79 | depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE | 79 | depends on DVB_CINERGYT2_TUNING && DVB_CINERGYT2_ENABLE_RC_INPUT_DEVICE |
80 | default "100" | 80 | default "50" |
81 | help | 81 | help |
82 | If you have a very fast-repeating remote control you can try lower | 82 | If you have a very fast-repeating remote control you can try lower |
83 | values, for normal consumer receivers the default value should be | 83 | values, for normal consumer receivers the default value should be |
diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index c52e9d5c3d96..6db0929ef53d 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include "dvb_demux.h" | 35 | #include "dvb_demux.h" |
36 | #include "dvb_net.h" | 36 | #include "dvb_net.h" |
37 | 37 | ||
38 | |||
39 | #ifdef CONFIG_DVB_CINERGYT2_TUNING | 38 | #ifdef CONFIG_DVB_CINERGYT2_TUNING |
40 | #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) | 39 | #define STREAM_URB_COUNT (CONFIG_DVB_CINERGYT2_STREAM_URB_COUNT) |
41 | #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) | 40 | #define STREAM_BUF_SIZE (CONFIG_DVB_CINERGYT2_STREAM_BUF_SIZE) |
@@ -48,7 +47,7 @@ | |||
48 | #define STREAM_URB_COUNT (32) | 47 | #define STREAM_URB_COUNT (32) |
49 | #define STREAM_BUF_SIZE (512) /* bytes */ | 48 | #define STREAM_BUF_SIZE (512) /* bytes */ |
50 | #define ENABLE_RC (1) | 49 | #define ENABLE_RC (1) |
51 | #define RC_QUERY_INTERVAL (100) /* milliseconds */ | 50 | #define RC_QUERY_INTERVAL (50) /* milliseconds */ |
52 | #define QUERY_INTERVAL (333) /* milliseconds */ | 51 | #define QUERY_INTERVAL (333) /* milliseconds */ |
53 | #endif | 52 | #endif |
54 | 53 | ||
@@ -141,6 +140,8 @@ struct cinergyt2 { | |||
141 | struct input_dev rc_input_dev; | 140 | struct input_dev rc_input_dev; |
142 | struct work_struct rc_query_work; | 141 | struct work_struct rc_query_work; |
143 | int rc_input_event; | 142 | int rc_input_event; |
143 | u32 rc_last_code; | ||
144 | unsigned long last_event_jiffies; | ||
144 | #endif | 145 | #endif |
145 | }; | 146 | }; |
146 | 147 | ||
@@ -155,7 +156,7 @@ struct cinergyt2_rc_event { | |||
155 | uint32_t value; | 156 | uint32_t value; |
156 | } __attribute__((packed)); | 157 | } __attribute__((packed)); |
157 | 158 | ||
158 | static const uint32_t rc_keys [] = { | 159 | static const uint32_t rc_keys[] = { |
159 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, | 160 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfe01eb04, KEY_POWER, |
160 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, | 161 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfd02eb04, KEY_1, |
161 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, | 162 | CINERGYT2_RC_EVENT_TYPE_NEC, 0xfc03eb04, KEY_2, |
@@ -684,52 +685,68 @@ static struct dvb_device cinergyt2_fe_template = { | |||
684 | #ifdef ENABLE_RC | 685 | #ifdef ENABLE_RC |
685 | static void cinergyt2_query_rc (void *data) | 686 | static void cinergyt2_query_rc (void *data) |
686 | { | 687 | { |
687 | struct cinergyt2 *cinergyt2 = (struct cinergyt2 *) data; | 688 | struct cinergyt2 *cinergyt2 = data; |
688 | char buf [1] = { CINERGYT2_EP1_GET_RC_EVENTS }; | 689 | char buf[1] = { CINERGYT2_EP1_GET_RC_EVENTS }; |
689 | struct cinergyt2_rc_event rc_events[12]; | 690 | struct cinergyt2_rc_event rc_events[12]; |
690 | int n, len; | 691 | int n, len, i; |
691 | 692 | ||
692 | if (down_interruptible(&cinergyt2->sem)) | 693 | if (down_interruptible(&cinergyt2->sem)) |
693 | return; | 694 | return; |
694 | 695 | ||
695 | len = cinergyt2_command(cinergyt2, buf, sizeof(buf), | 696 | len = cinergyt2_command(cinergyt2, buf, sizeof(buf), |
696 | (char *) rc_events, sizeof(rc_events)); | 697 | (char *) rc_events, sizeof(rc_events)); |
697 | 698 | if (len < 0) | |
698 | for (n=0; len>0 && n<(len/sizeof(rc_events[0])); n++) { | 699 | goto out; |
699 | int i; | 700 | if (len == 0) { |
701 | if (time_after(jiffies, cinergyt2->last_event_jiffies + | ||
702 | msecs_to_jiffies(150))) { | ||
703 | /* stop key repeat */ | ||
704 | if (cinergyt2->rc_input_event != KEY_MAX) { | ||
705 | dprintk(1, "rc_input_event=%d Up\n", cinergyt2->rc_input_event); | ||
706 | input_report_key(&cinergyt2->rc_input_dev, | ||
707 | cinergyt2->rc_input_event, 0); | ||
708 | cinergyt2->rc_input_event = KEY_MAX; | ||
709 | } | ||
710 | cinergyt2->rc_last_code = ~0; | ||
711 | } | ||
712 | goto out; | ||
713 | } | ||
714 | cinergyt2->last_event_jiffies = jiffies; | ||
700 | 715 | ||
701 | /* dprintk(1,"rc_events[%d].value = %x, type=%x\n",n,le32_to_cpu(rc_events[n].value),rc_events[n].type);*/ | 716 | for (n = 0; n < (len / sizeof(rc_events[0])); n++) { |
717 | dprintk(1, "rc_events[%d].value = %x, type=%x\n", | ||
718 | n, le32_to_cpu(rc_events[n].value), rc_events[n].type); | ||
702 | 719 | ||
703 | if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && | 720 | if (rc_events[n].type == CINERGYT2_RC_EVENT_TYPE_NEC && |
704 | rc_events[n].value == ~0) | 721 | rc_events[n].value == ~0) { |
705 | { | 722 | /* keyrepeat bit -> just repeat last rc_input_event */ |
706 | /** | ||
707 | * keyrepeat bit. If we would handle this properly | ||
708 | * we would need to emit down events as long the | ||
709 | * keyrepeat goes, a up event if no further | ||
710 | * repeat bits occur. Would need a timer to implement | ||
711 | * and no other driver does this, so we simply | ||
712 | * emit the last key up/down sequence again. | ||
713 | */ | ||
714 | } else { | 723 | } else { |
715 | cinergyt2->rc_input_event = KEY_MAX; | 724 | cinergyt2->rc_input_event = KEY_MAX; |
716 | for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) { | 725 | for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) { |
717 | if (rc_keys[i+0] == rc_events[n].type && | 726 | if (rc_keys[i + 0] == rc_events[n].type && |
718 | rc_keys[i+1] == le32_to_cpu(rc_events[n].value)) | 727 | rc_keys[i + 1] == le32_to_cpu(rc_events[n].value)) { |
719 | { | 728 | cinergyt2->rc_input_event = rc_keys[i + 2]; |
720 | cinergyt2->rc_input_event = rc_keys[i+2]; | ||
721 | break; | 729 | break; |
722 | } | 730 | } |
723 | } | 731 | } |
724 | } | 732 | } |
725 | 733 | ||
726 | if (cinergyt2->rc_input_event != KEY_MAX) { | 734 | if (cinergyt2->rc_input_event != KEY_MAX) { |
727 | input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 1); | 735 | if (rc_events[n].value == cinergyt2->rc_last_code && |
728 | input_report_key(&cinergyt2->rc_input_dev, cinergyt2->rc_input_event, 0); | 736 | cinergyt2->rc_last_code != ~0) { |
729 | input_sync(&cinergyt2->rc_input_dev); | 737 | /* emit a key-up so the double event is recognized */ |
738 | dprintk(1, "rc_input_event=%d UP\n", cinergyt2->rc_input_event); | ||
739 | input_report_key(&cinergyt2->rc_input_dev, | ||
740 | cinergyt2->rc_input_event, 0); | ||
741 | } | ||
742 | dprintk(1, "rc_input_event=%d\n", cinergyt2->rc_input_event); | ||
743 | input_report_key(&cinergyt2->rc_input_dev, | ||
744 | cinergyt2->rc_input_event, 1); | ||
745 | cinergyt2->rc_last_code = rc_events[n].value; | ||
730 | } | 746 | } |
731 | } | 747 | } |
732 | 748 | ||
749 | out: | ||
733 | schedule_delayed_work(&cinergyt2->rc_query_work, | 750 | schedule_delayed_work(&cinergyt2->rc_query_work, |
734 | msecs_to_jiffies(RC_QUERY_INTERVAL)); | 751 | msecs_to_jiffies(RC_QUERY_INTERVAL)); |
735 | 752 | ||
@@ -771,7 +788,10 @@ static int cinergyt2_probe (struct usb_interface *intf, | |||
771 | const struct usb_device_id *id) | 788 | const struct usb_device_id *id) |
772 | { | 789 | { |
773 | struct cinergyt2 *cinergyt2; | 790 | struct cinergyt2 *cinergyt2; |
774 | int i, err; | 791 | int err; |
792 | #ifdef ENABLE_RC | ||
793 | int i; | ||
794 | #endif | ||
775 | 795 | ||
776 | if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { | 796 | if (!(cinergyt2 = kmalloc (sizeof(struct cinergyt2), GFP_KERNEL))) { |
777 | dprintk(1, "out of memory?!?\n"); | 797 | dprintk(1, "out of memory?!?\n"); |
@@ -827,19 +847,18 @@ static int cinergyt2_probe (struct usb_interface *intf, | |||
827 | DVB_DEVICE_FRONTEND); | 847 | DVB_DEVICE_FRONTEND); |
828 | 848 | ||
829 | #ifdef ENABLE_RC | 849 | #ifdef ENABLE_RC |
830 | init_input_dev(&cinergyt2->rc_input_dev); | 850 | cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REP); |
831 | 851 | cinergyt2->rc_input_dev.keycodesize = 0; | |
832 | cinergyt2->rc_input_dev.evbit[0] = BIT(EV_KEY); | 852 | cinergyt2->rc_input_dev.keycodemax = 0; |
833 | cinergyt2->rc_input_dev.keycodesize = sizeof(unsigned char); | ||
834 | cinergyt2->rc_input_dev.keycodemax = KEY_MAX; | ||
835 | cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control"; | 853 | cinergyt2->rc_input_dev.name = DRIVER_NAME " remote control"; |
836 | 854 | ||
837 | for (i=0; i<sizeof(rc_keys)/sizeof(rc_keys[0]); i+=3) | 855 | for (i = 0; i < sizeof(rc_keys) / sizeof(rc_keys[0]); i += 3) |
838 | set_bit(rc_keys[i+2], cinergyt2->rc_input_dev.keybit); | 856 | set_bit(rc_keys[i + 2], cinergyt2->rc_input_dev.keybit); |
839 | 857 | ||
840 | input_register_device(&cinergyt2->rc_input_dev); | 858 | input_register_device(&cinergyt2->rc_input_dev); |
841 | 859 | ||
842 | cinergyt2->rc_input_event = KEY_MAX; | 860 | cinergyt2->rc_input_event = KEY_MAX; |
861 | cinergyt2->rc_last_code = ~0; | ||
843 | 862 | ||
844 | INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); | 863 | INIT_WORK(&cinergyt2->rc_query_work, cinergyt2_query_rc, cinergyt2); |
845 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); | 864 | schedule_delayed_work(&cinergyt2->rc_query_work, HZ/2); |