1 // SPDX-License-Identifier: GPL-2.0
2 // ir-nec-decoder.c - handle NEC IR Pulse/Space protocol
4 // Copyright (C) 2010 by Mauro Carvalho Chehab
6 #include <linux/bitrev.h>
7 #include <linux/module.h>
8 #include "rc-core-priv.h"
11 #define NEC_UNIT 562500 /* ns */
12 #define NEC_HEADER_PULSE (16 * NEC_UNIT)
13 #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
14 #define NEC_HEADER_SPACE (8 * NEC_UNIT)
15 #define NEC_REPEAT_SPACE (4 * NEC_UNIT)
16 #define NEC_BIT_PULSE (1 * NEC_UNIT)
17 #define NEC_BIT_0_SPACE (1 * NEC_UNIT)
18 #define NEC_BIT_1_SPACE (3 * NEC_UNIT)
19 #define NEC_TRAILER_PULSE (1 * NEC_UNIT)
20 #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
21 #define NECX_REPEAT_BITS 1
33 * ir_nec_decode() - Decode one NEC pulse or space
34 * @dev: the struct rc_dev descriptor of the device
35 * @ev: the struct ir_raw_event descriptor of the pulse/space
37 * This function returns -EINVAL if the pulse violates the state machine
39 static int ir_nec_decode(struct rc_dev
*dev
, struct ir_raw_event ev
)
41 struct nec_dec
*data
= &dev
->raw
->nec
;
43 enum rc_proto rc_proto
;
44 u8 address
, not_address
, command
, not_command
;
46 if (!is_timing_event(ev
)) {
48 data
->state
= STATE_INACTIVE
;
52 IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
53 data
->state
, TO_US(ev
.duration
), TO_STR(ev
.pulse
));
55 switch (data
->state
) {
61 if (eq_margin(ev
.duration
, NEC_HEADER_PULSE
, NEC_UNIT
* 2)) {
62 data
->is_nec_x
= false;
63 data
->necx_repeat
= false;
64 } else if (eq_margin(ev
.duration
, NECX_HEADER_PULSE
, NEC_UNIT
/ 2))
65 data
->is_nec_x
= true;
70 data
->state
= STATE_HEADER_SPACE
;
73 case STATE_HEADER_SPACE
:
77 if (eq_margin(ev
.duration
, NEC_HEADER_SPACE
, NEC_UNIT
)) {
78 data
->state
= STATE_BIT_PULSE
;
80 } else if (eq_margin(ev
.duration
, NEC_REPEAT_SPACE
, NEC_UNIT
/ 2)) {
81 data
->state
= STATE_TRAILER_PULSE
;
91 if (!eq_margin(ev
.duration
, NEC_BIT_PULSE
, NEC_UNIT
/ 2))
94 data
->state
= STATE_BIT_SPACE
;
101 if (data
->necx_repeat
&& data
->count
== NECX_REPEAT_BITS
&&
102 geq_margin(ev
.duration
,
103 NEC_TRAILER_SPACE
, NEC_UNIT
/ 2)) {
104 IR_dprintk(1, "Repeat last key\n");
106 data
->state
= STATE_INACTIVE
;
109 } else if (data
->count
> NECX_REPEAT_BITS
)
110 data
->necx_repeat
= false;
113 if (eq_margin(ev
.duration
, NEC_BIT_1_SPACE
, NEC_UNIT
/ 2))
115 else if (!eq_margin(ev
.duration
, NEC_BIT_0_SPACE
, NEC_UNIT
/ 2))
119 if (data
->count
== NEC_NBITS
)
120 data
->state
= STATE_TRAILER_PULSE
;
122 data
->state
= STATE_BIT_PULSE
;
126 case STATE_TRAILER_PULSE
:
130 if (!eq_margin(ev
.duration
, NEC_TRAILER_PULSE
, NEC_UNIT
/ 2))
133 data
->state
= STATE_TRAILER_SPACE
;
136 case STATE_TRAILER_SPACE
:
140 if (!geq_margin(ev
.duration
, NEC_TRAILER_SPACE
, NEC_UNIT
/ 2))
143 if (data
->count
== NEC_NBITS
) {
144 address
= bitrev8((data
->bits
>> 24) & 0xff);
145 not_address
= bitrev8((data
->bits
>> 16) & 0xff);
146 command
= bitrev8((data
->bits
>> 8) & 0xff);
147 not_command
= bitrev8((data
->bits
>> 0) & 0xff);
149 scancode
= ir_nec_bytes_to_scancode(address
,
156 data
->necx_repeat
= true;
158 rc_keydown(dev
, rc_proto
, scancode
, 0);
163 data
->state
= STATE_INACTIVE
;
167 IR_dprintk(1, "NEC decode failed at count %d state %d (%uus %s)\n",
168 data
->count
, data
->state
, TO_US(ev
.duration
), TO_STR(ev
.pulse
));
169 data
->state
= STATE_INACTIVE
;
174 * ir_nec_scancode_to_raw() - encode an NEC scancode ready for modulation.
175 * @protocol: specific protocol to use
176 * @scancode: a single NEC scancode.
178 static u32
ir_nec_scancode_to_raw(enum rc_proto protocol
, u32 scancode
)
180 unsigned int addr
, addr_inv
, data
, data_inv
;
182 data
= scancode
& 0xff;
184 if (protocol
== RC_PROTO_NEC32
) {
185 /* 32-bit NEC (used by Apple and TiVo remotes) */
186 /* scan encoding: aaAAddDD */
187 addr_inv
= (scancode
>> 24) & 0xff;
188 addr
= (scancode
>> 16) & 0xff;
189 data_inv
= (scancode
>> 8) & 0xff;
190 } else if (protocol
== RC_PROTO_NECX
) {
192 /* scan encoding AAaaDD */
193 addr
= (scancode
>> 16) & 0xff;
194 addr_inv
= (scancode
>> 8) & 0xff;
195 data_inv
= data
^ 0xff;
198 /* scan encoding: AADD */
199 addr
= (scancode
>> 8) & 0xff;
200 addr_inv
= addr
^ 0xff;
201 data_inv
= data
^ 0xff;
204 /* raw encoding: ddDDaaAA */
205 return data_inv
<< 24 |
211 static const struct ir_raw_timings_pd ir_nec_timings
= {
212 .header_pulse
= NEC_HEADER_PULSE
,
213 .header_space
= NEC_HEADER_SPACE
,
214 .bit_pulse
= NEC_BIT_PULSE
,
215 .bit_space
[0] = NEC_BIT_0_SPACE
,
216 .bit_space
[1] = NEC_BIT_1_SPACE
,
217 .trailer_pulse
= NEC_TRAILER_PULSE
,
218 .trailer_space
= NEC_TRAILER_SPACE
,
223 * ir_nec_encode() - Encode a scancode as a stream of raw events
225 * @protocol: protocol to encode
226 * @scancode: scancode to encode
227 * @events: array of raw ir events to write into
228 * @max: maximum size of @events
230 * Returns: The number of events written.
231 * -ENOBUFS if there isn't enough space in the array to fit the
232 * encoding. In this case all @max events will have been written.
234 static int ir_nec_encode(enum rc_proto protocol
, u32 scancode
,
235 struct ir_raw_event
*events
, unsigned int max
)
237 struct ir_raw_event
*e
= events
;
241 /* Convert a NEC scancode to raw NEC data */
242 raw
= ir_nec_scancode_to_raw(protocol
, scancode
);
244 /* Modulate the raw data using a pulse distance modulation */
245 ret
= ir_raw_gen_pd(&e
, max
, &ir_nec_timings
, NEC_NBITS
, raw
);
252 static struct ir_raw_handler nec_handler
= {
253 .protocols
= RC_PROTO_BIT_NEC
| RC_PROTO_BIT_NECX
|
255 .decode
= ir_nec_decode
,
256 .encode
= ir_nec_encode
,
260 static int __init
ir_nec_decode_init(void)
262 ir_raw_handler_register(&nec_handler
);
264 printk(KERN_INFO
"IR NEC protocol handler initialized\n");
268 static void __exit
ir_nec_decode_exit(void)
270 ir_raw_handler_unregister(&nec_handler
);
273 module_init(ir_nec_decode_init
);
274 module_exit(ir_nec_decode_exit
);
276 MODULE_LICENSE("GPL v2");
277 MODULE_AUTHOR("Mauro Carvalho Chehab");
278 MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
279 MODULE_DESCRIPTION("NEC IR protocol decoder");