xref: /linux/drivers/media/rc/ir-sharp-decoder.c (revision 0d3b051adbb72ed81956447d0d1e54d5943ee6f5)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* ir-sharp-decoder.c - handle Sharp IR Pulse/Space protocol
3  *
4  * Copyright (C) 2013-2014 Imagination Technologies Ltd.
5  *
6  * Based on NEC decoder:
7  * Copyright (C) 2010 by Mauro Carvalho Chehab
8  */
9 
10 #include <linux/bitrev.h>
11 #include <linux/module.h>
12 #include "rc-core-priv.h"
13 
14 #define SHARP_NBITS		15
15 #define SHARP_UNIT		40  /* us */
16 #define SHARP_BIT_PULSE		(8    * SHARP_UNIT) /* 320us */
17 #define SHARP_BIT_0_PERIOD	(25   * SHARP_UNIT) /* 1ms (680us space) */
18 #define SHARP_BIT_1_PERIOD	(50   * SHARP_UNIT) /* 2ms (1680ms space) */
19 #define SHARP_ECHO_SPACE	(1000 * SHARP_UNIT) /* 40 ms */
20 #define SHARP_TRAILER_SPACE	(125  * SHARP_UNIT) /* 5 ms (even longer) */
21 
22 enum sharp_state {
23 	STATE_INACTIVE,
24 	STATE_BIT_PULSE,
25 	STATE_BIT_SPACE,
26 	STATE_TRAILER_PULSE,
27 	STATE_ECHO_SPACE,
28 	STATE_TRAILER_SPACE,
29 };
30 
31 /**
32  * ir_sharp_decode() - Decode one Sharp pulse or space
33  * @dev:	the struct rc_dev descriptor of the device
34  * @ev:		the struct ir_raw_event descriptor of the pulse/space
35  *
36  * This function returns -EINVAL if the pulse violates the state machine
37  */
38 static int ir_sharp_decode(struct rc_dev *dev, struct ir_raw_event ev)
39 {
40 	struct sharp_dec *data = &dev->raw->sharp;
41 	u32 msg, echo, address, command, scancode;
42 
43 	if (!is_timing_event(ev)) {
44 		if (ev.reset)
45 			data->state = STATE_INACTIVE;
46 		return 0;
47 	}
48 
49 	dev_dbg(&dev->dev, "Sharp decode started at state %d (%uus %s)\n",
50 		data->state, ev.duration, TO_STR(ev.pulse));
51 
52 	switch (data->state) {
53 
54 	case STATE_INACTIVE:
55 		if (!ev.pulse)
56 			break;
57 
58 		if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
59 			       SHARP_BIT_PULSE / 2))
60 			break;
61 
62 		data->count = 0;
63 		data->pulse_len = ev.duration;
64 		data->state = STATE_BIT_SPACE;
65 		return 0;
66 
67 	case STATE_BIT_PULSE:
68 		if (!ev.pulse)
69 			break;
70 
71 		if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
72 			       SHARP_BIT_PULSE / 2))
73 			break;
74 
75 		data->pulse_len = ev.duration;
76 		data->state = STATE_BIT_SPACE;
77 		return 0;
78 
79 	case STATE_BIT_SPACE:
80 		if (ev.pulse)
81 			break;
82 
83 		data->bits <<= 1;
84 		if (eq_margin(data->pulse_len + ev.duration, SHARP_BIT_1_PERIOD,
85 			      SHARP_BIT_PULSE * 2))
86 			data->bits |= 1;
87 		else if (!eq_margin(data->pulse_len + ev.duration,
88 				    SHARP_BIT_0_PERIOD, SHARP_BIT_PULSE * 2))
89 			break;
90 		data->count++;
91 
92 		if (data->count == SHARP_NBITS ||
93 		    data->count == SHARP_NBITS * 2)
94 			data->state = STATE_TRAILER_PULSE;
95 		else
96 			data->state = STATE_BIT_PULSE;
97 
98 		return 0;
99 
100 	case STATE_TRAILER_PULSE:
101 		if (!ev.pulse)
102 			break;
103 
104 		if (!eq_margin(ev.duration, SHARP_BIT_PULSE,
105 			       SHARP_BIT_PULSE / 2))
106 			break;
107 
108 		if (data->count == SHARP_NBITS) {
109 			/* exp,chk bits should be 1,0 */
110 			if ((data->bits & 0x3) != 0x2 &&
111 			/* DENON variant, both chk bits 0 */
112 			    (data->bits & 0x3) != 0x0)
113 				break;
114 			data->state = STATE_ECHO_SPACE;
115 		} else {
116 			data->state = STATE_TRAILER_SPACE;
117 		}
118 		return 0;
119 
120 	case STATE_ECHO_SPACE:
121 		if (ev.pulse)
122 			break;
123 
124 		if (!eq_margin(ev.duration, SHARP_ECHO_SPACE,
125 			       SHARP_ECHO_SPACE / 4))
126 			break;
127 
128 		data->state = STATE_BIT_PULSE;
129 
130 		return 0;
131 
132 	case STATE_TRAILER_SPACE:
133 		if (ev.pulse)
134 			break;
135 
136 		if (!geq_margin(ev.duration, SHARP_TRAILER_SPACE,
137 				SHARP_BIT_PULSE / 2))
138 			break;
139 
140 		/* Validate - command, ext, chk should be inverted in 2nd */
141 		msg = (data->bits >> 15) & 0x7fff;
142 		echo = data->bits & 0x7fff;
143 		if ((msg ^ echo) != 0x3ff) {
144 			dev_dbg(&dev->dev,
145 				"Sharp checksum error: received 0x%04x, 0x%04x\n",
146 				msg, echo);
147 			break;
148 		}
149 
150 		address = bitrev8((msg >> 7) & 0xf8);
151 		command = bitrev8((msg >> 2) & 0xff);
152 
153 		scancode = address << 8 | command;
154 		dev_dbg(&dev->dev, "Sharp scancode 0x%04x\n", scancode);
155 
156 		rc_keydown(dev, RC_PROTO_SHARP, scancode, 0);
157 		data->state = STATE_INACTIVE;
158 		return 0;
159 	}
160 
161 	dev_dbg(&dev->dev, "Sharp decode failed at count %d state %d (%uus %s)\n",
162 		data->count, data->state, ev.duration, TO_STR(ev.pulse));
163 	data->state = STATE_INACTIVE;
164 	return -EINVAL;
165 }
166 
167 static const struct ir_raw_timings_pd ir_sharp_timings = {
168 	.header_pulse  = 0,
169 	.header_space  = 0,
170 	.bit_pulse     = SHARP_BIT_PULSE,
171 	.bit_space[0]  = SHARP_BIT_0_PERIOD,
172 	.bit_space[1]  = SHARP_BIT_1_PERIOD,
173 	.trailer_pulse = SHARP_BIT_PULSE,
174 	.trailer_space = SHARP_ECHO_SPACE,
175 	.msb_first     = 1,
176 };
177 
178 /**
179  * ir_sharp_encode() - Encode a scancode as a stream of raw events
180  *
181  * @protocol:	protocol to encode
182  * @scancode:	scancode to encode
183  * @events:	array of raw ir events to write into
184  * @max:	maximum size of @events
185  *
186  * Returns:	The number of events written.
187  *		-ENOBUFS if there isn't enough space in the array to fit the
188  *		encoding. In this case all @max events will have been written.
189  */
190 static int ir_sharp_encode(enum rc_proto protocol, u32 scancode,
191 			   struct ir_raw_event *events, unsigned int max)
192 {
193 	struct ir_raw_event *e = events;
194 	int ret;
195 	u32 raw;
196 
197 	raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
198 		bitrev8(scancode);
199 	ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
200 			    (raw << 2) | 2);
201 	if (ret < 0)
202 		return ret;
203 
204 	max -= ret;
205 
206 	raw = (((bitrev8(scancode >> 8) >> 3) << 8) & 0x1f00) |
207 		bitrev8(~scancode);
208 	ret = ir_raw_gen_pd(&e, max, &ir_sharp_timings, SHARP_NBITS,
209 			    (raw << 2) | 1);
210 	if (ret < 0)
211 		return ret;
212 
213 	return e - events;
214 }
215 
216 static struct ir_raw_handler sharp_handler = {
217 	.protocols	= RC_PROTO_BIT_SHARP,
218 	.decode		= ir_sharp_decode,
219 	.encode		= ir_sharp_encode,
220 	.carrier	= 38000,
221 	.min_timeout	= SHARP_ECHO_SPACE + SHARP_ECHO_SPACE / 4,
222 };
223 
224 static int __init ir_sharp_decode_init(void)
225 {
226 	ir_raw_handler_register(&sharp_handler);
227 
228 	pr_info("IR Sharp protocol handler initialized\n");
229 	return 0;
230 }
231 
232 static void __exit ir_sharp_decode_exit(void)
233 {
234 	ir_raw_handler_unregister(&sharp_handler);
235 }
236 
237 module_init(ir_sharp_decode_init);
238 module_exit(ir_sharp_decode_exit);
239 
240 MODULE_LICENSE("GPL");
241 MODULE_AUTHOR("James Hogan <jhogan@kernel.org>");
242 MODULE_DESCRIPTION("Sharp IR protocol decoder");
243