diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/IR/ir-core-priv.h | 49 | ||||
-rw-r--r-- | drivers/media/IR/ir-nec-decoder.c | 120 | ||||
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 30 | ||||
-rw-r--r-- | drivers/media/IR/ir-rc5-decoder.c | 105 | ||||
-rw-r--r-- | drivers/media/IR/ir-rc6-decoder.c | 221 |
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 @@ | |||
22 | struct ir_raw_handler { | 22 | struct 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)) | 39 | static 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) | 43 | static 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 { \ | 47 | static 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); \ | 51 | static 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 | */ |
71 | int ir_raw_event_register(struct input_dev *input_dev); | 73 | int ir_raw_event_register(struct input_dev *input_dev); |
72 | void ir_raw_event_unregister(struct input_dev *input_dev); | 74 | void ir_raw_event_unregister(struct input_dev *input_dev); |
73 | static 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 | } | ||
78 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); | 75 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); |
79 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); | 76 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); |
80 | void ir_raw_init(void); | 77 | void 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 */ |
29 | static LIST_HEAD(decoder_list); | 31 | static 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 | */ |
126 | static int ir_nec_decode(struct input_dev *input_dev, s64 duration) | 128 | static 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 | ||
238 | out: | 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 | ||
58 | static void ir_raw_event_work(struct work_struct *work) | 58 | static 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 | ||
68 | int ir_raw_event_register(struct input_dev *input_dev) | 68 | int 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 | */ |
124 | int ir_raw_event_store(struct input_dev *input_dev, s64 duration) | 124 | int 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 */ |
32 | static LIST_HEAD(decoder_list); | 34 | static 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 | */ |
131 | static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) | 133 | static 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 | ||
155 | again: | 155 | again: |
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 | ||
255 | out: | 248 | out: |
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 | */ |
159 | static int ir_rc6_decode(struct input_dev *input_dev, s64 duration) | 163 | static 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 | ||
183 | again: | 185 | again: |
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 | ||
337 | out: | 344 | out: |
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 | } |