blob: a58c717ec6b06694fc58769c4cccbf3169f62dff [file] [log] [blame]
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -03001/* ir-raw-event.c - handle IR Pulse/Space event
2 *
3 * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation version 2 of the License.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <media/ir-core.h>
16
17/* Start time: 4.5 ms */
18#define MIN_START_TIME 3900000
19#define MAX_START_TIME 5100000
20
21/* Pulse time: 560 us */
22#define MIN_PULSE_TIME 460000
23#define MAX_PULSE_TIME 660000
24
25/* Bit 1 space time: 2.25ms-560 us */
26#define MIN_BIT1_TIME 1490000
27#define MAX_BIT1_TIME 1890000
28
29/* Bit 0 space time: 1.12ms-560 us */
30#define MIN_BIT0_TIME 360000
31#define MAX_BIT0_TIME 760000
32
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030033/**
34 * __ir_nec_decode() - Decode one NEC pulsecode
35 * @input_dev: the struct input_dev descriptor of the device
36 * @evs: event array with type/duration of pulse/space
37 * @len: length of the array
38 * @pos: position to start seeking for a code
39 * This function returns the decoded ircode or -EINVAL if no pulse got decoded
40 */
41static int __ir_nec_decode(struct input_dev *input_dev,
42 struct ir_raw_event *evs,
43 int len, int *pos)
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030044{
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030045 int count = -1;
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030046 int ircode = 0, not_code = 0;
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030047
48 /* Be sure that the first event is an start one and is a pulse */
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030049 for (; *pos < len; (*pos)++) {
50 if (evs[*pos].type & (IR_START_EVENT | IR_PULSE))
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030051 break;
52 }
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030053 (*pos)++; /* First event doesn't contain data */
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030054
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030055 if (*pos >= len)
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030056 return 0;
57
58 /* First space should have 4.5 ms otherwise is not NEC protocol */
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030059 if ((evs[*pos].delta.tv_nsec < MIN_START_TIME) |
60 (evs[*pos].delta.tv_nsec > MAX_START_TIME) |
61 (evs[*pos].type != IR_SPACE))
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030062 goto err;
63
64 /*
65 * FIXME: need to implement the repeat sequence
66 */
67
68 count = 0;
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030069 for ((*pos)++; *pos < len; (*pos)++) {
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030070 int bit;
71
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030072 if ((evs[*pos].delta.tv_nsec < MIN_PULSE_TIME) |
73 (evs[*pos].delta.tv_nsec > MAX_PULSE_TIME) |
74 (evs[*pos].type != IR_PULSE))
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030075 goto err;
76
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030077 if (++*pos >= len)
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030078 goto err;
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030079 if (evs[*pos].type != IR_SPACE)
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030080 goto err;
81
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030082 if ((evs[*pos].delta.tv_nsec > MIN_BIT1_TIME) &&
83 (evs[*pos].delta.tv_nsec < MAX_BIT1_TIME))
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030084 bit = 1;
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -030085 else if ((evs[*pos].delta.tv_nsec > MIN_BIT0_TIME) &&
86 (evs[*pos].delta.tv_nsec < MAX_BIT0_TIME))
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -030087 bit = 0;
88 else
89 goto err;
90
91 if (bit) {
92 int shift = count;
93 /* Address first, then command */
94 if (shift < 8) {
95 shift += 8;
96 ircode |= 1 << shift;
97 } else if (shift < 16) {
98 not_code |= 1 << shift;
99 } else if (shift < 24) {
100 shift -= 16;
101 ircode |= 1 << shift;
102 } else {
103 shift -= 24;
104 not_code |= 1 << shift;
105 }
106 }
107 if (++count == 32)
108 break;
109 }
110
111 /*
112 * Fixme: may need to accept Extended NEC protocol?
113 */
114 if ((ircode & ~not_code) != ircode) {
115 IR_dprintk(1, "NEC checksum error: code 0x%04x, not-code 0x%04x\n",
116 ircode, not_code);
117 return -EINVAL;
118 }
119
120 IR_dprintk(1, "NEC scancode 0x%04x\n", ircode);
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -0300121 ir_keydown(input_dev, ircode);
122 ir_keyup(input_dev);
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -0300123
124 return ircode;
125err:
126 IR_dprintk(1, "NEC decoded failed at bit %d while decoding %luus time\n",
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -0300127 count, (evs[*pos].delta.tv_nsec + 500) / 1000);
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -0300128
129 return -EINVAL;
130}
Mauro Carvalho Chehabada39632010-03-21 12:24:24 -0300131
132/**
133 * __ir_nec_decode() - Decodes all NEC pulsecodes on a given array
134 * @input_dev: the struct input_dev descriptor of the device
135 * @evs: event array with type/duration of pulse/space
136 * @len: length of the array
137 * This function returns the number of decoded pulses or -EINVAL if no
138 * pulse got decoded
139 */
140int ir_nec_decode(struct input_dev *input_dev,
141 struct ir_raw_event *evs,
142 int len)
143{
144 int pos = 0;
145 int rc = 0;
146
147 while (pos < len) {
148 if (__ir_nec_decode(input_dev, evs, len, &pos) >= 0)
149 rc++;
150 }
151
152 if (!rc)
153 return -EINVAL;
154 return rc;
155}
156
Mauro Carvalho Chehaba3572c32010-03-20 20:59:44 -0300157EXPORT_SYMBOL_GPL(ir_nec_decode);