1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // ir-sanyo-decoder.c - handle SANYO IR Pulse/Space protocol |
3 | // |
4 | // Copyright (C) 2011 by Mauro Carvalho Chehab |
5 | // |
6 | // This protocol uses the NEC protocol timings. However, data is formatted as: |
7 | // 13 bits Custom Code |
8 | // 13 bits NOT(Custom Code) |
9 | // 8 bits Key data |
10 | // 8 bits NOT(Key data) |
11 | // |
12 | // According with LIRC, this protocol is used on Sanyo, Aiwa and Chinon |
13 | // Information for this protocol is available at the Sanyo LC7461 datasheet. |
14 | |
15 | #include <linux/module.h> |
16 | #include <linux/bitrev.h> |
17 | #include "rc-core-priv.h" |
18 | |
19 | #define SANYO_NBITS (13+13+8+8) |
20 | #define SANYO_UNIT 563 /* us */ |
21 | #define (16 * SANYO_UNIT) |
22 | #define (8 * SANYO_UNIT) |
23 | #define SANYO_BIT_PULSE (1 * SANYO_UNIT) |
24 | #define SANYO_BIT_0_SPACE (1 * SANYO_UNIT) |
25 | #define SANYO_BIT_1_SPACE (3 * SANYO_UNIT) |
26 | #define SANYO_REPEAT_SPACE (150 * SANYO_UNIT) |
27 | #define SANYO_TRAILER_PULSE (1 * SANYO_UNIT) |
28 | #define SANYO_TRAILER_SPACE (10 * SANYO_UNIT) /* in fact, 42 */ |
29 | |
30 | enum sanyo_state { |
31 | STATE_INACTIVE, |
32 | , |
33 | STATE_BIT_PULSE, |
34 | STATE_BIT_SPACE, |
35 | STATE_TRAILER_PULSE, |
36 | STATE_TRAILER_SPACE, |
37 | }; |
38 | |
39 | /** |
40 | * ir_sanyo_decode() - Decode one SANYO pulse or space |
41 | * @dev: the struct rc_dev descriptor of the device |
42 | * @ev: 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_sanyo_decode(struct rc_dev *dev, struct ir_raw_event ev) |
47 | { |
48 | struct sanyo_dec *data = &dev->raw->sanyo; |
49 | u32 scancode; |
50 | u16 address; |
51 | u8 command, not_command; |
52 | |
53 | if (!is_timing_event(ev)) { |
54 | if (ev.overflow) { |
55 | dev_dbg(&dev->dev, "SANYO event overflow received. reset to state 0\n" ); |
56 | data->state = STATE_INACTIVE; |
57 | } |
58 | return 0; |
59 | } |
60 | |
61 | dev_dbg(&dev->dev, "SANYO decode started at state %d (%uus %s)\n" , |
62 | data->state, ev.duration, TO_STR(ev.pulse)); |
63 | |
64 | switch (data->state) { |
65 | |
66 | case STATE_INACTIVE: |
67 | if (!ev.pulse) |
68 | break; |
69 | |
70 | if (eq_margin(d1: ev.duration, SANYO_HEADER_PULSE, SANYO_UNIT / 2)) { |
71 | data->count = 0; |
72 | data->state = STATE_HEADER_SPACE; |
73 | return 0; |
74 | } |
75 | break; |
76 | |
77 | |
78 | case STATE_HEADER_SPACE: |
79 | if (ev.pulse) |
80 | break; |
81 | |
82 | if (eq_margin(d1: ev.duration, SANYO_HEADER_SPACE, SANYO_UNIT / 2)) { |
83 | data->state = STATE_BIT_PULSE; |
84 | return 0; |
85 | } |
86 | |
87 | break; |
88 | |
89 | case STATE_BIT_PULSE: |
90 | if (!ev.pulse) |
91 | break; |
92 | |
93 | if (!eq_margin(d1: ev.duration, SANYO_BIT_PULSE, SANYO_UNIT / 2)) |
94 | break; |
95 | |
96 | data->state = STATE_BIT_SPACE; |
97 | return 0; |
98 | |
99 | case STATE_BIT_SPACE: |
100 | if (ev.pulse) |
101 | break; |
102 | |
103 | if (!data->count && geq_margin(d1: ev.duration, SANYO_REPEAT_SPACE, SANYO_UNIT / 2)) { |
104 | rc_repeat(dev); |
105 | dev_dbg(&dev->dev, "SANYO repeat last key\n" ); |
106 | data->state = STATE_INACTIVE; |
107 | return 0; |
108 | } |
109 | |
110 | data->bits <<= 1; |
111 | if (eq_margin(d1: ev.duration, SANYO_BIT_1_SPACE, SANYO_UNIT / 2)) |
112 | data->bits |= 1; |
113 | else if (!eq_margin(d1: ev.duration, SANYO_BIT_0_SPACE, SANYO_UNIT / 2)) |
114 | break; |
115 | data->count++; |
116 | |
117 | if (data->count == SANYO_NBITS) |
118 | data->state = STATE_TRAILER_PULSE; |
119 | else |
120 | data->state = STATE_BIT_PULSE; |
121 | |
122 | return 0; |
123 | |
124 | case STATE_TRAILER_PULSE: |
125 | if (!ev.pulse) |
126 | break; |
127 | |
128 | if (!eq_margin(d1: ev.duration, SANYO_TRAILER_PULSE, SANYO_UNIT / 2)) |
129 | break; |
130 | |
131 | data->state = STATE_TRAILER_SPACE; |
132 | return 0; |
133 | |
134 | case STATE_TRAILER_SPACE: |
135 | if (ev.pulse) |
136 | break; |
137 | |
138 | if (!geq_margin(d1: ev.duration, SANYO_TRAILER_SPACE, SANYO_UNIT / 2)) |
139 | break; |
140 | |
141 | address = bitrev16((data->bits >> 29) & 0x1fff) >> 3; |
142 | /* not_address = bitrev16((data->bits >> 16) & 0x1fff) >> 3; */ |
143 | command = bitrev8((data->bits >> 8) & 0xff); |
144 | not_command = bitrev8((data->bits >> 0) & 0xff); |
145 | |
146 | if ((command ^ not_command) != 0xff) { |
147 | dev_dbg(&dev->dev, "SANYO checksum error: received 0x%08llx\n" , |
148 | data->bits); |
149 | data->state = STATE_INACTIVE; |
150 | return 0; |
151 | } |
152 | |
153 | scancode = address << 8 | command; |
154 | dev_dbg(&dev->dev, "SANYO scancode: 0x%06x\n" , scancode); |
155 | rc_keydown(dev, protocol: RC_PROTO_SANYO, scancode, toggle: 0); |
156 | data->state = STATE_INACTIVE; |
157 | return 0; |
158 | } |
159 | |
160 | dev_dbg(&dev->dev, "SANYO decode failed at count %d state %d (%uus %s)\n" , |
161 | data->count, data->state, ev.duration, TO_STR(ev.pulse)); |
162 | data->state = STATE_INACTIVE; |
163 | return -EINVAL; |
164 | } |
165 | |
166 | static const struct ir_raw_timings_pd ir_sanyo_timings = { |
167 | .header_pulse = SANYO_HEADER_PULSE, |
168 | .header_space = SANYO_HEADER_SPACE, |
169 | .bit_pulse = SANYO_BIT_PULSE, |
170 | .bit_space[0] = SANYO_BIT_0_SPACE, |
171 | .bit_space[1] = SANYO_BIT_1_SPACE, |
172 | .trailer_pulse = SANYO_TRAILER_PULSE, |
173 | .trailer_space = SANYO_TRAILER_SPACE, |
174 | .msb_first = 1, |
175 | }; |
176 | |
177 | /** |
178 | * ir_sanyo_encode() - Encode a scancode as a stream of raw events |
179 | * |
180 | * @protocol: protocol to encode |
181 | * @scancode: scancode to encode |
182 | * @events: array of raw ir events to write into |
183 | * @max: maximum size of @events |
184 | * |
185 | * Returns: The number of events written. |
186 | * -ENOBUFS if there isn't enough space in the array to fit the |
187 | * encoding. In this case all @max events will have been written. |
188 | */ |
189 | static int ir_sanyo_encode(enum rc_proto protocol, u32 scancode, |
190 | struct ir_raw_event *events, unsigned int max) |
191 | { |
192 | struct ir_raw_event *e = events; |
193 | int ret; |
194 | u64 raw; |
195 | |
196 | raw = ((u64)(bitrev16(scancode >> 8) & 0xfff8) << (8 + 8 + 13 - 3)) | |
197 | ((u64)(bitrev16(~scancode >> 8) & 0xfff8) << (8 + 8 + 0 - 3)) | |
198 | ((bitrev8(scancode) & 0xff) << 8) | |
199 | (bitrev8(~scancode) & 0xff); |
200 | |
201 | ret = ir_raw_gen_pd(ev: &e, max, timings: &ir_sanyo_timings, SANYO_NBITS, data: raw); |
202 | if (ret < 0) |
203 | return ret; |
204 | |
205 | return e - events; |
206 | } |
207 | |
208 | static struct ir_raw_handler sanyo_handler = { |
209 | .protocols = RC_PROTO_BIT_SANYO, |
210 | .decode = ir_sanyo_decode, |
211 | .encode = ir_sanyo_encode, |
212 | .carrier = 38000, |
213 | .min_timeout = SANYO_TRAILER_SPACE, |
214 | }; |
215 | |
216 | static int __init ir_sanyo_decode_init(void) |
217 | { |
218 | ir_raw_handler_register(ir_raw_handler: &sanyo_handler); |
219 | |
220 | printk(KERN_INFO "IR SANYO protocol handler initialized\n" ); |
221 | return 0; |
222 | } |
223 | |
224 | static void __exit ir_sanyo_decode_exit(void) |
225 | { |
226 | ir_raw_handler_unregister(ir_raw_handler: &sanyo_handler); |
227 | } |
228 | |
229 | module_init(ir_sanyo_decode_init); |
230 | module_exit(ir_sanyo_decode_exit); |
231 | |
232 | MODULE_LICENSE("GPL v2" ); |
233 | MODULE_AUTHOR("Mauro Carvalho Chehab" ); |
234 | MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)" ); |
235 | MODULE_DESCRIPTION("SANYO IR protocol decoder" ); |
236 | |