diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 10:04:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 16:23:10 -0500 |
commit | b32e724308300a6ecead0f4895f0452a06a4291d (patch) | |
tree | cafdc5dc6a5036f3c0e54346a220845910929018 /drivers | |
parent | 39cac3758f62c6495d954e0d7dc1ca7e69fa565d (diff) |
[media] rc: Add support for decoding Sanyo protocol
This protocol is found on Sanyo/Aiwa remotes.
Tested with an Aiwa RC-7AS06 remote control.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/rc/Kconfig | 10 | ||||
-rw-r--r-- | drivers/media/rc/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/rc/ir-raw.c | 1 | ||||
-rw-r--r-- | drivers/media/rc/ir-sanyo-decoder.c | 204 | ||||
-rw-r--r-- | drivers/media/rc/rc-core-priv.h | 12 | ||||
-rw-r--r-- | drivers/media/rc/rc-main.c | 1 |
6 files changed, 229 insertions, 0 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index aeb7f43dfb65..4df4affeea5f 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -87,6 +87,16 @@ config IR_RC5_SZ_DECODER | |||
87 | uses an IR protocol that is almost standard RC-5, but not quite, | 87 | uses an IR protocol that is almost standard RC-5, but not quite, |
88 | as it uses an additional bit). | 88 | as it uses an additional bit). |
89 | 89 | ||
90 | config IR_SANYO_DECODER | ||
91 | tristate "Enable IR raw decoder for the Sanyo protocol" | ||
92 | depends on RC_CORE | ||
93 | default y | ||
94 | |||
95 | ---help--- | ||
96 | Enable this option if you have an infrared remote control which | ||
97 | uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes), | ||
98 | and you need software decoding support. | ||
99 | |||
90 | config IR_MCE_KBD_DECODER | 100 | config IR_MCE_KBD_DECODER |
91 | tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" | 101 | tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" |
92 | depends on RC_CORE | 102 | depends on RC_CORE |
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index 2156e786b557..fb3dee2dd845 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_IR_RC6_DECODER) += ir-rc6-decoder.o | |||
10 | obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o | 10 | obj-$(CONFIG_IR_JVC_DECODER) += ir-jvc-decoder.o |
11 | obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o | 11 | obj-$(CONFIG_IR_SONY_DECODER) += ir-sony-decoder.o |
12 | obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o | 12 | obj-$(CONFIG_IR_RC5_SZ_DECODER) += ir-rc5-sz-decoder.o |
13 | obj-$(CONFIG_IR_SANYO_DECODER) += ir-sanyo-decoder.o | ||
13 | obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o | 14 | obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o |
14 | obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o | 15 | obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o |
15 | 16 | ||
diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c index 27808bb59eba..9e841f43ed4d 100644 --- a/drivers/media/rc/ir-raw.c +++ b/drivers/media/rc/ir-raw.c | |||
@@ -355,6 +355,7 @@ static void init_decoders(struct work_struct *work) | |||
355 | load_rc6_decode(); | 355 | load_rc6_decode(); |
356 | load_jvc_decode(); | 356 | load_jvc_decode(); |
357 | load_sony_decode(); | 357 | load_sony_decode(); |
358 | load_sanyo_decode(); | ||
358 | load_mce_kbd_decode(); | 359 | load_mce_kbd_decode(); |
359 | load_lirc_codec(); | 360 | load_lirc_codec(); |
360 | 361 | ||
diff --git a/drivers/media/rc/ir-sanyo-decoder.c b/drivers/media/rc/ir-sanyo-decoder.c new file mode 100644 index 000000000000..164673071252 --- /dev/null +++ b/drivers/media/rc/ir-sanyo-decoder.c | |||
@@ -0,0 +1,204 @@ | |||
1 | /* ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2011 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation version 2 of the License. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * This protocol uses the NEC protocol timings. However, data is formatted as: | ||
15 | * 13 bits Custom Code | ||
16 | * 13 bits NOT(Custom Code) | ||
17 | * 8 bits Key data | ||
18 | * 8 bits NOT(Key data) | ||
19 | * | ||
20 | * According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon | ||
21 | * Information for this protocol is available at the Sanyo LC7461 datasheet. | ||
22 | */ | ||
23 | |||
24 | #include <linux/bitrev.h> | ||
25 | #include "rc-core-priv.h" | ||
26 | |||
27 | #define SANYO_NBITS (13+13+8+8) | ||
28 | #define SANYO_UNIT 562500 /* ns */ | ||
29 | #define SANYO_HEADER_PULSE (16 * SANYO_UNIT) | ||
30 | #define SANYO_HEADER_SPACE (8 * SANYO_UNIT) | ||
31 | #define SANYO_BIT_PULSE (1 * SANYO_UNIT) | ||
32 | #define SANYO_BIT_0_SPACE (1 * SANYO_UNIT) | ||
33 | #define SANYO_BIT_1_SPACE (3 * SANYO_UNIT) | ||
34 | #define SANYO_REPEAT_SPACE (150 * SANYO_UNIT) | ||
35 | #define SANYO_TRAILER_PULSE (1 * SANYO_UNIT) | ||
36 | #define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */ | ||
37 | |||
38 | enum sanyo_state { | ||
39 | STATE_INACTIVE, | ||
40 | STATE_HEADER_SPACE, | ||
41 | STATE_BIT_PULSE, | ||
42 | STATE_BIT_SPACE, | ||
43 | STATE_TRAILER_PULSE, | ||
44 | STATE_TRAILER_SPACE, | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * ir_sanyo_decode() - Decode one SANYO pulse or space | ||
49 | * @dev: the struct rc_dev descriptor of the device | ||
50 | * @duration: the struct ir_raw_event descriptor of the pulse/space | ||
51 | * | ||
52 | * This function returns -EINVAL if the pulse violates the state machine | ||
53 | */ | ||
54 | static int ir_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) | ||
55 | { | ||
56 | struct sanyo_dec *data = &dev->raw->sanyo; | ||
57 | u32 scancode; | ||
58 | u8 address, not_address, command, not_command; | ||
59 | |||
60 | if (!(dev->raw->enabled_protocols & RC_TYPE_SANYO)) | ||
61 | return 0; | ||
62 | |||
63 | if (!is_timing_event(ev)) { | ||
64 | if (ev.reset) { | ||
65 | IR_dprintk(1, "SANYO event reset received. reset to state 0\n"); | ||
66 | data->state = STATE_INACTIVE; | ||
67 | } | ||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | IR_dprintk(2, "SANYO decode started at state %d (%uus %s)\n", | ||
72 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
73 | |||
74 | switch (data->state) { | ||
75 | |||
76 | case STATE_INACTIVE: | ||
77 | if (!ev.pulse) | ||
78 | break; | ||
79 | |||
80 | if (eq_margin(ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) { | ||
81 | data->count = 0; | ||
82 | data->state = STATE_HEADER_SPACE; | ||
83 | return 0; | ||
84 | } | ||
85 | break; | ||
86 | |||
87 | |||
88 | case STATE_HEADER_SPACE: | ||
89 | if (ev.pulse) | ||
90 | break; | ||
91 | |||
92 | if (eq_margin(ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) { | ||
93 | data->state = STATE_BIT_PULSE; | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | break; | ||
98 | |||
99 | case STATE_BIT_PULSE: | ||
100 | if (!ev.pulse) | ||
101 | break; | ||
102 | |||
103 | if (!eq_margin(ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2)) | ||
104 | break; | ||
105 | |||
106 | data->state = STATE_BIT_SPACE; | ||
107 | return 0; | ||
108 | |||
109 | case STATE_BIT_SPACE: | ||
110 | if (ev.pulse) | ||
111 | break; | ||
112 | |||
113 | if (!data->count && geq_margin(ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) { | ||
114 | if (!dev->keypressed) { | ||
115 | IR_dprintk(1, "SANYO discarding last key repeat: event after key up\n"); | ||
116 | } else { | ||
117 | rc_repeat(dev); | ||
118 | IR_dprintk(1, "SANYO repeat last key\n"); | ||
119 | data->state = STATE_INACTIVE; | ||
120 | } | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | data->bits <<= 1; | ||
125 | if (eq_margin(ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2)) | ||
126 | data->bits |= 1; | ||
127 | else if (!eq_margin(ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2)) | ||
128 | break; | ||
129 | data->count++; | ||
130 | |||
131 | if (data->count == SANYO_NBITS) | ||
132 | data->state = STATE_TRAILER_PULSE; | ||
133 | else | ||
134 | data->state = STATE_BIT_PULSE; | ||
135 | |||
136 | return 0; | ||
137 | |||
138 | case STATE_TRAILER_PULSE: | ||
139 | if (!ev.pulse) | ||
140 | break; | ||
141 | |||
142 | if (!eq_margin(ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2)) | ||
143 | break; | ||
144 | |||
145 | data->state = STATE_TRAILER_SPACE; | ||
146 | return 0; | ||
147 | |||
148 | case STATE_TRAILER_SPACE: | ||
149 | if (ev.pulse) | ||
150 | break; | ||
151 | |||
152 | if (!geq_margin(ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2)) | ||
153 | break; | ||
154 | |||
155 | address = bitrev16((data->bits >> 29) & 0x1fff) >> 3; | ||
156 | not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; | ||
157 | command = bitrev8((data->bits >> 8) & 0xff); | ||
158 | not_command = bitrev8((data->bits >> 0) & 0xff); | ||
159 | |||
160 | if ((command ^ not_command) != 0xff) { | ||
161 | IR_dprintk(1, "SANYO checksum error: received 0x%08Lx\n", | ||
162 | data->bits); | ||
163 | data->state = STATE_INACTIVE; | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | scancode = address << 8 | command; | ||
168 | IR_dprintk(1, "SANYO scancode: 0x%06x\n", scancode); | ||
169 | rc_keydown(dev, scancode, 0); | ||
170 | data->state = STATE_INACTIVE; | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | IR_dprintk(1, "SANYO decode failed at count %d state %d (%uus %s)\n", | ||
175 | data->count, data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
176 | data->state = STATE_INACTIVE; | ||
177 | return -EINVAL; | ||
178 | } | ||
179 | |||
180 | static struct ir_raw_handler sanyo_handler = { | ||
181 | .protocols = RC_TYPE_SANYO, | ||
182 | .decode = ir_sanyo_decode, | ||
183 | }; | ||
184 | |||
185 | static int __init ir_sanyo_decode_init(void) | ||
186 | { | ||
187 | ir_raw_handler_register(&sanyo_handler); | ||
188 | |||
189 | printk(KERN_INFO "IR SANYO protocol handler initialized\n"); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static void __exit ir_sanyo_decode_exit(void) | ||
194 | { | ||
195 | ir_raw_handler_unregister(&sanyo_handler); | ||
196 | } | ||
197 | |||
198 | module_init(ir_sanyo_decode_init); | ||
199 | module_exit(ir_sanyo_decode_exit); | ||
200 | |||
201 | MODULE_LICENSE("GPL"); | ||
202 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | ||
203 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)"); | ||
204 | MODULE_DESCRIPTION("SANYO IR protocol decoder"); | ||
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index c6ca870e8b7e..b72f8580e317 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h | |||
@@ -84,6 +84,11 @@ struct ir_raw_event_ctrl { | |||
84 | unsigned count; | 84 | unsigned count; |
85 | unsigned wanted_bits; | 85 | unsigned wanted_bits; |
86 | } rc5_sz; | 86 | } rc5_sz; |
87 | struct sanyo_dec { | ||
88 | int state; | ||
89 | unsigned count; | ||
90 | u64 bits; | ||
91 | } sanyo; | ||
87 | struct mce_kbd_dec { | 92 | struct mce_kbd_dec { |
88 | struct input_dev *idev; | 93 | struct input_dev *idev; |
89 | struct timer_list rx_timeout; | 94 | struct timer_list rx_timeout; |
@@ -193,6 +198,13 @@ static inline void load_jvc_decode(void) { } | |||
193 | static inline void load_sony_decode(void) { } | 198 | static inline void load_sony_decode(void) { } |
194 | #endif | 199 | #endif |
195 | 200 | ||
201 | /* from ir-sanyo-decoder.c */ | ||
202 | #ifdef CONFIG_IR_SANYO_DECODER_MODULE | ||
203 | #define load_sanyo_decode() request_module("ir-sanyo-decoder") | ||
204 | #else | ||
205 | static inline void load_sanyo_decode(void) { } | ||
206 | #endif | ||
207 | |||
196 | /* from ir-mce_kbd-decoder.c */ | 208 | /* from ir-mce_kbd-decoder.c */ |
197 | #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE | 209 | #ifdef CONFIG_IR_MCE_KBD_DECODER_MODULE |
198 | #define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder") | 210 | #define load_mce_kbd_decode() request_module("ir-mce_kbd-decoder") |
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 666d4bb5b1fb..35e2fcf0dc0a 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c | |||
@@ -735,6 +735,7 @@ static struct { | |||
735 | { RC_TYPE_JVC, "jvc" }, | 735 | { RC_TYPE_JVC, "jvc" }, |
736 | { RC_TYPE_SONY, "sony" }, | 736 | { RC_TYPE_SONY, "sony" }, |
737 | { RC_TYPE_RC5_SZ, "rc-5-sz" }, | 737 | { RC_TYPE_RC5_SZ, "rc-5-sz" }, |
738 | { RC_TYPE_SANYO, "sanyo" }, | ||
738 | { RC_TYPE_MCE_KBD, "mce_kbd" }, | 739 | { RC_TYPE_MCE_KBD, "mce_kbd" }, |
739 | { RC_TYPE_LIRC, "lirc" }, | 740 | { RC_TYPE_LIRC, "lirc" }, |
740 | { RC_TYPE_OTHER, "other" }, | 741 | { RC_TYPE_OTHER, "other" }, |