diff options
-rw-r--r-- | drivers/media/IR/ir-nec-decoder.c | 247 | ||||
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 143 | ||||
-rw-r--r-- | drivers/media/IR/ir-rc5-decoder.c | 150 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 2 | ||||
-rw-r--r-- | include/media/ir-core.h | 47 |
5 files changed, 296 insertions, 293 deletions
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index 18918e52c0c0..02682e617fae 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c | |||
@@ -13,15 +13,16 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include <media/ir-core.h> | 15 | #include <media/ir-core.h> |
16 | #include <linux/bitrev.h> | ||
16 | 17 | ||
17 | #define NEC_NBITS 32 | 18 | #define NEC_NBITS 32 |
18 | #define NEC_UNIT 559979 /* ns */ | 19 | #define NEC_UNIT 562500 /* ns */ |
19 | #define NEC_HEADER_MARK (16 * NEC_UNIT) | 20 | #define NEC_HEADER_PULSE PULSE(16) |
20 | #define NEC_HEADER_SPACE (8 * NEC_UNIT) | 21 | #define NEC_HEADER_SPACE SPACE(8) |
21 | #define NEC_REPEAT_SPACE (4 * NEC_UNIT) | 22 | #define NEC_REPEAT_SPACE SPACE(4) |
22 | #define NEC_MARK (NEC_UNIT) | 23 | #define NEC_BIT_PULSE PULSE(1) |
23 | #define NEC_0_SPACE (NEC_UNIT) | 24 | #define NEC_BIT_0_SPACE SPACE(1) |
24 | #define NEC_1_SPACE (3 * NEC_UNIT) | 25 | #define NEC_BIT_1_SPACE SPACE(3) |
25 | 26 | ||
26 | /* Used to register nec_decoder clients */ | 27 | /* Used to register nec_decoder clients */ |
27 | static LIST_HEAD(decoder_list); | 28 | static LIST_HEAD(decoder_list); |
@@ -29,21 +30,13 @@ static DEFINE_SPINLOCK(decoder_lock); | |||
29 | 30 | ||
30 | enum nec_state { | 31 | enum nec_state { |
31 | STATE_INACTIVE, | 32 | STATE_INACTIVE, |
32 | STATE_HEADER_MARK, | ||
33 | STATE_HEADER_SPACE, | 33 | STATE_HEADER_SPACE, |
34 | STATE_MARK, | 34 | STATE_BIT_PULSE, |
35 | STATE_SPACE, | 35 | STATE_BIT_SPACE, |
36 | STATE_TRAILER_MARK, | 36 | STATE_TRAILER_PULSE, |
37 | STATE_TRAILER_SPACE, | 37 | STATE_TRAILER_SPACE, |
38 | }; | 38 | }; |
39 | 39 | ||
40 | struct nec_code { | ||
41 | u8 address; | ||
42 | u8 not_address; | ||
43 | u8 command; | ||
44 | u8 not_command; | ||
45 | }; | ||
46 | |||
47 | struct decoder_data { | 40 | struct decoder_data { |
48 | struct list_head list; | 41 | struct list_head list; |
49 | struct ir_input_dev *ir_dev; | 42 | struct ir_input_dev *ir_dev; |
@@ -51,7 +44,7 @@ struct decoder_data { | |||
51 | 44 | ||
52 | /* State machine control */ | 45 | /* State machine control */ |
53 | enum nec_state state; | 46 | enum nec_state state; |
54 | struct nec_code nec_code; | 47 | u32 nec_bits; |
55 | unsigned count; | 48 | unsigned count; |
56 | }; | 49 | }; |
57 | 50 | ||
@@ -62,7 +55,6 @@ struct decoder_data { | |||
62 | * | 55 | * |
63 | * Returns the struct decoder_data that corresponds to a device | 56 | * Returns the struct decoder_data that corresponds to a device |
64 | */ | 57 | */ |
65 | |||
66 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | 58 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) |
67 | { | 59 | { |
68 | struct decoder_data *data = NULL; | 60 | struct decoder_data *data = NULL; |
@@ -123,20 +115,20 @@ static struct attribute_group decoder_attribute_group = { | |||
123 | .attrs = decoder_attributes, | 115 | .attrs = decoder_attributes, |
124 | }; | 116 | }; |
125 | 117 | ||
126 | |||
127 | /** | 118 | /** |
128 | * ir_nec_decode() - Decode one NEC pulse or space | 119 | * ir_nec_decode() - Decode one NEC pulse or space |
129 | * @input_dev: the struct input_dev descriptor of the device | 120 | * @input_dev: the struct input_dev descriptor of the device |
130 | * @ev: event array with type/duration of pulse/space | 121 | * @duration: duration in ns of pulse/space |
131 | * | 122 | * |
132 | * This function returns -EINVAL if the pulse violates the state machine | 123 | * This function returns -EINVAL if the pulse violates the state machine |
133 | */ | 124 | */ |
134 | static int ir_nec_decode(struct input_dev *input_dev, | 125 | static int ir_nec_decode(struct input_dev *input_dev, s64 duration) |
135 | struct ir_raw_event *ev) | ||
136 | { | 126 | { |
137 | struct decoder_data *data; | 127 | struct decoder_data *data; |
138 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 128 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
139 | int bit, last_bit; | 129 | int u; |
130 | u32 scancode; | ||
131 | u8 address, not_address, command, not_command; | ||
140 | 132 | ||
141 | data = get_decoder_data(ir_dev); | 133 | data = get_decoder_data(ir_dev); |
142 | if (!data) | 134 | if (!data) |
@@ -145,150 +137,107 @@ static int ir_nec_decode(struct input_dev *input_dev, | |||
145 | if (!data->enabled) | 137 | if (!data->enabled) |
146 | return 0; | 138 | return 0; |
147 | 139 | ||
148 | /* Except for the initial event, what matters is the previous bit */ | 140 | if (IS_RESET(duration)) { |
149 | bit = (ev->type & IR_PULSE) ? 1 : 0; | ||
150 | |||
151 | last_bit = !bit; | ||
152 | |||
153 | /* Discards spurious space last_bits when inactive */ | ||
154 | |||
155 | /* Very long delays are considered as start events */ | ||
156 | if (ev->delta.tv_nsec > NEC_HEADER_MARK + NEC_HEADER_SPACE - NEC_UNIT / 2) | ||
157 | data->state = STATE_INACTIVE; | 141 | data->state = STATE_INACTIVE; |
142 | return 0; | ||
143 | } | ||
158 | 144 | ||
159 | if (ev->type & IR_START_EVENT) | 145 | u = TO_UNITS(duration, NEC_UNIT); |
160 | data->state = STATE_INACTIVE; | 146 | if (DURATION(u) == 0) |
147 | goto out; | ||
148 | |||
149 | IR_dprintk(2, "NEC decode started at state %d (%i units, %ius)\n", | ||
150 | data->state, u, TO_US(duration)); | ||
161 | 151 | ||
162 | switch (data->state) { | 152 | switch (data->state) { |
163 | case STATE_INACTIVE: | ||
164 | if (!bit) /* PULSE marks the start event */ | ||
165 | return 0; | ||
166 | 153 | ||
167 | data->count = 0; | 154 | case STATE_INACTIVE: |
168 | data->state = STATE_HEADER_MARK; | 155 | if (u == NEC_HEADER_PULSE) { |
169 | memset (&data->nec_code, 0, sizeof(data->nec_code)); | 156 | data->count = 0; |
170 | return 0; | 157 | data->state = STATE_HEADER_SPACE; |
171 | case STATE_HEADER_MARK: | 158 | } |
172 | if (!last_bit) | ||
173 | goto err; | ||
174 | if (ev->delta.tv_nsec < NEC_HEADER_MARK - 6 * NEC_UNIT) | ||
175 | goto err; | ||
176 | data->state = STATE_HEADER_SPACE; | ||
177 | return 0; | 159 | return 0; |
160 | |||
178 | case STATE_HEADER_SPACE: | 161 | case STATE_HEADER_SPACE: |
179 | if (last_bit) | 162 | if (u == NEC_HEADER_SPACE) { |
180 | goto err; | 163 | data->state = STATE_BIT_PULSE; |
181 | if (ev->delta.tv_nsec >= NEC_HEADER_SPACE - NEC_UNIT / 2) { | ||
182 | data->state = STATE_MARK; | ||
183 | return 0; | 164 | return 0; |
184 | } | 165 | } else if (u == NEC_REPEAT_SPACE) { |
185 | |||
186 | if (ev->delta.tv_nsec >= NEC_REPEAT_SPACE - NEC_UNIT / 2) { | ||
187 | ir_repeat(input_dev); | 166 | ir_repeat(input_dev); |
188 | IR_dprintk(1, "Repeat last key\n"); | 167 | IR_dprintk(1, "Repeat last key\n"); |
189 | data->state = STATE_TRAILER_MARK; | 168 | data->state = STATE_TRAILER_PULSE; |
190 | return 0; | 169 | return 0; |
191 | } | 170 | } |
192 | goto err; | 171 | break; |
193 | case STATE_MARK: | 172 | |
194 | if (!last_bit) | 173 | case STATE_BIT_PULSE: |
195 | goto err; | 174 | if (u == NEC_BIT_PULSE) { |
196 | if ((ev->delta.tv_nsec > NEC_MARK + NEC_UNIT / 2) || | 175 | data->state = STATE_BIT_SPACE; |
197 | (ev->delta.tv_nsec < NEC_MARK - NEC_UNIT / 2)) | 176 | return 0; |
198 | goto err; | 177 | } |
199 | data->state = STATE_SPACE; | 178 | break; |
200 | return 0; | 179 | |
201 | case STATE_SPACE: | 180 | case STATE_BIT_SPACE: |
202 | if (last_bit) | 181 | if (u != NEC_BIT_0_SPACE && u != NEC_BIT_1_SPACE) |
203 | goto err; | 182 | break; |
204 | 183 | ||
205 | if ((ev->delta.tv_nsec >= NEC_0_SPACE - NEC_UNIT / 2) && | 184 | data->nec_bits <<= 1; |
206 | (ev->delta.tv_nsec < NEC_0_SPACE + NEC_UNIT / 2)) | 185 | if (u == NEC_BIT_1_SPACE) |
207 | bit = 0; | 186 | data->nec_bits |= 1; |
208 | else if ((ev->delta.tv_nsec >= NEC_1_SPACE - NEC_UNIT / 2) && | 187 | data->count++; |
209 | (ev->delta.tv_nsec < NEC_1_SPACE + NEC_UNIT / 2)) | 188 | |
210 | bit = 1; | 189 | if (data->count != NEC_NBITS) { |
211 | else { | 190 | data->state = STATE_BIT_PULSE; |
212 | IR_dprintk(1, "Decode failed at %d-th bit (%s) @%luus\n", | 191 | return 0; |
213 | data->count, | 192 | } |
214 | last_bit ? "pulse" : "space", | 193 | |
215 | (ev->delta.tv_nsec + 500) / 1000); | 194 | address = bitrev8((data->nec_bits >> 24) & 0xff); |
216 | 195 | not_address = bitrev8((data->nec_bits >> 16) & 0xff); | |
217 | goto err2; | 196 | command = bitrev8((data->nec_bits >> 8) & 0xff); |
197 | not_command = bitrev8((data->nec_bits >> 0) & 0xff); | ||
198 | |||
199 | if ((command ^ not_command) != 0xff) { | ||
200 | IR_dprintk(1, "NEC checksum error: received 0x%08x\n", | ||
201 | data->nec_bits); | ||
202 | break; | ||
218 | } | 203 | } |
219 | 204 | ||
220 | /* Ok, we've got a valid bit. proccess it */ | 205 | if ((address ^ not_address) != 0xff) { |
221 | if (bit) { | 206 | /* Extended NEC */ |
222 | int shift = data->count; | 207 | scancode = address << 16 | |
223 | 208 | not_address << 8 | | |
224 | /* | 209 | command; |
225 | * NEC transmit bytes on this temporal order: | 210 | IR_dprintk(1, "NEC (Ext) scancode 0x%06x\n", scancode); |
226 | * address | not address | command | not command | 211 | } else { |
227 | */ | 212 | /* normal NEC */ |
228 | if (shift < 8) { | 213 | scancode = address << 8 | command; |
229 | data->nec_code.address |= 1 << shift; | 214 | IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); |
230 | } else if (shift < 16) { | ||
231 | data->nec_code.not_address |= 1 << (shift - 8); | ||
232 | } else if (shift < 24) { | ||
233 | data->nec_code.command |= 1 << (shift - 16); | ||
234 | } else { | ||
235 | data->nec_code.not_command |= 1 << (shift - 24); | ||
236 | } | ||
237 | } | 215 | } |
238 | if (++data->count == NEC_NBITS) { | 216 | |
239 | u32 scancode; | 217 | ir_keydown(input_dev, scancode, 0); |
240 | /* | 218 | data->state = STATE_TRAILER_PULSE; |
241 | * Fixme: may need to accept Extended NEC protocol? | ||
242 | */ | ||
243 | if ((data->nec_code.command ^ data->nec_code.not_command) != 0xff) | ||
244 | goto checksum_err; | ||
245 | |||
246 | if ((data->nec_code.address ^ data->nec_code.not_address) != 0xff) { | ||
247 | /* Extended NEC */ | ||
248 | scancode = data->nec_code.address << 16 | | ||
249 | data->nec_code.not_address << 8 | | ||
250 | data->nec_code.command; | ||
251 | IR_dprintk(1, "NEC scancode 0x%06x\n", scancode); | ||
252 | } else { | ||
253 | /* normal NEC */ | ||
254 | scancode = data->nec_code.address << 8 | | ||
255 | data->nec_code.command; | ||
256 | IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); | ||
257 | } | ||
258 | ir_keydown(input_dev, scancode, 0); | ||
259 | |||
260 | data->state = STATE_TRAILER_MARK; | ||
261 | } else | ||
262 | data->state = STATE_MARK; | ||
263 | return 0; | ||
264 | case STATE_TRAILER_MARK: | ||
265 | if (!last_bit) | ||
266 | goto err; | ||
267 | data->state = STATE_TRAILER_SPACE; | ||
268 | return 0; | 219 | return 0; |
220 | |||
221 | case STATE_TRAILER_PULSE: | ||
222 | if (u > 0) { | ||
223 | data->state = STATE_TRAILER_SPACE; | ||
224 | return 0; | ||
225 | } | ||
226 | break; | ||
227 | |||
269 | case STATE_TRAILER_SPACE: | 228 | case STATE_TRAILER_SPACE: |
270 | if (last_bit) | 229 | if (u < 0) { |
271 | goto err; | 230 | data->state = STATE_INACTIVE; |
272 | data->state = STATE_INACTIVE; | 231 | return 0; |
273 | return 0; | 232 | } |
274 | } | ||
275 | 233 | ||
276 | err: | 234 | break; |
277 | IR_dprintk(1, "NEC decoded failed at state %d (%s) @ %luus\n", | 235 | } |
278 | data->state, | ||
279 | bit ? "pulse" : "space", | ||
280 | (ev->delta.tv_nsec + 500) / 1000); | ||
281 | err2: | ||
282 | data->state = STATE_INACTIVE; | ||
283 | return -EINVAL; | ||
284 | 236 | ||
285 | checksum_err: | 237 | out: |
238 | IR_dprintk(1, "NEC decode failed at state %d (%i units, %ius)\n", | ||
239 | data->state, u, TO_US(duration)); | ||
286 | data->state = STATE_INACTIVE; | 240 | data->state = STATE_INACTIVE; |
287 | IR_dprintk(1, "NEC checksum error: received 0x%02x%02x%02x%02x\n", | ||
288 | data->nec_code.address, | ||
289 | data->nec_code.not_address, | ||
290 | data->nec_code.command, | ||
291 | data->nec_code.not_command); | ||
292 | return -EINVAL; | 241 | return -EINVAL; |
293 | } | 242 | } |
294 | 243 | ||
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index bc4ca08adf4a..e144f1522962 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c | |||
@@ -15,9 +15,10 @@ | |||
15 | #include <media/ir-core.h> | 15 | #include <media/ir-core.h> |
16 | #include <linux/workqueue.h> | 16 | #include <linux/workqueue.h> |
17 | #include <linux/spinlock.h> | 17 | #include <linux/spinlock.h> |
18 | #include <linux/sched.h> | ||
18 | 19 | ||
19 | /* Define the max number of bit transitions per IR keycode */ | 20 | /* Define the max number of pulse/space transitions to buffer */ |
20 | #define MAX_IR_EVENT_SIZE 256 | 21 | #define MAX_IR_EVENT_SIZE 512 |
21 | 22 | ||
22 | /* Used to handle IR raw handler extensions */ | 23 | /* Used to handle IR raw handler extensions */ |
23 | static LIST_HEAD(ir_raw_handler_list); | 24 | static LIST_HEAD(ir_raw_handler_list); |
@@ -53,19 +54,30 @@ static DEFINE_SPINLOCK(ir_raw_handler_lock); | |||
53 | /* Used to load the decoders */ | 54 | /* Used to load the decoders */ |
54 | static struct work_struct wq_load; | 55 | static struct work_struct wq_load; |
55 | 56 | ||
57 | static void ir_raw_event_work(struct work_struct *work) | ||
58 | { | ||
59 | s64 d; | ||
60 | struct ir_raw_event_ctrl *raw = | ||
61 | container_of(work, struct ir_raw_event_ctrl, rx_work); | ||
62 | |||
63 | while (kfifo_out(&raw->kfifo, &d, sizeof(d)) == sizeof(d)) | ||
64 | RUN_DECODER(decode, raw->input_dev, d); | ||
65 | } | ||
66 | |||
56 | int ir_raw_event_register(struct input_dev *input_dev) | 67 | int ir_raw_event_register(struct input_dev *input_dev) |
57 | { | 68 | { |
58 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 69 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
59 | int rc, size; | 70 | int rc; |
60 | 71 | ||
61 | ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); | 72 | ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); |
62 | if (!ir->raw) | 73 | if (!ir->raw) |
63 | return -ENOMEM; | 74 | return -ENOMEM; |
64 | 75 | ||
65 | size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2; | 76 | ir->raw->input_dev = input_dev; |
66 | size = roundup_pow_of_two(size); | 77 | INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); |
67 | 78 | ||
68 | rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL); | 79 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, |
80 | GFP_KERNEL); | ||
69 | if (rc < 0) { | 81 | if (rc < 0) { |
70 | kfree(ir->raw); | 82 | kfree(ir->raw); |
71 | ir->raw = NULL; | 83 | ir->raw = NULL; |
@@ -90,6 +102,7 @@ void ir_raw_event_unregister(struct input_dev *input_dev) | |||
90 | if (!ir->raw) | 102 | if (!ir->raw) |
91 | return; | 103 | return; |
92 | 104 | ||
105 | cancel_work_sync(&ir->raw->rx_work); | ||
93 | RUN_DECODER(raw_unregister, input_dev); | 106 | RUN_DECODER(raw_unregister, input_dev); |
94 | 107 | ||
95 | kfifo_free(&ir->raw->kfifo); | 108 | kfifo_free(&ir->raw->kfifo); |
@@ -97,74 +110,90 @@ void ir_raw_event_unregister(struct input_dev *input_dev) | |||
97 | ir->raw = NULL; | 110 | ir->raw = NULL; |
98 | } | 111 | } |
99 | 112 | ||
100 | int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type) | 113 | /** |
114 | * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders | ||
115 | * @input_dev: the struct input_dev device descriptor | ||
116 | * @duration: duration of the pulse or space in ns | ||
117 | * | ||
118 | * This routine (which may be called from an interrupt context) stores a | ||
119 | * pulse/space duration for the raw ir decoding state machines. Pulses are | ||
120 | * signalled as positive values and spaces as negative values. A zero value | ||
121 | * will reset the decoding state machines. | ||
122 | */ | ||
123 | int ir_raw_event_store(struct input_dev *input_dev, s64 duration) | ||
101 | { | 124 | { |
102 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 125 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
103 | struct timespec ts; | ||
104 | struct ir_raw_event event; | ||
105 | int rc; | ||
106 | 126 | ||
107 | if (!ir->raw) | 127 | if (!ir->raw) |
108 | return -EINVAL; | 128 | return -EINVAL; |
109 | 129 | ||
110 | event.type = type; | 130 | if (kfifo_in(&ir->raw->kfifo, &duration, sizeof(duration)) != sizeof(duration)) |
111 | event.delta.tv_sec = 0; | 131 | return -ENOMEM; |
112 | event.delta.tv_nsec = 0; | ||
113 | 132 | ||
114 | ktime_get_ts(&ts); | 133 | return 0; |
134 | } | ||
135 | EXPORT_SYMBOL_GPL(ir_raw_event_store); | ||
115 | 136 | ||
116 | if (timespec_equal(&ir->raw->last_event, &event.delta)) | 137 | /** |
117 | event.type |= IR_START_EVENT; | 138 | * ir_raw_event_store_edge() - notify raw ir decoders of the start of a pulse/space |
118 | else | 139 | * @input_dev: the struct input_dev device descriptor |
119 | event.delta = timespec_sub(ts, ir->raw->last_event); | 140 | * @type: the type of the event that has occurred |
141 | * | ||
142 | * This routine (which may be called from an interrupt context) is used to | ||
143 | * store the beginning of an ir pulse or space (or the start/end of ir | ||
144 | * reception) for the raw ir decoding state machines. This is used by | ||
145 | * hardware which does not provide durations directly but only interrupts | ||
146 | * (or similar events) on state change. | ||
147 | */ | ||
148 | int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type) | ||
149 | { | ||
150 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
151 | ktime_t now; | ||
152 | s64 delta; /* ns */ | ||
153 | int rc = 0; | ||
120 | 154 | ||
121 | memcpy(&ir->raw->last_event, &ts, sizeof(ts)); | 155 | if (!ir->raw) |
156 | return -EINVAL; | ||
122 | 157 | ||
123 | if (event.delta.tv_sec) { | 158 | now = ktime_get(); |
124 | event.type |= IR_START_EVENT; | 159 | delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); |
125 | event.delta.tv_sec = 0; | ||
126 | event.delta.tv_nsec = 0; | ||
127 | } | ||
128 | 160 | ||
129 | kfifo_in(&ir->raw->kfifo, &event, sizeof(event)); | 161 | /* Check for a long duration since last event or if we're |
162 | * being called for the first time, note that delta can't | ||
163 | * possibly be negative. | ||
164 | */ | ||
165 | if (delta > NSEC_PER_SEC || !ir->raw->last_type) | ||
166 | type |= IR_START_EVENT; | ||
167 | |||
168 | if (type & IR_START_EVENT) | ||
169 | ir_raw_event_reset(input_dev); | ||
170 | else if (ir->raw->last_type & IR_SPACE) | ||
171 | rc = ir_raw_event_store(input_dev, -delta); | ||
172 | else if (ir->raw->last_type & IR_PULSE) | ||
173 | rc = ir_raw_event_store(input_dev, delta); | ||
174 | else | ||
175 | return 0; | ||
130 | 176 | ||
177 | ir->raw->last_event = now; | ||
178 | ir->raw->last_type = type; | ||
131 | return rc; | 179 | return rc; |
132 | } | 180 | } |
133 | EXPORT_SYMBOL_GPL(ir_raw_event_store); | 181 | EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); |
134 | 182 | ||
135 | int ir_raw_event_handle(struct input_dev *input_dev) | 183 | /** |
184 | * ir_raw_event_handle() - schedules the decoding of stored ir data | ||
185 | * @input_dev: the struct input_dev device descriptor | ||
186 | * | ||
187 | * This routine will signal the workqueue to start decoding stored ir data. | ||
188 | */ | ||
189 | void ir_raw_event_handle(struct input_dev *input_dev) | ||
136 | { | 190 | { |
137 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 191 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
138 | int rc; | ||
139 | struct ir_raw_event ev; | ||
140 | int len, i; | ||
141 | |||
142 | /* | ||
143 | * Store the events into a temporary buffer. This allows calling more than | ||
144 | * one decoder to deal with the received data | ||
145 | */ | ||
146 | len = kfifo_len(&ir->raw->kfifo) / sizeof(ev); | ||
147 | if (!len) | ||
148 | return 0; | ||
149 | |||
150 | for (i = 0; i < len; i++) { | ||
151 | rc = kfifo_out(&ir->raw->kfifo, &ev, sizeof(ev)); | ||
152 | if (rc != sizeof(ev)) { | ||
153 | IR_dprintk(1, "overflow error: received %d instead of %zd\n", | ||
154 | rc, sizeof(ev)); | ||
155 | return -EINVAL; | ||
156 | } | ||
157 | IR_dprintk(2, "event type %d, time before event: %07luus\n", | ||
158 | ev.type, (ev.delta.tv_nsec + 500) / 1000); | ||
159 | rc = RUN_DECODER(decode, input_dev, &ev); | ||
160 | } | ||
161 | 192 | ||
162 | /* | 193 | if (!ir->raw) |
163 | * Call all ir decoders. This allows decoding the same event with | 194 | return; |
164 | * more than one protocol handler. | ||
165 | */ | ||
166 | 195 | ||
167 | return rc; | 196 | schedule_work(&ir->raw->rx_work); |
168 | } | 197 | } |
169 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 198 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
170 | 199 | ||
diff --git a/drivers/media/IR/ir-rc5-decoder.c b/drivers/media/IR/ir-rc5-decoder.c index 6323066438b5..1d0857b69089 100644 --- a/drivers/media/IR/ir-rc5-decoder.c +++ b/drivers/media/IR/ir-rc5-decoder.c | |||
@@ -21,11 +21,8 @@ | |||
21 | 21 | ||
22 | #include <media/ir-core.h> | 22 | #include <media/ir-core.h> |
23 | 23 | ||
24 | static unsigned int ir_rc5_remote_gap = 888888; | ||
25 | |||
26 | #define RC5_NBITS 14 | 24 | #define RC5_NBITS 14 |
27 | #define RC5_BIT (ir_rc5_remote_gap * 2) | 25 | #define RC5_UNIT 888888 /* ns */ |
28 | #define RC5_DURATION (ir_rc5_remote_gap * RC5_NBITS) | ||
29 | 26 | ||
30 | /* Used to register rc5_decoder clients */ | 27 | /* Used to register rc5_decoder clients */ |
31 | static LIST_HEAD(decoder_list); | 28 | static LIST_HEAD(decoder_list); |
@@ -33,13 +30,9 @@ static DEFINE_SPINLOCK(decoder_lock); | |||
33 | 30 | ||
34 | enum rc5_state { | 31 | enum rc5_state { |
35 | STATE_INACTIVE, | 32 | STATE_INACTIVE, |
36 | STATE_MARKSPACE, | 33 | STATE_BIT_START, |
37 | STATE_TRAILER, | 34 | STATE_BIT_END, |
38 | }; | 35 | STATE_FINISHED, |
39 | |||
40 | struct rc5_code { | ||
41 | u8 address; | ||
42 | u8 command; | ||
43 | }; | 36 | }; |
44 | 37 | ||
45 | struct decoder_data { | 38 | struct decoder_data { |
@@ -49,8 +42,9 @@ struct decoder_data { | |||
49 | 42 | ||
50 | /* State machine control */ | 43 | /* State machine control */ |
51 | enum rc5_state state; | 44 | enum rc5_state state; |
52 | struct rc5_code rc5_code; | 45 | u32 rc5_bits; |
53 | unsigned code, elapsed, last_bit, last_code; | 46 | int last_unit; |
47 | unsigned count; | ||
54 | }; | 48 | }; |
55 | 49 | ||
56 | 50 | ||
@@ -122,18 +116,19 @@ static struct attribute_group decoder_attribute_group = { | |||
122 | }; | 116 | }; |
123 | 117 | ||
124 | /** | 118 | /** |
125 | * handle_event() - Decode one RC-5 pulse or space | 119 | * ir_rc5_decode() - Decode one RC-5 pulse or space |
126 | * @input_dev: the struct input_dev descriptor of the device | 120 | * @input_dev: the struct input_dev descriptor of the device |
127 | * @ev: event array with type/duration of pulse/space | 121 | * @duration: duration of pulse/space in ns |
128 | * | 122 | * |
129 | * This function returns -EINVAL if the pulse violates the state machine | 123 | * This function returns -EINVAL if the pulse violates the state machine |
130 | */ | 124 | */ |
131 | static int ir_rc5_decode(struct input_dev *input_dev, | 125 | static int ir_rc5_decode(struct input_dev *input_dev, s64 duration) |
132 | struct ir_raw_event *ev) | ||
133 | { | 126 | { |
134 | struct decoder_data *data; | 127 | struct decoder_data *data; |
135 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | 128 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); |
136 | int is_pulse, scancode, delta, toggle; | 129 | u8 command, system, toggle; |
130 | u32 scancode; | ||
131 | int u; | ||
137 | 132 | ||
138 | data = get_decoder_data(ir_dev); | 133 | data = get_decoder_data(ir_dev); |
139 | if (!data) | 134 | if (!data) |
@@ -142,79 +137,84 @@ static int ir_rc5_decode(struct input_dev *input_dev, | |||
142 | if (!data->enabled) | 137 | if (!data->enabled) |
143 | return 0; | 138 | return 0; |
144 | 139 | ||
145 | delta = DIV_ROUND_CLOSEST(ev->delta.tv_nsec, ir_rc5_remote_gap); | 140 | if (IS_RESET(duration)) { |
146 | |||
147 | /* The duration time refers to the last bit time */ | ||
148 | is_pulse = (ev->type & IR_PULSE) ? 1 : 0; | ||
149 | |||
150 | /* Very long delays are considered as start events */ | ||
151 | if (delta > RC5_DURATION || (ev->type & IR_START_EVENT)) | ||
152 | data->state = STATE_INACTIVE; | 141 | data->state = STATE_INACTIVE; |
153 | |||
154 | switch (data->state) { | ||
155 | case STATE_INACTIVE: | ||
156 | IR_dprintk(2, "currently inative. Start bit (%s) @%uus\n", | ||
157 | is_pulse ? "pulse" : "space", | ||
158 | (unsigned)(ev->delta.tv_nsec + 500) / 1000); | ||
159 | |||
160 | /* Discards the initial start space */ | ||
161 | if (!is_pulse) | ||
162 | goto err; | ||
163 | data->code = 1; | ||
164 | data->last_bit = 1; | ||
165 | data->elapsed = 0; | ||
166 | memset(&data->rc5_code, 0, sizeof(data->rc5_code)); | ||
167 | data->state = STATE_MARKSPACE; | ||
168 | return 0; | 142 | return 0; |
169 | case STATE_MARKSPACE: | 143 | } |
170 | if (delta != 1) | ||
171 | data->last_bit = data->last_bit ? 0 : 1; | ||
172 | 144 | ||
173 | data->elapsed += delta; | 145 | u = TO_UNITS(duration, RC5_UNIT); |
146 | if (DURATION(u) == 0) | ||
147 | goto out; | ||
174 | 148 | ||
175 | if ((data->elapsed % 2) == 1) | 149 | again: |
176 | return 0; | 150 | IR_dprintk(2, "RC5 decode started at state %i (%i units, %ius)\n", |
151 | data->state, u, TO_US(duration)); | ||
177 | 152 | ||
178 | data->code <<= 1; | 153 | if (DURATION(u) == 0 && data->state != STATE_FINISHED) |
179 | data->code |= data->last_bit; | 154 | return 0; |
180 | |||
181 | /* Fill the 2 unused bits at the command with 0 */ | ||
182 | if (data->elapsed / 2 == 6) | ||
183 | data->code <<= 2; | ||
184 | 155 | ||
185 | if (data->elapsed >= (RC5_NBITS - 1) * 2) { | 156 | switch (data->state) { |
186 | scancode = data->code; | ||
187 | 157 | ||
188 | /* Check for the start bits */ | 158 | case STATE_INACTIVE: |
189 | if ((scancode & 0xc000) != 0xc000) { | 159 | if (IS_PULSE(u)) { |
190 | IR_dprintk(1, "Code 0x%04x doesn't have two start bits. It is not RC-5\n", scancode); | 160 | data->state = STATE_BIT_START; |
191 | goto err; | 161 | data->count = 1; |
162 | DECREASE_DURATION(u, 1); | ||
163 | goto again; | ||
164 | } | ||
165 | break; | ||
166 | |||
167 | case STATE_BIT_START: | ||
168 | if (DURATION(u) == 1) { | ||
169 | data->rc5_bits <<= 1; | ||
170 | if (IS_SPACE(u)) | ||
171 | data->rc5_bits |= 1; | ||
172 | data->count++; | ||
173 | data->last_unit = u; | ||
174 | |||
175 | /* | ||
176 | * If the last bit is zero, a space will merge | ||
177 | * with the silence after the command. | ||
178 | */ | ||
179 | if (IS_PULSE(u) && data->count == RC5_NBITS) { | ||
180 | data->state = STATE_FINISHED; | ||
181 | goto again; | ||
192 | } | 182 | } |
193 | 183 | ||
194 | toggle = (scancode & 0x2000) ? 1 : 0; | 184 | data->state = STATE_BIT_END; |
185 | return 0; | ||
186 | } | ||
187 | break; | ||
195 | 188 | ||
196 | if (scancode == data->last_code) { | 189 | case STATE_BIT_END: |
197 | IR_dprintk(1, "RC-5 repeat\n"); | 190 | if (IS_TRANSITION(u, data->last_unit)) { |
198 | ir_repeat(input_dev); | 191 | if (data->count == RC5_NBITS) |
199 | } else { | 192 | data->state = STATE_FINISHED; |
200 | data->last_code = scancode; | 193 | else |
201 | scancode &= 0x1fff; | 194 | data->state = STATE_BIT_START; |
202 | IR_dprintk(1, "RC-5 scancode 0x%04x\n", scancode); | ||
203 | 195 | ||
204 | ir_keydown(input_dev, scancode, 0); | 196 | DECREASE_DURATION(u, 1); |
205 | } | 197 | goto again; |
206 | data->state = STATE_TRAILER; | ||
207 | } | 198 | } |
208 | return 0; | 199 | break; |
209 | case STATE_TRAILER: | 200 | |
201 | case STATE_FINISHED: | ||
202 | command = (data->rc5_bits & 0x0003F) >> 0; | ||
203 | system = (data->rc5_bits & 0x007C0) >> 6; | ||
204 | toggle = (data->rc5_bits & 0x00800) ? 1 : 0; | ||
205 | command += (data->rc5_bits & 0x01000) ? 0 : 0x40; | ||
206 | scancode = system << 8 | command; | ||
207 | |||
208 | IR_dprintk(1, "RC5 scancode 0x%04x (toggle: %u)\n", | ||
209 | scancode, toggle); | ||
210 | ir_keydown(input_dev, scancode, toggle); | ||
210 | data->state = STATE_INACTIVE; | 211 | data->state = STATE_INACTIVE; |
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
214 | err: | 215 | out: |
215 | IR_dprintk(1, "RC-5 decoded failed at %s @ %luus\n", | 216 | IR_dprintk(1, "RC5 decode failed at state %i (%i units, %ius)\n", |
216 | is_pulse ? "pulse" : "space", | 217 | data->state, u, TO_US(duration)); |
217 | (ev->delta.tv_nsec + 500) / 1000); | ||
218 | data->state = STATE_INACTIVE; | 218 | data->state = STATE_INACTIVE; |
219 | return -EINVAL; | 219 | return -EINVAL; |
220 | } | 220 | } |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 6d5fe596245d..e4681eda01f9 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -1018,7 +1018,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev) | |||
1018 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | 1018 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); |
1019 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | 1019 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); |
1020 | space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; | 1020 | space = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2) & ir->mask_keydown; |
1021 | ir_raw_event_store(dev->remote->dev, space ? IR_SPACE : IR_PULSE); | 1021 | ir_raw_event_store_edge(dev->remote->dev, space ? IR_SPACE : IR_PULSE); |
1022 | 1022 | ||
1023 | 1023 | ||
1024 | /* | 1024 | /* |
diff --git a/include/media/ir-core.h b/include/media/ir-core.h index e9fa94fe2ef5..e9a0cbf67ff6 100644 --- a/include/media/ir-core.h +++ b/include/media/ir-core.h | |||
@@ -65,14 +65,12 @@ struct ir_dev_props { | |||
65 | void (*close)(void *priv); | 65 | void (*close)(void *priv); |
66 | }; | 66 | }; |
67 | 67 | ||
68 | struct ir_raw_event { | ||
69 | struct timespec delta; /* Time spent before event */ | ||
70 | enum raw_event_type type; /* event type */ | ||
71 | }; | ||
72 | |||
73 | struct ir_raw_event_ctrl { | 68 | struct ir_raw_event_ctrl { |
74 | struct kfifo kfifo; /* fifo for the pulse/space events */ | 69 | struct work_struct rx_work; /* for the rx decoding workqueue */ |
75 | struct timespec last_event; /* when last event occurred */ | 70 | struct kfifo kfifo; /* fifo for the pulse/space durations */ |
71 | ktime_t last_event; /* when last event occurred */ | ||
72 | enum raw_event_type last_type; /* last event type */ | ||
73 | struct input_dev *input_dev; /* pointer to the parent input_dev */ | ||
76 | }; | 74 | }; |
77 | 75 | ||
78 | struct ir_input_dev { | 76 | struct ir_input_dev { |
@@ -97,8 +95,7 @@ struct ir_input_dev { | |||
97 | struct ir_raw_handler { | 95 | struct ir_raw_handler { |
98 | struct list_head list; | 96 | struct list_head list; |
99 | 97 | ||
100 | int (*decode)(struct input_dev *input_dev, | 98 | int (*decode)(struct input_dev *input_dev, s64 duration); |
101 | struct ir_raw_event *ev); | ||
102 | int (*raw_register)(struct input_dev *input_dev); | 99 | int (*raw_register)(struct input_dev *input_dev); |
103 | int (*raw_unregister)(struct input_dev *input_dev); | 100 | int (*raw_unregister)(struct input_dev *input_dev); |
104 | }; | 101 | }; |
@@ -154,8 +151,14 @@ void ir_unregister_class(struct input_dev *input_dev); | |||
154 | /* Routines from ir-raw-event.c */ | 151 | /* Routines from ir-raw-event.c */ |
155 | int ir_raw_event_register(struct input_dev *input_dev); | 152 | int ir_raw_event_register(struct input_dev *input_dev); |
156 | void ir_raw_event_unregister(struct input_dev *input_dev); | 153 | void ir_raw_event_unregister(struct input_dev *input_dev); |
157 | int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type); | 154 | void ir_raw_event_handle(struct input_dev *input_dev); |
158 | int ir_raw_event_handle(struct input_dev *input_dev); | 155 | int ir_raw_event_store(struct input_dev *input_dev, s64 duration); |
156 | int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type type); | ||
157 | static inline void ir_raw_event_reset(struct input_dev *input_dev) | ||
158 | { | ||
159 | ir_raw_event_store(input_dev, 0); | ||
160 | ir_raw_event_handle(input_dev); | ||
161 | } | ||
159 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); | 162 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); |
160 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); | 163 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); |
161 | void ir_raw_init(void); | 164 | void ir_raw_init(void); |
@@ -174,4 +177,26 @@ void ir_raw_init(void); | |||
174 | #define load_rc5_decode() 0 | 177 | #define load_rc5_decode() 0 |
175 | #endif | 178 | #endif |
176 | 179 | ||
180 | /* macros for ir decoders */ | ||
181 | #define PULSE(units) ((units)) | ||
182 | #define SPACE(units) (-(units)) | ||
183 | #define IS_RESET(duration) ((duration) == 0) | ||
184 | #define IS_PULSE(duration) ((duration) > 0) | ||
185 | #define IS_SPACE(duration) ((duration) < 0) | ||
186 | #define DURATION(duration) (abs((duration))) | ||
187 | #define IS_TRANSITION(x, y) ((x) * (y) < 0) | ||
188 | #define DECREASE_DURATION(duration, amount) \ | ||
189 | do { \ | ||
190 | if (IS_SPACE(duration)) \ | ||
191 | duration += (amount); \ | ||
192 | else if (IS_PULSE(duration)) \ | ||
193 | duration -= (amount); \ | ||
194 | } while (0) | ||
195 | |||
196 | #define TO_UNITS(duration, unit_len) \ | ||
197 | ((int)((duration) > 0 ? \ | ||
198 | DIV_ROUND_CLOSEST(abs((duration)), (unit_len)) :\ | ||
199 | -DIV_ROUND_CLOSEST(abs((duration)), (unit_len)))) | ||
200 | #define TO_US(duration) ((int)TO_UNITS(duration, 1000)) | ||
201 | |||
177 | #endif /* _IR_CORE */ | 202 | #endif /* _IR_CORE */ |