aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-04-15 17:46:00 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-19 11:57:42 -0400
commite40b1127f994a427568319d1be9b9e5ab1f58dd1 (patch)
tree5d4f892dbe90588f8932cd4e1768b953814f3f47 /drivers
parent21677cfc562a27e099719d413287bc8d1d24deb7 (diff)
V4L/DVB: ir-core: change duration to be coded as a u32 integer
This patch implements the agreed upon 1:31 integer encoded pulse/duration struct for ir-core raw decoders. All decoders have been tested after the change. Comments are welcome. Signed-off-by: David Härdeman <david@hardeman.nu> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/IR/ir-core-priv.h49
-rw-r--r--drivers/media/IR/ir-nec-decoder.c120
-rw-r--r--drivers/media/IR/ir-raw-event.c30
-rw-r--r--drivers/media/IR/ir-rc5-decoder.c105
-rw-r--r--drivers/media/IR/ir-rc6-decoder.c221
5 files changed, 271 insertions, 254 deletions
diff --git a/drivers/media/IR/ir-core-priv.h b/drivers/media/IR/ir-core-priv.h
index 8c1f84645eaf..77d0b94ede10 100644
--- a/drivers/media/IR/ir-core-priv.h
+++ b/drivers/media/IR/ir-core-priv.h
@@ -22,7 +22,7 @@
22struct ir_raw_handler { 22struct ir_raw_handler {
23 struct list_head list; 23 struct list_head list;
24 24
25 int (*decode)(struct input_dev *input_dev, s64 duration); 25 int (*decode)(struct input_dev *input_dev, struct ir_raw_event event);
26 int (*raw_register)(struct input_dev *input_dev); 26 int (*raw_register)(struct input_dev *input_dev);
27 int (*raw_unregister)(struct input_dev *input_dev); 27 int (*raw_unregister)(struct input_dev *input_dev);
28}; 28};
@@ -36,26 +36,28 @@ struct ir_raw_event_ctrl {
36}; 36};
37 37
38/* macros for IR decoders */ 38/* macros for IR decoders */
39#define PULSE(units) ((units)) 39static inline bool geq_margin(unsigned d1, unsigned d2, unsigned margin) {
40#define SPACE(units) (-(units)) 40 return d1 > (d2 - margin);
41#define IS_RESET(duration) ((duration) == 0) 41}
42#define IS_PULSE(duration) ((duration) > 0) 42
43#define IS_SPACE(duration) ((duration) < 0) 43static inline bool eq_margin(unsigned d1, unsigned d2, unsigned margin) {
44#define DURATION(duration) (abs((duration))) 44 return ((d1 > (d2 - margin)) && (d1 < (d2 + margin)));
45#define IS_TRANSITION(x, y) ((x) * (y) < 0) 45}
46#define DECREASE_DURATION(duration, amount) \ 46
47 do { \ 47static inline bool is_transition(struct ir_raw_event *x, struct ir_raw_event *y) {
48 if (IS_SPACE(duration)) \ 48 return x->pulse != y->pulse;
49 duration += (amount); \ 49}
50 else if (IS_PULSE(duration)) \ 50
51 duration -= (amount); \ 51static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) {
52 } while (0) 52 if (duration > ev->duration)
53 53 ev->duration = 0;
54#define TO_UNITS(duration, unit_len) \ 54 else
55 ((int)((duration) > 0 ? \ 55 ev->duration -= duration;
56 DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\ 56}
57 -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) 57
58#define TO_US(duration) ((int)TO_UNITS(duration, 1000)) 58#define TO_US(duration) (((duration) + 500) / 1000)
59#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
60#define IS_RESET(ev) (ev.duration == 0)
59 61
60/* 62/*
61 * Routines from ir-sysfs.c - Meant to be called only internally inside 63 * Routines from ir-sysfs.c - Meant to be called only internally inside
@@ -70,11 +72,6 @@ void ir_unregister_class(struct input_dev *input_dev);
70 */ 72 */
71int ir_raw_event_register(struct input_dev *input_dev); 73int ir_raw_event_register(struct input_dev *input_dev);
72void ir_raw_event_unregister(struct input_dev *input_dev); 74void ir_raw_event_unregister(struct input_dev *input_dev);
73static inline void ir_raw_event_reset(struct input_dev *input_dev)
74{
75 ir_raw_event_store(input_dev, 0);
76 ir_raw_event_handle(input_dev);
77}
78int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); 75int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
79void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); 76void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
80void ir_raw_init(void); 77void ir_raw_init(void);
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c
index 14609d9580a8..ba79233112ef 100644
--- a/drivers/media/IR/ir-nec-decoder.c
+++ b/drivers/media/IR/ir-nec-decoder.c
@@ -17,13 +17,15 @@
17 17
18#define NEC_NBITS 32 18#define NEC_NBITS 32
19#define NEC_UNIT 562500 /* ns */ 19#define NEC_UNIT 562500 /* ns */
20#define NEC_HEADER_PULSE PULSE(16) 20#define NEC_HEADER_PULSE (16 * NEC_UNIT)
21#define NECX_HEADER_PULSE PULSE(8) /* Less common NEC variant */ 21#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
22#define NEC_HEADER_SPACE SPACE(8) 22#define NEC_HEADER_SPACE (8 * NEC_UNIT)
23#define NEC_REPEAT_SPACE SPACE(4) 23#define NEC_REPEAT_SPACE (8 * NEC_UNIT)
24#define NEC_BIT_PULSE PULSE(1) 24#define NEC_BIT_PULSE (1 * NEC_UNIT)
25#define NEC_BIT_0_SPACE SPACE(1) 25#define NEC_BIT_0_SPACE (1 * NEC_UNIT)
26#define NEC_BIT_1_SPACE SPACE(3) 26#define NEC_BIT_1_SPACE (3 * NEC_UNIT)
27#define NEC_TRAILER_PULSE (1 * NEC_UNIT)
28#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
27 29
28/* Used to register nec_decoder clients */ 30/* Used to register nec_decoder clients */
29static LIST_HEAD(decoder_list); 31static LIST_HEAD(decoder_list);
@@ -119,15 +121,14 @@ static struct attribute_group decoder_attribute_group = {
119/** 121/**
120 * ir_nec_decode() - Decode one NEC pulse or space 122 * ir_nec_decode() - Decode one NEC pulse or space
121 * @input_dev: the struct input_dev descriptor of the device 123 * @input_dev: the struct input_dev descriptor of the device
122 * @duration: duration in ns of pulse/space 124 * @duration: the struct ir_raw_event descriptor of the pulse/space
123 * 125 *
124 * This function returns -EINVAL if the pulse violates the state machine 126 * This function returns -EINVAL if the pulse violates the state machine
125 */ 127 */
126static int ir_nec_decode(struct input_dev *input_dev, s64 duration) 128static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
127{ 129{
128 struct decoder_data *data; 130 struct decoder_data *data;
129 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 131 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
130 int u;
131 u32 scancode; 132 u32 scancode;
132 u8 address, not_address, command, not_command; 133 u8 address, not_address, command, not_command;
133 134
@@ -138,59 +139,88 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
138 if (!data->enabled) 139 if (!data->enabled)
139 return 0; 140 return 0;
140 141
141 if (IS_RESET(duration)) { 142 if (IS_RESET(ev)) {
142 data->state = STATE_INACTIVE; 143 data->state = STATE_INACTIVE;
143 return 0; 144 return 0;
144 } 145 }
145 146
146 u = TO_UNITS(duration, NEC_UNIT); 147 IR_dprintk(2, "NEC decode started at state %d (%uus %s)\n",
147 if (DURATION(u) == 0) 148 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
148 goto out;
149
150 IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n",
151 data->state, u, TO_US(duration));
152 149
153 switch (data->state) { 150 switch (data->state) {
154 151
155 case STATE_INACTIVE: 152 case STATE_INACTIVE:
156 if (u == NEC_HEADER_PULSE || u == NECX_HEADER_PULSE) { 153 if (!ev.pulse)
157 data->count = 0; 154 break;
158 data->state = STATE_HEADER_SPACE; 155
159 } 156 if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) &&
157 !eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
158 break;
159
160 data->count = 0;
161 data->state = STATE_HEADER_SPACE;
160 return 0; 162 return 0;
161 163
162 case STATE_HEADER_SPACE: 164 case STATE_HEADER_SPACE:
163 if (u == NEC_HEADER_SPACE) { 165 if (ev.pulse)
166 break;
167
168 if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
164 data->state = STATE_BIT_PULSE; 169 data->state = STATE_BIT_PULSE;
165 return 0; 170 return 0;
166 } else if (u == NEC_REPEAT_SPACE) { 171 } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
167 ir_repeat(input_dev); 172 ir_repeat(input_dev);
168 IR_dprintk(1, "Repeat last key\n"); 173 IR_dprintk(1, "Repeat last key\n");
169 data->state = STATE_TRAILER_PULSE; 174 data->state = STATE_TRAILER_PULSE;
170 return 0; 175 return 0;
171 } 176 }
177
172 break; 178 break;
173 179
174 case STATE_BIT_PULSE: 180 case STATE_BIT_PULSE:
175 if (u == NEC_BIT_PULSE) { 181 if (!ev.pulse)
176 data->state = STATE_BIT_SPACE; 182 break;
177 return 0; 183
178 } 184 if (!eq_margin(ev.duration, NEC_BIT_PULSE, NEC_UNIT / 2))
179 break; 185 break;
186
187 data->state = STATE_BIT_SPACE;
188 return 0;
180 189
181 case STATE_BIT_SPACE: 190 case STATE_BIT_SPACE:
182 if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE) 191 if (ev.pulse)
183 break; 192 break;
184 193
185 data->nec_bits <<= 1; 194 data->nec_bits <<= 1;
186 if (u == NEC_BIT_1_SPACE) 195 if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
187 data->nec_bits |= 1; 196 data->nec_bits |= 1;
197 else if (!eq_margin(ev.duration, NEC_BIT_0_SPACE, NEC_UNIT / 2))
198 break;
188 data->count++; 199 data->count++;
189 200
190 if (data->count != NEC_NBITS) { 201 if (data->count == NEC_NBITS)
202 data->state = STATE_TRAILER_PULSE;
203 else
191 data->state = STATE_BIT_PULSE; 204 data->state = STATE_BIT_PULSE;
192 return 0; 205
193 } 206 return 0;
207
208 case STATE_TRAILER_PULSE:
209 if (!ev.pulse)
210 break;
211
212 if (!eq_margin(ev.duration, NEC_TRAILER_PULSE, NEC_UNIT / 2))
213 break;
214
215 data->state = STATE_TRAILER_SPACE;
216 return 0;
217
218 case STATE_TRAILER_SPACE:
219 if (ev.pulse)
220 break;
221
222 if (!geq_margin(ev.duration, NEC_TRAILER_SPACE, NEC_UNIT / 2))
223 break;
194 224
195 address = bitrev8((data->nec_bits >> 24) & 0xff); 225 address = bitrev8((data->nec_bits >> 24) & 0xff);
196 not_address = bitrev8((data->nec_bits >> 16) & 0xff); 226 not_address = bitrev8((data->nec_bits >> 16) & 0xff);
@@ -210,34 +240,18 @@ static int ir_nec_decode(struct input_dev *input_dev, s64 duration)
210 command; 240 command;
211 IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); 241 IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode);
212 } else { 242 } else {
213 /* normal NEC */ 243 /* Normal NEC */
214 scancode = address << 8 | command; 244 scancode = address << 8 | command;
215 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); 245 IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
216 } 246 }
217 247
218 ir_keydown(input_dev, scancode, 0); 248 ir_keydown(input_dev, scancode, 0);
219 data->state = STATE_TRAILER_PULSE; 249 data->state = STATE_INACTIVE;
220 return 0; 250 return 0;
221
222 case STATE_TRAILER_PULSE:
223 if (u > 0) {
224 data->state = STATE_TRAILER_SPACE;
225 return 0;
226 }
227 break;
228
229 case STATE_TRAILER_SPACE:
230 if (u < 0) {
231 data->state = STATE_INACTIVE;
232 return 0;
233 }
234
235 break;
236 } 251 }
237 252
238out: 253 IR_dprintk(1, "NEC decode failed at state %d (%uus %s)\n",
239 IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n", 254 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
240 data->state, u, TO_US(duration));
241 data->state = STATE_INACTIVE; 255 data->state = STATE_INACTIVE;
242 return -EINVAL; 256 return -EINVAL;
243} 257}
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index 674442b2f0a8..59f173c45b9d 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -57,12 +57,12 @@ static struct work_struct wq_load;
57 57
58static void ir_raw_event_work(struct work_struct *work) 58static void ir_raw_event_work(struct work_struct *work)
59{ 59{
60 s64 d; 60 struct ir_raw_event ev;
61 struct ir_raw_event_ctrl *raw = 61 struct ir_raw_event_ctrl *raw =
62 container_of(work, struct ir_raw_event_ctrl, rx_work); 62 container_of(work, struct ir_raw_event_ctrl, rx_work);
63 63
64 while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d)) 64 while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev))
65 RUN_DECODER(decode, raw->input_dev, d); 65 RUN_DECODER(decode, raw->input_dev, ev);
66} 66}
67 67
68int ir_raw_event_register(struct input_dev *input_dev) 68int ir_raw_event_register(struct input_dev *input_dev)
@@ -114,21 +114,21 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
114/** 114/**
115 * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders 115 * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders
116 * @input_dev: the struct input_dev device descriptor 116 * @input_dev: the struct input_dev device descriptor
117 * @duration: duration of the pulse or space in ns 117 * @ev: the struct ir_raw_event descriptor of the pulse/space
118 * 118 *
119 * This routine (which may be called from an interrupt context) stores a 119 * This routine (which may be called from an interrupt context) stores a
120 * pulse/space duration for the raw ir decoding state machines. Pulses are 120 * pulse/space duration for the raw ir decoding state machines. Pulses are
121 * signalled as positive values and spaces as negative values. A zero value 121 * signalled as positive values and spaces as negative values. A zero value
122 * will reset the decoding state machines. 122 * will reset the decoding state machines.
123 */ 123 */
124int ir_raw_event_store(struct input_dev *input_dev, s64 duration) 124int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
125{ 125{
126 struct ir_input_dev *ir = input_get_drvdata(input_dev); 126 struct ir_input_dev *ir = input_get_drvdata(input_dev);
127 127
128 if (!ir->raw) 128 if (!ir->raw)
129 return -EINVAL; 129 return -EINVAL;
130 130
131 if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration)) 131 if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
132 return -ENOMEM; 132 return -ENOMEM;
133 133
134 return 0; 134 return 0;
@@ -151,6 +151,7 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
151 struct ir_input_dev *ir = input_get_drvdata(input_dev); 151 struct ir_input_dev *ir = input_get_drvdata(input_dev);
152 ktime_t now; 152 ktime_t now;
153 s64 delta; /* ns */ 153 s64 delta; /* ns */
154 struct ir_raw_event ev;
154 int rc = 0; 155 int rc = 0;
155 156
156 if (!ir->raw) 157 if (!ir->raw)
@@ -163,16 +164,21 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
163 * being called for the first time, note that delta can't 164 * being called for the first time, note that delta can't
164 * possibly be negative. 165 * possibly be negative.
165 */ 166 */
166 if (delta > NSEC_PER_SEC || !ir->raw->last_type) 167 ev.duration = 0;
168 if (delta > IR_MAX_DURATION || !ir->raw->last_type)
167 type |= IR_START_EVENT; 169 type |= IR_START_EVENT;
170 else
171 ev.duration = delta;
168 172
169 if (type & IR_START_EVENT) 173 if (type & IR_START_EVENT)
170 ir_raw_event_reset(input_dev); 174 ir_raw_event_reset(input_dev);
171 else if (ir->raw->last_type & IR_SPACE) 175 else if (ir->raw->last_type & IR_SPACE) {
172 rc = ir_raw_event_store(input_dev, -delta); 176 ev.pulse = false;
173 else if (ir->raw->last_type & IR_PULSE) 177 rc = ir_raw_event_store(input_dev, &ev);
174 rc = ir_raw_event_store(input_dev, delta); 178 } else if (ir->raw->last_type & IR_PULSE) {
175 else 179 ev.pulse = true;
180 rc = ir_raw_event_store(input_dev, &ev);
181 } else
176 return 0; 182 return 0;
177 183
178 ir->raw->last_event = now; 184 ir->raw->last_event = now;
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c
index dd5a4d5f25fd..23cdb1b1a3bc 100644
--- a/drivers/media/IR/ir-rc5-decoder.c
+++ b/drivers/media/IR/ir-rc5-decoder.c
@@ -25,8 +25,10 @@
25#define RC5_NBITS 14 25#define RC5_NBITS 14
26#define RC5X_NBITS 20 26#define RC5X_NBITS 20
27#define CHECK_RC5X_NBITS 8 27#define CHECK_RC5X_NBITS 8
28#define RC5X_SPACE SPACE(4)
29#define RC5_UNIT 888888 /* ns */ 28#define RC5_UNIT 888888 /* ns */
29#define RC5_BIT_START (1 * RC5_UNIT)
30#define RC5_BIT_END (1 * RC5_UNIT)
31#define RC5X_SPACE (4 * RC5_UNIT)
30 32
31/* Used to register rc5_decoder clients */ 33/* Used to register rc5_decoder clients */
32static LIST_HEAD(decoder_list); 34static LIST_HEAD(decoder_list);
@@ -48,7 +50,7 @@ struct decoder_data {
48 /* State machine control */ 50 /* State machine control */
49 enum rc5_state state; 51 enum rc5_state state;
50 u32 rc5_bits; 52 u32 rc5_bits;
51 int last_unit; 53 struct ir_raw_event prev_ev;
52 unsigned count; 54 unsigned count;
53 unsigned wanted_bits; 55 unsigned wanted_bits;
54}; 56};
@@ -124,17 +126,16 @@ static struct attribute_group decoder_attribute_group = {
124/** 126/**
125 * ir_rc5_decode() - Decode one RC-5 pulse or space 127 * ir_rc5_decode() - Decode one RC-5 pulse or space
126 * @input_dev: the struct input_dev descriptor of the device 128 * @input_dev: the struct input_dev descriptor of the device
127 * @duration: duration of pulse/space in ns 129 * @ev: the struct ir_raw_event descriptor of the pulse/space
128 * 130 *
129 * This function returns -EINVAL if the pulse violates the state machine 131 * This function returns -EINVAL if the pulse violates the state machine
130 */ 132 */
131static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) 133static int ir_rc5_decode(struct input_dev *input_dev, struct ir_raw_event ev)
132{ 134{
133 struct decoder_data *data; 135 struct decoder_data *data;
134 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 136 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
135 u8 toggle; 137 u8 toggle;
136 u32 scancode; 138 u32 scancode;
137 int u;
138 139
139 data = get_decoder_data(ir_dev); 140 data = get_decoder_data(ir_dev);
140 if (!data) 141 if (!data)
@@ -143,76 +144,65 @@ static int ir_rc5_decode(struct input_dev *input_dev, s64 duration)
143 if (!data->enabled) 144 if (!data->enabled)
144 return 0; 145 return 0;
145 146
146 if (IS_RESET(duration)) { 147 if (IS_RESET(ev)) {
147 data->state = STATE_INACTIVE; 148 data->state = STATE_INACTIVE;
148 return 0; 149 return 0;
149 } 150 }
150 151
151 u = TO_UNITS(duration, RC5_UNIT); 152 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
152 if (DURATION(u) == 0)
153 goto out; 153 goto out;
154 154
155again: 155again:
156 IR_dprintk(2, "RC5(x) decode started at state %i (%i units, %ius)\n", 156 IR_dprintk(2, "RC5(x) decode started at state %i (%uus %s)\n",
157 data->state, u, TO_US(duration)); 157 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
158 158
159 if (DURATION(u) == 0 && data->state != STATE_FINISHED) 159 if (!geq_margin(ev.duration, RC5_UNIT, RC5_UNIT / 2))
160 return 0; 160 return 0;
161 161
162 switch (data->state) { 162 switch (data->state) {
163 163
164 case STATE_INACTIVE: 164 case STATE_INACTIVE:
165 if (IS_PULSE(u)) { 165 if (!ev.pulse)
166 data->state = STATE_BIT_START; 166 break;
167 data->count = 1; 167
168 /* We just need enough bits to get to STATE_CHECK_RC5X */ 168 data->state = STATE_BIT_START;
169 data->wanted_bits = RC5X_NBITS; 169 data->count = 1;
170 DECREASE_DURATION(u, 1); 170 /* We just need enough bits to get to STATE_CHECK_RC5X */
171 goto again; 171 data->wanted_bits = RC5X_NBITS;
172 } 172 decrease_duration(&ev, RC5_BIT_START);
173 break; 173 goto again;
174 174
175 case STATE_BIT_START: 175 case STATE_BIT_START:
176 if (DURATION(u) == 1) { 176 if (!eq_margin(ev.duration, RC5_BIT_START, RC5_UNIT / 2))
177 data->rc5_bits <<= 1; 177 break;
178 if (IS_SPACE(u)) 178
179 data->rc5_bits |= 1; 179 data->rc5_bits <<= 1;
180 data->count++; 180 if (!ev.pulse)
181 data->last_unit = u; 181 data->rc5_bits |= 1;
182 182 data->count++;
183 /* 183 data->prev_ev = ev;
184 * If the last bit is zero, a space will merge 184 data->state = STATE_BIT_END;
185 * with the silence after the command. 185 return 0;
186 */
187 if (IS_PULSE(u) && data->count == data->wanted_bits) {
188 data->state = STATE_FINISHED;
189 goto again;
190 }
191
192 data->state = STATE_BIT_END;
193 return 0;
194 }
195 break;
196 186
197 case STATE_BIT_END: 187 case STATE_BIT_END:
198 if (IS_TRANSITION(u, data->last_unit)) { 188 if (!is_transition(&ev, &data->prev_ev))
199 if (data->count == data->wanted_bits) 189 break;
200 data->state = STATE_FINISHED; 190
201 else if (data->count == CHECK_RC5X_NBITS) 191 if (data->count == data->wanted_bits)
202 data->state = STATE_CHECK_RC5X; 192 data->state = STATE_FINISHED;
203 else 193 else if (data->count == CHECK_RC5X_NBITS)
204 data->state = STATE_BIT_START; 194 data->state = STATE_CHECK_RC5X;
205 195 else
206 DECREASE_DURATION(u, 1); 196 data->state = STATE_BIT_START;
207 goto again; 197
208 } 198 decrease_duration(&ev, RC5_BIT_END);
209 break; 199 goto again;
210 200
211 case STATE_CHECK_RC5X: 201 case STATE_CHECK_RC5X:
212 if (IS_SPACE(u) && DURATION(u) >= DURATION(RC5X_SPACE)) { 202 if (!ev.pulse && geq_margin(ev.duration, RC5X_SPACE, RC5_UNIT / 2)) {
213 /* RC5X */ 203 /* RC5X */
214 data->wanted_bits = RC5X_NBITS; 204 data->wanted_bits = RC5X_NBITS;
215 DECREASE_DURATION(u, DURATION(RC5X_SPACE)); 205 decrease_duration(&ev, RC5X_SPACE);
216 } else { 206 } else {
217 /* RC5 */ 207 /* RC5 */
218 data->wanted_bits = RC5_NBITS; 208 data->wanted_bits = RC5_NBITS;
@@ -221,6 +211,9 @@ again:
221 goto again; 211 goto again;
222 212
223 case STATE_FINISHED: 213 case STATE_FINISHED:
214 if (ev.pulse)
215 break;
216
224 if (data->wanted_bits == RC5X_NBITS) { 217 if (data->wanted_bits == RC5X_NBITS) {
225 /* RC5X */ 218 /* RC5X */
226 u8 xdata, command, system; 219 u8 xdata, command, system;
@@ -253,8 +246,8 @@ again:
253 } 246 }
254 247
255out: 248out:
256 IR_dprintk(1, "RC5(x) decode failed at state %i (%i units, %ius)\n", 249 IR_dprintk(1, "RC5(x) decode failed at state %i (%uus %s)\n",
257 data->state, u, TO_US(duration)); 250 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
258 data->state = STATE_INACTIVE; 251 data->state = STATE_INACTIVE;
259 return -EINVAL; 252 return -EINVAL;
260} 253}
diff --git a/drivers/media/IR/ir-rc6-decoder.c b/drivers/media/IR/ir-rc6-decoder.c
index ccc5be240f82..2bf479f4f1bc 100644
--- a/drivers/media/IR/ir-rc6-decoder.c
+++ b/drivers/media/IR/ir-rc6-decoder.c
@@ -26,8 +26,12 @@
26#define RC6_0_NBITS 16 26#define RC6_0_NBITS 16
27#define RC6_6A_SMALL_NBITS 24 27#define RC6_6A_SMALL_NBITS 24
28#define RC6_6A_LARGE_NBITS 32 28#define RC6_6A_LARGE_NBITS 32
29#define RC6_PREFIX_PULSE PULSE(6) 29#define RC6_PREFIX_PULSE (6 * RC6_UNIT)
30#define RC6_PREFIX_SPACE SPACE(2) 30#define RC6_PREFIX_SPACE (2 * RC6_UNIT)
31#define RC6_BIT_START (1 * RC6_UNIT)
32#define RC6_BIT_END (1 * RC6_UNIT)
33#define RC6_TOGGLE_START (2 * RC6_UNIT)
34#define RC6_TOGGLE_END (2 * RC6_UNIT)
31#define RC6_MODE_MASK 0x07 /* for the header bits */ 35#define RC6_MODE_MASK 0x07 /* for the header bits */
32#define RC6_STARTBIT_MASK 0x08 /* for the header bits */ 36#define RC6_STARTBIT_MASK 0x08 /* for the header bits */
33#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */ 37#define RC6_6A_MCE_TOGGLE_MASK 0x8000 /* for the body bits */
@@ -63,7 +67,7 @@ struct decoder_data {
63 enum rc6_state state; 67 enum rc6_state state;
64 u8 header; 68 u8 header;
65 u32 body; 69 u32 body;
66 int last_unit; 70 struct ir_raw_event prev_ev;
67 bool toggle; 71 bool toggle;
68 unsigned count; 72 unsigned count;
69 unsigned wanted_bits; 73 unsigned wanted_bits;
@@ -152,17 +156,16 @@ static enum rc6_mode rc6_mode(struct decoder_data *data) {
152/** 156/**
153 * ir_rc6_decode() - Decode one RC6 pulse or space 157 * ir_rc6_decode() - Decode one RC6 pulse or space
154 * @input_dev: the struct input_dev descriptor of the device 158 * @input_dev: the struct input_dev descriptor of the device
155 * @duration: duration of pulse/space in ns 159 * @ev: the struct ir_raw_event descriptor of the pulse/space
156 * 160 *
157 * This function returns -EINVAL if the pulse violates the state machine 161 * This function returns -EINVAL if the pulse violates the state machine
158 */ 162 */
159static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) 163static int ir_rc6_decode(struct input_dev *input_dev, struct ir_raw_event ev)
160{ 164{
161 struct decoder_data *data; 165 struct decoder_data *data;
162 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 166 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
163 u32 scancode; 167 u32 scancode;
164 u8 toggle; 168 u8 toggle;
165 int u;
166 169
167 data = get_decoder_data(ir_dev); 170 data = get_decoder_data(ir_dev);
168 if (!data) 171 if (!data)
@@ -171,140 +174,144 @@ static int ir_rc6_decode(struct input_dev *input_dev, s64 duration)
171 if (!data->enabled) 174 if (!data->enabled)
172 return 0; 175 return 0;
173 176
174 if (IS_RESET(duration)) { 177 if (IS_RESET(ev)) {
175 data->state = STATE_INACTIVE; 178 data->state = STATE_INACTIVE;
176 return 0; 179 return 0;
177 } 180 }
178 181
179 u = TO_UNITS(duration, RC6_UNIT); 182 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
180 if (DURATION(u) == 0)
181 goto out; 183 goto out;
182 184
183again: 185again:
184 IR_dprintk(2, "RC6 decode started at state %i (%i units, %ius)\n", 186 IR_dprintk(2, "RC6 decode started at state %i (%uus %s)\n",
185 data->state, u, TO_US(duration)); 187 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
186 188
187 if (DURATION(u) == 0 && data->state != STATE_FINISHED) 189 if (!geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
188 return 0; 190 return 0;
189 191
190 switch (data->state) { 192 switch (data->state) {
191 193
192 case STATE_INACTIVE: 194 case STATE_INACTIVE:
193 if (u >= RC6_PREFIX_PULSE - 1 && u <= RC6_PREFIX_PULSE + 1) { 195 if (!ev.pulse)
194 data->state = STATE_PREFIX_SPACE; 196 break;
195 data->count = 0; 197
196 return 0; 198 /* Note: larger margin on first pulse since each RC6_UNIT
197 } 199 is quite short and some hardware takes some time to
198 break; 200 adjust to the signal */
201 if (!eq_margin(ev.duration, RC6_PREFIX_PULSE, RC6_UNIT))
202 break;
203
204 data->state = STATE_PREFIX_SPACE;
205 data->count = 0;
206 return 0;
199 207
200 case STATE_PREFIX_SPACE: 208 case STATE_PREFIX_SPACE:
201 if (u == RC6_PREFIX_SPACE) { 209 if (ev.pulse)
202 data->state = STATE_HEADER_BIT_START; 210 break;
203 return 0; 211
204 } 212 if (!eq_margin(ev.duration, RC6_PREFIX_SPACE, RC6_UNIT / 2))
205 break; 213 break;
214
215 data->state = STATE_HEADER_BIT_START;
216 return 0;
206 217
207 case STATE_HEADER_BIT_START: 218 case STATE_HEADER_BIT_START:
208 if (DURATION(u) == 1) { 219 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
209 data->header <<= 1; 220 break;
210 if (IS_PULSE(u)) 221
211 data->header |= 1; 222 data->header <<= 1;
212 data->count++; 223 if (ev.pulse)
213 data->last_unit = u; 224 data->header |= 1;
214 data->state = STATE_HEADER_BIT_END; 225 data->count++;
215 return 0; 226 data->prev_ev = ev;
216 } 227 data->state = STATE_HEADER_BIT_END;
217 break; 228 return 0;
218 229
219 case STATE_HEADER_BIT_END: 230 case STATE_HEADER_BIT_END:
220 if (IS_TRANSITION(u, data->last_unit)) { 231 if (!is_transition(&ev, &data->prev_ev))
221 if (data->count == RC6_HEADER_NBITS) 232 break;
222 data->state = STATE_TOGGLE_START;
223 else
224 data->state = STATE_HEADER_BIT_START;
225 233
226 DECREASE_DURATION(u, 1); 234 if (data->count == RC6_HEADER_NBITS)
227 goto again; 235 data->state = STATE_TOGGLE_START;
228 } 236 else
229 break; 237 data->state = STATE_HEADER_BIT_START;
238
239 decrease_duration(&ev, RC6_BIT_END);
240 goto again;
230 241
231 case STATE_TOGGLE_START: 242 case STATE_TOGGLE_START:
232 if (DURATION(u) == 2) { 243 if (!eq_margin(ev.duration, RC6_TOGGLE_START, RC6_UNIT / 2))
233 data->toggle = IS_PULSE(u); 244 break;
234 data->last_unit = u; 245
235 data->state = STATE_TOGGLE_END; 246 data->toggle = ev.pulse;
236 return 0; 247 data->prev_ev = ev;
237 } 248 data->state = STATE_TOGGLE_END;
238 break; 249 return 0;
239 250
240 case STATE_TOGGLE_END: 251 case STATE_TOGGLE_END:
241 if (IS_TRANSITION(u, data->last_unit) && DURATION(u) >= 2) { 252 if (!is_transition(&ev, &data->prev_ev) ||
242 data->state = STATE_BODY_BIT_START; 253 !geq_margin(ev.duration, RC6_TOGGLE_END, RC6_UNIT / 2))
243 data->last_unit = u; 254 break;
244 DECREASE_DURATION(u, 2);
245 data->count = 0;
246 255
247 if (!(data->header & RC6_STARTBIT_MASK)) { 256 if (!(data->header & RC6_STARTBIT_MASK)) {
248 IR_dprintk(1, "RC6 invalid start bit\n"); 257 IR_dprintk(1, "RC6 invalid start bit\n");
249 break; 258 break;
250 } 259 }
251 260
252 switch (rc6_mode(data)) { 261 data->state = STATE_BODY_BIT_START;
253 case RC6_MODE_0: 262 data->prev_ev = ev;
254 data->wanted_bits = RC6_0_NBITS; 263 decrease_duration(&ev, RC6_TOGGLE_END);
255 break; 264 data->count = 0;
256 case RC6_MODE_6A: 265
257 /* This might look weird, but we basically 266 switch (rc6_mode(data)) {
258 check the value of the first body bit to 267 case RC6_MODE_0:
259 determine the number of bits in mode 6A */ 268 data->wanted_bits = RC6_0_NBITS;
260 if ((DURATION(u) == 0 && IS_SPACE(data->last_unit)) || DURATION(u) > 0) 269 break;
261 data->wanted_bits = RC6_6A_LARGE_NBITS; 270 case RC6_MODE_6A:
262 else 271 /* This might look weird, but we basically
263 data->wanted_bits = RC6_6A_SMALL_NBITS; 272 check the value of the first body bit to
264 break; 273 determine the number of bits in mode 6A */
265 default: 274 if ((!ev.pulse && !geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2)) ||
266 IR_dprintk(1, "RC6 unknown mode\n"); 275 geq_margin(ev.duration, RC6_UNIT, RC6_UNIT / 2))
267 goto out; 276 data->wanted_bits = RC6_6A_LARGE_NBITS;
268 } 277 else
269 goto again; 278 data->wanted_bits = RC6_6A_SMALL_NBITS;
279 break;
280 default:
281 IR_dprintk(1, "RC6 unknown mode\n");
282 goto out;
270 } 283 }
271 break; 284 goto again;
272 285
273 case STATE_BODY_BIT_START: 286 case STATE_BODY_BIT_START:
274 if (DURATION(u) == 1) { 287 if (!eq_margin(ev.duration, RC6_BIT_START, RC6_UNIT / 2))
275 data->body <<= 1; 288 break;
276 if (IS_PULSE(u))
277 data->body |= 1;
278 data->count++;
279 data->last_unit = u;
280
281 /*
282 * If the last bit is one, a space will merge
283 * with the silence after the command.
284 */
285 if (IS_PULSE(u) && data->count == data->wanted_bits) {
286 data->state = STATE_FINISHED;
287 goto again;
288 }
289 289
290 data->state = STATE_BODY_BIT_END; 290 data->body <<= 1;
291 return 0; 291 if (ev.pulse)
292 } 292 data->body |= 1;
293 break; 293 data->count++;
294 data->prev_ev = ev;
295
296 data->state = STATE_BODY_BIT_END;
297 return 0;
294 298
295 case STATE_BODY_BIT_END: 299 case STATE_BODY_BIT_END:
296 if (IS_TRANSITION(u, data->last_unit)) { 300 if (!is_transition(&ev, &data->prev_ev))
297 if (data->count == data->wanted_bits) 301 break;
298 data->state = STATE_FINISHED;
299 else
300 data->state = STATE_BODY_BIT_START;
301 302
302 DECREASE_DURATION(u, 1); 303 if (data->count == data->wanted_bits)
303 goto again; 304 data->state = STATE_FINISHED;
304 } 305 else
305 break; 306 data->state = STATE_BODY_BIT_START;
307
308 decrease_duration(&ev, RC6_BIT_END);
309 goto again;
306 310
307 case STATE_FINISHED: 311 case STATE_FINISHED:
312 if (ev.pulse)
313 break;
314
308 switch (rc6_mode(data)) { 315 switch (rc6_mode(data)) {
309 case RC6_MODE_0: 316 case RC6_MODE_0:
310 scancode = data->body & 0xffff; 317 scancode = data->body & 0xffff;
@@ -335,8 +342,8 @@ again:
335 } 342 }
336 343
337out: 344out:
338 IR_dprintk(1, "RC6 decode failed at state %i (%i units, %ius)\n", 345 IR_dprintk(1, "RC6 decode failed at state %i (%uus %s)\n",
339 data->state, u, TO_US(duration)); 346 data->state, TO_US(ev.duration), TO_STR(ev.pulse));
340 data->state = STATE_INACTIVE; 347 data->state = STATE_INACTIVE;
341 return -EINVAL; 348 return -EINVAL;
342} 349}