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