diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/rc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/media/rc/Makefile | 1 | ||||
-rw-r--r-- | drivers/media/rc/ir-sharp-decoder.c | 200 | ||||
-rw-r--r-- | drivers/media/rc/rc-core-priv.h | 6 |
4 files changed, 216 insertions, 0 deletions
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 904f11367c29..3b25887a9c09 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -106,6 +106,15 @@ config IR_SANYO_DECODER | |||
106 | uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes), | 106 | uses the Sanyo protocol (Sanyo, Aiwa, Chinon remotes), |
107 | and you need software decoding support. | 107 | and you need software decoding support. |
108 | 108 | ||
109 | config IR_SHARP_DECODER | ||
110 | tristate "Enable IR raw decoder for the Sharp protocol" | ||
111 | depends on RC_CORE | ||
112 | default y | ||
113 | |||
114 | ---help--- | ||
115 | Enable this option if you have an infrared remote control which | ||
116 | uses the Sharp protocol, and you need software decoding support. | ||
117 | |||
109 | config IR_MCE_KBD_DECODER | 118 | config IR_MCE_KBD_DECODER |
110 | tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" | 119 | tristate "Enable IR raw decoder for the MCE keyboard/mouse protocol" |
111 | depends on RC_CORE | 120 | depends on RC_CORE |
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile index f4eb32c0a455..36dafed412dd 100644 --- a/drivers/media/rc/Makefile +++ b/drivers/media/rc/Makefile | |||
@@ -11,6 +11,7 @@ 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_SANYO_DECODER) += ir-sanyo-decoder.o |
14 | obj-$(CONFIG_IR_SHARP_DECODER) += ir-sharp-decoder.o | ||
14 | obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o | 15 | obj-$(CONFIG_IR_MCE_KBD_DECODER) += ir-mce_kbd-decoder.o |
15 | obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o | 16 | obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o |
16 | 17 | ||
diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c new file mode 100644 index 000000000000..4c17be5d68ba --- /dev/null +++ b/drivers/media/rc/ir-sharp-decoder.c | |||
@@ -0,0 +1,200 @@ | |||
1 | /* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol | ||
2 | * | ||
3 | * Copyright (C) 2013-2014 Imagination Technologies Ltd. | ||
4 | * | ||
5 | * Based on NEC decoder: | ||
6 | * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/bitrev.h> | ||
19 | #include <linux/module.h> | ||
20 | #include "rc-core-priv.h" | ||
21 | |||
22 | #define SHARP_NBITS 15 | ||
23 | #define SHARP_UNIT 40000 /* ns */ | ||
24 | #define SHARP_BIT_PULSE (8 * SHARP_UNIT) /* 320us */ | ||
25 | #define SHARP_BIT_0_PERIOD (25 * SHARP_UNIT) /* 1ms (680us space) */ | ||
26 | #define SHARP_BIT_1_PERIOD (50 * SHARP_UNIT) /* 2ms (1680ms space) */ | ||
27 | #define SHARP_ECHO_SPACE (1000 * SHARP_UNIT) /* 40 ms */ | ||
28 | #define SHARP_TRAILER_SPACE (125 * SHARP_UNIT) /* 5 ms (even longer) */ | ||
29 | |||
30 | enum sharp_state { | ||
31 | STATE_INACTIVE, | ||
32 | STATE_BIT_PULSE, | ||
33 | STATE_BIT_SPACE, | ||
34 | STATE_TRAILER_PULSE, | ||
35 | STATE_ECHO_SPACE, | ||
36 | STATE_TRAILER_SPACE, | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * ir_sharp_decode() - Decode one Sharp pulse or space | ||
41 | * @dev: the struct rc_dev descriptor of the device | ||
42 | * @duration: the struct ir_raw_event descriptor of the pulse/space | ||
43 | * | ||
44 | * This function returns -EINVAL if the pulse violates the state machine | ||
45 | */ | ||
46 | static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev) | ||
47 | { | ||
48 | struct sharp_dec *data = &dev->raw->sharp; | ||
49 | u32 msg, echo, address, command, scancode; | ||
50 | |||
51 | if (!(dev->enabled_protocols & RC_BIT_SHARP)) | ||
52 | return 0; | ||
53 | |||
54 | if (!is_timing_event(ev)) { | ||
55 | if (ev.reset) | ||
56 | data->state = STATE_INACTIVE; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | IR_dprintk(2, "Sharp decode started at state %d (%uus %s)\n", | ||
61 | data->state, TO_US(ev.duration), TO_STR(ev.pulse)); | ||
62 | |||
63 | switch (data->state) { | ||
64 | |||
65 | case STATE_INACTIVE: | ||
66 | if (!ev.pulse) | ||
67 | break; | ||
68 | |||
69 | if (!eq_margin(ev.duration, SHARP_BIT_PULSE, | ||
70 | SHARP_BIT_PULSE / 2)) | ||
71 | break; | ||
72 | |||
73 | data->count = 0; | ||
74 | data->pulse_len = ev.duration; | ||
75 | data->state = STATE_BIT_SPACE; | ||
76 | return 0; | ||
77 | |||
78 | case STATE_BIT_PULSE: | ||
79 | if (!ev.pulse) | ||
80 | break; | ||
81 | |||
82 | if (!eq_margin(ev.duration, SHARP_BIT_PULSE, | ||
83 | SHARP_BIT_PULSE / 2)) | ||
84 | break; | ||
85 | |||
86 | data->pulse_len = ev.duration; | ||
87 | data->state = STATE_BIT_SPACE; | ||
88 | return 0; | ||
89 | |||
90 | case STATE_BIT_SPACE: | ||
91 | if (ev.pulse) | ||
92 | break; | ||
93 | |||
94 | data->bits <<= 1; | ||
95 | if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD, | ||
96 | SHARP_BIT_PULSE * 2)) | ||
97 | data->bits |= 1; | ||
98 | else if (!eq_margin(data->pulse_len + ev.duration, | ||
99 | SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2)) | ||
100 | break; | ||
101 | data->count++; | ||
102 | |||
103 | if (data->count == SHARP_NBITS || | ||
104 | data->count == SHARP_NBITS * 2) | ||
105 | data->state = STATE_TRAILER_PULSE; | ||
106 | else | ||
107 | data->state = STATE_BIT_PULSE; | ||
108 | |||
109 | return 0; | ||
110 | |||
111 | case STATE_TRAILER_PULSE: | ||
112 | if (!ev.pulse) | ||
113 | break; | ||
114 | |||
115 | if (!eq_margin(ev.duration, SHARP_BIT_PULSE, | ||
116 | SHARP_BIT_PULSE / 2)) | ||
117 | break; | ||
118 | |||
119 | if (data->count == SHARP_NBITS) { | ||
120 | /* exp,chk bits should be 1,0 */ | ||
121 | if ((data->bits & 0x3) != 0x2) | ||
122 | break; | ||
123 | data->state = STATE_ECHO_SPACE; | ||
124 | } else { | ||
125 | data->state = STATE_TRAILER_SPACE; | ||
126 | } | ||
127 | return 0; | ||
128 | |||
129 | case STATE_ECHO_SPACE: | ||
130 | if (ev.pulse) | ||
131 | break; | ||
132 | |||
133 | if (!eq_margin(ev.duration, SHARP_ECHO_SPACE, | ||
134 | SHARP_ECHO_SPACE / 4)) | ||
135 | break; | ||
136 | |||
137 | data->state = STATE_BIT_PULSE; | ||
138 | |||
139 | return 0; | ||
140 | |||
141 | case STATE_TRAILER_SPACE: | ||
142 | if (ev.pulse) | ||
143 | break; | ||
144 | |||
145 | if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE, | ||
146 | SHARP_BIT_PULSE / 2)) | ||
147 | break; | ||
148 | |||
149 | /* Validate - command, ext, chk should be inverted in 2nd */ | ||
150 | msg = (data->bits >> 15) & 0x7fff; | ||
151 | echo = data->bits & 0x7fff; | ||
152 | if ((msg ^ echo) != 0x3ff) { | ||
153 | IR_dprintk(1, | ||
154 | "Sharp checksum error: received 0x%04x, 0x%04x\n", | ||
155 | msg, echo); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | address = bitrev8((msg >> 7) & 0xf8); | ||
160 | command = bitrev8((msg >> 2) & 0xff); | ||
161 | |||
162 | scancode = address << 8 | command; | ||
163 | IR_dprintk(1, "Sharp scancode 0x%04x\n", scancode); | ||
164 | |||
165 | rc_keydown(dev, scancode, 0); | ||
166 | data->state = STATE_INACTIVE; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | IR_dprintk(1, "Sharp decode failed at count %d state %d (%uus %s)\n", | ||
171 | data->count, data->state, TO_US(ev.duration), | ||
172 | TO_STR(ev.pulse)); | ||
173 | data->state = STATE_INACTIVE; | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | static struct ir_raw_handler sharp_handler = { | ||
178 | .protocols = RC_BIT_SHARP, | ||
179 | .decode = ir_sharp_decode, | ||
180 | }; | ||
181 | |||
182 | static int __init ir_sharp_decode_init(void) | ||
183 | { | ||
184 | ir_raw_handler_register(&sharp_handler); | ||
185 | |||
186 | pr_info("IR Sharp protocol handler initialized\n"); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static void __exit ir_sharp_decode_exit(void) | ||
191 | { | ||
192 | ir_raw_handler_unregister(&sharp_handler); | ||
193 | } | ||
194 | |||
195 | module_init(ir_sharp_decode_init); | ||
196 | module_exit(ir_sharp_decode_exit); | ||
197 | |||
198 | MODULE_LICENSE("GPL"); | ||
199 | MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>"); | ||
200 | MODULE_DESCRIPTION("Sharp IR protocol decoder"); | ||
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h index 70a180bb0bd0..c40d6660acac 100644 --- a/drivers/media/rc/rc-core-priv.h +++ b/drivers/media/rc/rc-core-priv.h | |||
@@ -88,6 +88,12 @@ struct ir_raw_event_ctrl { | |||
88 | unsigned count; | 88 | unsigned count; |
89 | u64 bits; | 89 | u64 bits; |
90 | } sanyo; | 90 | } sanyo; |
91 | struct sharp_dec { | ||
92 | int state; | ||
93 | unsigned count; | ||
94 | u32 bits; | ||
95 | unsigned int pulse_len; | ||
96 | } sharp; | ||
91 | struct mce_kbd_dec { | 97 | struct mce_kbd_dec { |
92 | struct input_dev *idev; | 98 | struct input_dev *idev; |
93 | struct timer_list rx_timeout; | 99 | struct timer_list rx_timeout; |