diff options
Diffstat (limited to 'drivers/media/IR/ir-raw-event.c')
| -rw-r--r-- | drivers/media/IR/ir-raw-event.c | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 8e0e1b1f8c87..a06a07e4e0b1 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c | |||
| @@ -39,22 +39,34 @@ static int ir_raw_event_thread(void *data) | |||
| 39 | struct ir_raw_event ev; | 39 | struct ir_raw_event ev; |
| 40 | struct ir_raw_handler *handler; | 40 | struct ir_raw_handler *handler; |
| 41 | struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; | 41 | struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data; |
| 42 | int retval; | ||
| 42 | 43 | ||
| 43 | while (!kthread_should_stop()) { | 44 | while (!kthread_should_stop()) { |
| 44 | try_to_freeze(); | ||
| 45 | 45 | ||
| 46 | mutex_lock(&ir_raw_handler_lock); | 46 | spin_lock_irq(&raw->lock); |
| 47 | retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev)); | ||
| 48 | |||
| 49 | if (!retval) { | ||
| 50 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 51 | |||
| 52 | if (kthread_should_stop()) | ||
| 53 | set_current_state(TASK_RUNNING); | ||
| 47 | 54 | ||
| 48 | while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { | 55 | spin_unlock_irq(&raw->lock); |
| 49 | list_for_each_entry(handler, &ir_raw_handler_list, list) | 56 | schedule(); |
| 50 | handler->decode(raw->input_dev, ev); | 57 | continue; |
| 51 | raw->prev_ev = ev; | ||
| 52 | } | 58 | } |
| 53 | 59 | ||
| 54 | mutex_unlock(&ir_raw_handler_lock); | 60 | spin_unlock_irq(&raw->lock); |
| 61 | |||
| 55 | 62 | ||
| 56 | set_current_state(TASK_INTERRUPTIBLE); | 63 | BUG_ON(retval != sizeof(ev)); |
| 57 | schedule(); | 64 | |
| 65 | mutex_lock(&ir_raw_handler_lock); | ||
| 66 | list_for_each_entry(handler, &ir_raw_handler_list, list) | ||
| 67 | handler->decode(raw->input_dev, ev); | ||
| 68 | raw->prev_ev = ev; | ||
| 69 | mutex_unlock(&ir_raw_handler_lock); | ||
| 58 | } | 70 | } |
| 59 | 71 | ||
| 60 | return 0; | 72 | return 0; |
| @@ -77,7 +89,7 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) | |||
| 77 | if (!ir->raw) | 89 | if (!ir->raw) |
| 78 | return -EINVAL; | 90 | return -EINVAL; |
| 79 | 91 | ||
| 80 | IR_dprintk(2, "sample: (05%dus %s)\n", | 92 | IR_dprintk(2, "sample: (%05dus %s)\n", |
| 81 | TO_US(ev->duration), TO_STR(ev->pulse)); | 93 | TO_US(ev->duration), TO_STR(ev->pulse)); |
| 82 | 94 | ||
| 83 | if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) | 95 | if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) |
| @@ -162,7 +174,7 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev, | |||
| 162 | if (ir->idle && !ev->pulse) | 174 | if (ir->idle && !ev->pulse) |
| 163 | return 0; | 175 | return 0; |
| 164 | else if (ir->idle) | 176 | else if (ir->idle) |
| 165 | ir_raw_event_set_idle(input_dev, 0); | 177 | ir_raw_event_set_idle(input_dev, false); |
| 166 | 178 | ||
| 167 | if (!raw->this_ev.duration) { | 179 | if (!raw->this_ev.duration) { |
| 168 | raw->this_ev = *ev; | 180 | raw->this_ev = *ev; |
| @@ -175,48 +187,35 @@ int ir_raw_event_store_with_filter(struct input_dev *input_dev, | |||
| 175 | 187 | ||
| 176 | /* Enter idle mode if nessesary */ | 188 | /* Enter idle mode if nessesary */ |
| 177 | if (!ev->pulse && ir->props->timeout && | 189 | if (!ev->pulse && ir->props->timeout && |
| 178 | raw->this_ev.duration >= ir->props->timeout) | 190 | raw->this_ev.duration >= ir->props->timeout) { |
| 179 | ir_raw_event_set_idle(input_dev, 1); | 191 | ir_raw_event_set_idle(input_dev, true); |
| 192 | } | ||
| 180 | return 0; | 193 | return 0; |
| 181 | } | 194 | } |
| 182 | EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); | 195 | EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter); |
| 183 | 196 | ||
| 184 | void ir_raw_event_set_idle(struct input_dev *input_dev, int idle) | 197 | /** |
| 198 | * ir_raw_event_set_idle() - hint the ir core if device is receiving | ||
| 199 | * IR data or not | ||
| 200 | * @input_dev: the struct input_dev device descriptor | ||
| 201 | * @idle: the hint value | ||
| 202 | */ | ||
| 203 | void ir_raw_event_set_idle(struct input_dev *input_dev, bool idle) | ||
| 185 | { | 204 | { |
| 186 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 205 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
| 187 | struct ir_raw_event_ctrl *raw = ir->raw; | 206 | struct ir_raw_event_ctrl *raw = ir->raw; |
| 188 | ktime_t now; | ||
| 189 | u64 delta; | ||
| 190 | 207 | ||
| 191 | if (!ir->props) | 208 | if (!ir->props || !ir->raw) |
| 192 | return; | 209 | return; |
| 193 | 210 | ||
| 194 | if (!ir->raw) | 211 | IR_dprintk(2, "%s idle mode\n", idle ? "enter" : "leave"); |
| 195 | goto out; | ||
| 196 | 212 | ||
| 197 | if (idle) { | 213 | if (idle) { |
| 198 | IR_dprintk(2, "enter idle mode\n"); | 214 | raw->this_ev.timeout = true; |
| 199 | raw->last_event = ktime_get(); | ||
| 200 | } else { | ||
| 201 | IR_dprintk(2, "exit idle mode\n"); | ||
| 202 | |||
| 203 | now = ktime_get(); | ||
| 204 | delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event)); | ||
| 205 | |||
| 206 | WARN_ON(raw->this_ev.pulse); | ||
| 207 | |||
| 208 | raw->this_ev.duration = | ||
| 209 | min(raw->this_ev.duration + delta, | ||
| 210 | (u64)IR_MAX_DURATION); | ||
| 211 | |||
| 212 | ir_raw_event_store(input_dev, &raw->this_ev); | 215 | ir_raw_event_store(input_dev, &raw->this_ev); |
| 213 | 216 | init_ir_raw_event(&raw->this_ev); | |
| 214 | if (raw->this_ev.duration == IR_MAX_DURATION) | ||
| 215 | ir_raw_event_reset(input_dev); | ||
| 216 | |||
| 217 | raw->this_ev.duration = 0; | ||
| 218 | } | 217 | } |
| 219 | out: | 218 | |
| 220 | if (ir->props->s_idle) | 219 | if (ir->props->s_idle) |
| 221 | ir->props->s_idle(ir->props->priv, idle); | 220 | ir->props->s_idle(ir->props->priv, idle); |
| 222 | ir->idle = idle; | 221 | ir->idle = idle; |
| @@ -232,11 +231,14 @@ EXPORT_SYMBOL_GPL(ir_raw_event_set_idle); | |||
| 232 | void ir_raw_event_handle(struct input_dev *input_dev) | 231 | void ir_raw_event_handle(struct input_dev *input_dev) |
| 233 | { | 232 | { |
| 234 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | 233 | struct ir_input_dev *ir = input_get_drvdata(input_dev); |
| 234 | unsigned long flags; | ||
| 235 | 235 | ||
| 236 | if (!ir->raw) | 236 | if (!ir->raw) |
| 237 | return; | 237 | return; |
| 238 | 238 | ||
| 239 | spin_lock_irqsave(&ir->raw->lock, flags); | ||
| 239 | wake_up_process(ir->raw->thread); | 240 | wake_up_process(ir->raw->thread); |
| 241 | spin_unlock_irqrestore(&ir->raw->lock, flags); | ||
| 240 | } | 242 | } |
| 241 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 243 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
| 242 | 244 | ||
| @@ -275,6 +277,7 @@ int ir_raw_event_register(struct input_dev *input_dev) | |||
| 275 | return rc; | 277 | return rc; |
| 276 | } | 278 | } |
| 277 | 279 | ||
| 280 | spin_lock_init(&ir->raw->lock); | ||
| 278 | ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, | 281 | ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw, |
| 279 | "rc%u", (unsigned int)ir->devno); | 282 | "rc%u", (unsigned int)ir->devno); |
| 280 | 283 | ||
