1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* ir-rc6-decoder.c - A decoder for the RC6 IR protocol |
3 | * |
4 | * Copyright (C) 2010 by David Härdeman <david@hardeman.nu> |
5 | */ |
6 | |
7 | #include "rc-core-priv.h" |
8 | #include <linux/module.h> |
9 | |
10 | /* |
11 | * This decoder currently supports: |
12 | * RC6-0-16 (standard toggle bit in header) |
13 | * RC6-6A-20 (no toggle bit) |
14 | * RC6-6A-24 (no toggle bit) |
15 | * RC6-6A-32 (MCE version with toggle bit in body) |
16 | */ |
17 | |
18 | #define RC6_UNIT 444 /* microseconds */ |
19 | #define 4 /* not including toggle bit */ |
20 | #define RC6_0_NBITS 16 |
21 | #define RC6_6A_32_NBITS 32 |
22 | #define RC6_6A_NBITS 128 /* Variable 8..128 */ |
23 | #define RC6_PREFIX_PULSE (6 * RC6_UNIT) |
24 | #define RC6_PREFIX_SPACE (2 * RC6_UNIT) |
25 | #define RC6_BIT_START (1 * RC6_UNIT) |
26 | #define RC6_BIT_END (1 * RC6_UNIT) |
27 | #define RC6_TOGGLE_START (2 * RC6_UNIT) |
28 | #define RC6_TOGGLE_END (2 * RC6_UNIT) |
29 | #define RC6_SUFFIX_SPACE (6 * RC6_UNIT) |
30 | #define RC6_MODE_MASK 0x07 /* for the header bits */ |
31 | #define RC6_STARTBIT_MASK 0x08 /* for the header bits */ |
32 | #define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ |
33 | #define RC6_6A_LCC_MASK 0xffff0000 /* RC6-6A-32 long customer code mask */ |
34 | #define RC6_6A_MCE_CC 0x800f0000 /* MCE customer code */ |
35 | #define RC6_6A_ZOTAC_CC 0x80340000 /* Zotac customer code */ |
36 | #define RC6_6A_KATHREIN_CC 0x80460000 /* Kathrein RCU-676 customer code */ |
37 | #ifndef CHAR_BIT |
38 | #define CHAR_BIT 8 /* Normally in <limits.h> */ |
39 | #endif |
40 | |
41 | enum rc6_mode { |
42 | RC6_MODE_0, |
43 | RC6_MODE_6A, |
44 | RC6_MODE_UNKNOWN, |
45 | }; |
46 | |
47 | enum rc6_state { |
48 | STATE_INACTIVE, |
49 | STATE_PREFIX_SPACE, |
50 | , |
51 | , |
52 | STATE_TOGGLE_START, |
53 | STATE_TOGGLE_END, |
54 | STATE_BODY_BIT_START, |
55 | STATE_BODY_BIT_END, |
56 | STATE_FINISHED, |
57 | }; |
58 | |
59 | static enum rc6_mode rc6_mode(struct rc6_dec *data) |
60 | { |
61 | switch (data->header & RC6_MODE_MASK) { |
62 | case 0: |
63 | return RC6_MODE_0; |
64 | case 6: |
65 | if (!data->toggle) |
66 | return RC6_MODE_6A; |
67 | fallthrough; |
68 | default: |
69 | return RC6_MODE_UNKNOWN; |
70 | } |
71 | } |
72 | |
73 | /** |
74 | * ir_rc6_decode() - Decode one RC6 pulse or space |
75 | * @dev: the struct rc_dev descriptor of the device |
76 | * @ev: the struct ir_raw_event descriptor of the pulse/space |
77 | * |
78 | * This function returns -EINVAL if the pulse violates the state machine |
79 | */ |
80 | static int ir_rc6_decode(struct rc_dev *dev, struct ir_raw_event ev) |
81 | { |
82 | struct rc6_dec *data = &dev->raw->rc6; |
83 | u32 scancode; |
84 | u8 toggle; |
85 | enum rc_proto protocol; |
86 | |
87 | if (!is_timing_event(ev)) { |
88 | if (ev.overflow) |
89 | data->state = STATE_INACTIVE; |
90 | return 0; |
91 | } |
92 | |
93 | if (!geq_margin(d1: ev.duration, RC6_UNIT, RC6_UNIT / 2)) |
94 | goto out; |
95 | |
96 | again: |
97 | dev_dbg(&dev->dev, "RC6 decode started at state %i (%uus %s)\n" , |
98 | data->state, ev.duration, TO_STR(ev.pulse)); |
99 | |
100 | if (!geq_margin(d1: ev.duration, RC6_UNIT, RC6_UNIT / 2)) |
101 | return 0; |
102 | |
103 | switch (data->state) { |
104 | |
105 | case STATE_INACTIVE: |
106 | if (!ev.pulse) |
107 | break; |
108 | |
109 | /* Note: larger margin on first pulse since each RC6_UNIT |
110 | is quite short and some hardware takes some time to |
111 | adjust to the signal */ |
112 | if (!eq_margin(d1: ev.duration, RC6_PREFIX_PULSE, RC6_UNIT)) |
113 | break; |
114 | |
115 | data->state = STATE_PREFIX_SPACE; |
116 | data->count = 0; |
117 | return 0; |
118 | |
119 | case STATE_PREFIX_SPACE: |
120 | if (ev.pulse) |
121 | break; |
122 | |
123 | if (!eq_margin(d1: ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2)) |
124 | break; |
125 | |
126 | data->state = STATE_HEADER_BIT_START; |
127 | data->header = 0; |
128 | return 0; |
129 | |
130 | case STATE_HEADER_BIT_START: |
131 | if (!eq_margin(d1: ev.duration, RC6_BIT_START, RC6_UNIT / 2)) |
132 | break; |
133 | |
134 | data->header <<= 1; |
135 | if (ev.pulse) |
136 | data->header |= 1; |
137 | data->count++; |
138 | data->state = STATE_HEADER_BIT_END; |
139 | return 0; |
140 | |
141 | case STATE_HEADER_BIT_END: |
142 | if (data->count == RC6_HEADER_NBITS) |
143 | data->state = STATE_TOGGLE_START; |
144 | else |
145 | data->state = STATE_HEADER_BIT_START; |
146 | |
147 | decrease_duration(ev: &ev, RC6_BIT_END); |
148 | goto again; |
149 | |
150 | case STATE_TOGGLE_START: |
151 | if (!eq_margin(d1: ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2)) |
152 | break; |
153 | |
154 | data->toggle = ev.pulse; |
155 | data->state = STATE_TOGGLE_END; |
156 | return 0; |
157 | |
158 | case STATE_TOGGLE_END: |
159 | if (!(data->header & RC6_STARTBIT_MASK)) { |
160 | dev_dbg(&dev->dev, "RC6 invalid start bit\n" ); |
161 | break; |
162 | } |
163 | |
164 | data->state = STATE_BODY_BIT_START; |
165 | decrease_duration(ev: &ev, RC6_TOGGLE_END); |
166 | data->count = 0; |
167 | data->body = 0; |
168 | |
169 | switch (rc6_mode(data)) { |
170 | case RC6_MODE_0: |
171 | data->wanted_bits = RC6_0_NBITS; |
172 | break; |
173 | case RC6_MODE_6A: |
174 | data->wanted_bits = RC6_6A_NBITS; |
175 | break; |
176 | default: |
177 | dev_dbg(&dev->dev, "RC6 unknown mode\n" ); |
178 | goto out; |
179 | } |
180 | goto again; |
181 | |
182 | case STATE_BODY_BIT_START: |
183 | if (eq_margin(d1: ev.duration, RC6_BIT_START, RC6_UNIT / 2)) { |
184 | /* Discard LSB's that won't fit in data->body */ |
185 | if (data->count++ < CHAR_BIT * sizeof data->body) { |
186 | data->body <<= 1; |
187 | if (ev.pulse) |
188 | data->body |= 1; |
189 | } |
190 | data->state = STATE_BODY_BIT_END; |
191 | return 0; |
192 | } else if (RC6_MODE_6A == rc6_mode(data) && !ev.pulse && |
193 | geq_margin(d1: ev.duration, RC6_SUFFIX_SPACE, RC6_UNIT / 2)) { |
194 | data->state = STATE_FINISHED; |
195 | goto again; |
196 | } |
197 | break; |
198 | |
199 | case STATE_BODY_BIT_END: |
200 | if (data->count == data->wanted_bits) |
201 | data->state = STATE_FINISHED; |
202 | else |
203 | data->state = STATE_BODY_BIT_START; |
204 | |
205 | decrease_duration(ev: &ev, RC6_BIT_END); |
206 | goto again; |
207 | |
208 | case STATE_FINISHED: |
209 | if (ev.pulse) |
210 | break; |
211 | |
212 | switch (rc6_mode(data)) { |
213 | case RC6_MODE_0: |
214 | scancode = data->body; |
215 | toggle = data->toggle; |
216 | protocol = RC_PROTO_RC6_0; |
217 | dev_dbg(&dev->dev, "RC6(0) scancode 0x%04x (toggle: %u)\n" , |
218 | scancode, toggle); |
219 | break; |
220 | |
221 | case RC6_MODE_6A: |
222 | if (data->count > CHAR_BIT * sizeof data->body) { |
223 | dev_dbg(&dev->dev, "RC6 too many (%u) data bits\n" , |
224 | data->count); |
225 | goto out; |
226 | } |
227 | |
228 | scancode = data->body; |
229 | switch (data->count) { |
230 | case 20: |
231 | protocol = RC_PROTO_RC6_6A_20; |
232 | toggle = 0; |
233 | break; |
234 | case 24: |
235 | protocol = RC_PROTO_RC6_6A_24; |
236 | toggle = 0; |
237 | break; |
238 | case 32: |
239 | switch (scancode & RC6_6A_LCC_MASK) { |
240 | case RC6_6A_MCE_CC: |
241 | case RC6_6A_KATHREIN_CC: |
242 | case RC6_6A_ZOTAC_CC: |
243 | protocol = RC_PROTO_RC6_MCE; |
244 | toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK); |
245 | scancode &= ~RC6_6A_MCE_TOGGLE_MASK; |
246 | break; |
247 | default: |
248 | protocol = RC_PROTO_RC6_6A_32; |
249 | toggle = 0; |
250 | break; |
251 | } |
252 | break; |
253 | default: |
254 | dev_dbg(&dev->dev, "RC6(6A) unsupported length\n" ); |
255 | goto out; |
256 | } |
257 | |
258 | dev_dbg(&dev->dev, "RC6(6A) proto 0x%04x, scancode 0x%08x (toggle: %u)\n" , |
259 | protocol, scancode, toggle); |
260 | break; |
261 | default: |
262 | dev_dbg(&dev->dev, "RC6 unknown mode\n" ); |
263 | goto out; |
264 | } |
265 | |
266 | rc_keydown(dev, protocol, scancode, toggle); |
267 | data->state = STATE_INACTIVE; |
268 | return 0; |
269 | } |
270 | |
271 | out: |
272 | dev_dbg(&dev->dev, "RC6 decode failed at state %i (%uus %s)\n" , |
273 | data->state, ev.duration, TO_STR(ev.pulse)); |
274 | data->state = STATE_INACTIVE; |
275 | return -EINVAL; |
276 | } |
277 | |
278 | static const struct ir_raw_timings_manchester ir_rc6_timings[4] = { |
279 | { |
280 | .leader_pulse = RC6_PREFIX_PULSE, |
281 | .leader_space = RC6_PREFIX_SPACE, |
282 | .clock = RC6_UNIT, |
283 | .invert = 1, |
284 | }, |
285 | { |
286 | .clock = RC6_UNIT * 2, |
287 | .invert = 1, |
288 | }, |
289 | { |
290 | .clock = RC6_UNIT, |
291 | .invert = 1, |
292 | .trailer_space = RC6_SUFFIX_SPACE, |
293 | }, |
294 | }; |
295 | |
296 | /** |
297 | * ir_rc6_encode() - Encode a scancode as a stream of raw events |
298 | * |
299 | * @protocol: protocol to encode |
300 | * @scancode: scancode to encode |
301 | * @events: array of raw ir events to write into |
302 | * @max: maximum size of @events |
303 | * |
304 | * Returns: The number of events written. |
305 | * -ENOBUFS if there isn't enough space in the array to fit the |
306 | * encoding. In this case all @max events will have been written. |
307 | * -EINVAL if the scancode is ambiguous or invalid. |
308 | */ |
309 | static int ir_rc6_encode(enum rc_proto protocol, u32 scancode, |
310 | struct ir_raw_event *events, unsigned int max) |
311 | { |
312 | int ret; |
313 | struct ir_raw_event *e = events; |
314 | |
315 | if (protocol == RC_PROTO_RC6_0) { |
316 | /* Modulate the header (Start Bit & Mode-0) */ |
317 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
318 | timings: &ir_rc6_timings[0], |
319 | RC6_HEADER_NBITS, data: (1 << 3)); |
320 | if (ret < 0) |
321 | return ret; |
322 | |
323 | /* Modulate Trailer Bit */ |
324 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
325 | timings: &ir_rc6_timings[1], n: 1, data: 0); |
326 | if (ret < 0) |
327 | return ret; |
328 | |
329 | /* Modulate rest of the data */ |
330 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
331 | timings: &ir_rc6_timings[2], RC6_0_NBITS, |
332 | data: scancode); |
333 | if (ret < 0) |
334 | return ret; |
335 | |
336 | } else { |
337 | int bits; |
338 | |
339 | switch (protocol) { |
340 | case RC_PROTO_RC6_MCE: |
341 | case RC_PROTO_RC6_6A_32: |
342 | bits = 32; |
343 | break; |
344 | case RC_PROTO_RC6_6A_24: |
345 | bits = 24; |
346 | break; |
347 | case RC_PROTO_RC6_6A_20: |
348 | bits = 20; |
349 | break; |
350 | default: |
351 | return -EINVAL; |
352 | } |
353 | |
354 | /* Modulate the header (Start Bit & Header-version 6 */ |
355 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
356 | timings: &ir_rc6_timings[0], |
357 | RC6_HEADER_NBITS, data: (1 << 3 | 6)); |
358 | if (ret < 0) |
359 | return ret; |
360 | |
361 | /* Modulate Trailer Bit */ |
362 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
363 | timings: &ir_rc6_timings[1], n: 1, data: 0); |
364 | if (ret < 0) |
365 | return ret; |
366 | |
367 | /* Modulate rest of the data */ |
368 | ret = ir_raw_gen_manchester(ev: &e, max: max - (e - events), |
369 | timings: &ir_rc6_timings[2], |
370 | n: bits, |
371 | data: scancode); |
372 | if (ret < 0) |
373 | return ret; |
374 | } |
375 | |
376 | return e - events; |
377 | } |
378 | |
379 | static struct ir_raw_handler rc6_handler = { |
380 | .protocols = RC_PROTO_BIT_RC6_0 | RC_PROTO_BIT_RC6_6A_20 | |
381 | RC_PROTO_BIT_RC6_6A_24 | RC_PROTO_BIT_RC6_6A_32 | |
382 | RC_PROTO_BIT_RC6_MCE, |
383 | .decode = ir_rc6_decode, |
384 | .encode = ir_rc6_encode, |
385 | .carrier = 36000, |
386 | .min_timeout = RC6_SUFFIX_SPACE, |
387 | }; |
388 | |
389 | static int __init ir_rc6_decode_init(void) |
390 | { |
391 | ir_raw_handler_register(ir_raw_handler: &rc6_handler); |
392 | |
393 | printk(KERN_INFO "IR RC6 protocol handler initialized\n" ); |
394 | return 0; |
395 | } |
396 | |
397 | static void __exit ir_rc6_decode_exit(void) |
398 | { |
399 | ir_raw_handler_unregister(ir_raw_handler: &rc6_handler); |
400 | } |
401 | |
402 | module_init(ir_rc6_decode_init); |
403 | module_exit(ir_rc6_decode_exit); |
404 | |
405 | MODULE_LICENSE("GPL" ); |
406 | MODULE_AUTHOR("David Härdeman <david@hardeman.nu>" ); |
407 | MODULE_DESCRIPTION("RC6 IR protocol decoder" ); |
408 | |