]> Pileus Git - ~andy/linux/blob - drivers/media/IR/ir-raw-event.c
V4L/DVB: saa7134: don't wait too much to generate an IR event on raw_decode
[~andy/linux] / drivers / media / IR / ir-raw-event.c
1 /* ir-raw-event.c - handle IR Pulse/Space event
2  *
3  * Copyright (C) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  */
14
15 #include <media/ir-core.h>
16
17 /* Define the max number of bit transitions per IR keycode */
18 #define MAX_IR_EVENT_SIZE       256
19
20 static void ir_keyup_timer(unsigned long data)
21 {
22         struct input_dev *input_dev = (struct input_dev *)data;
23
24         ir_keyup(input_dev);
25 }
26
27 int ir_raw_event_register(struct input_dev *input_dev)
28 {
29         struct ir_input_dev *ir = input_get_drvdata(input_dev);
30         int rc, size;
31
32         ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
33
34         size = sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE * 2;
35         size = roundup_pow_of_two(size);
36
37         init_timer(&ir->raw->timer_keyup);
38         ir->raw->timer_keyup.function = ir_keyup_timer;
39         ir->raw->timer_keyup.data = (unsigned long)input_dev;
40         set_bit(EV_REP, input_dev->evbit);
41
42         rc = kfifo_alloc(&ir->raw->kfifo, size, GFP_KERNEL);
43
44         return rc;
45 }
46 EXPORT_SYMBOL_GPL(ir_raw_event_register);
47
48 void ir_raw_event_unregister(struct input_dev *input_dev)
49 {
50         struct ir_input_dev *ir = input_get_drvdata(input_dev);
51
52         if (!ir->raw)
53                 return;
54
55         del_timer_sync(&ir->raw->timer_keyup);
56
57         kfifo_free(&ir->raw->kfifo);
58         kfree(ir->raw);
59         ir->raw = NULL;
60 }
61 EXPORT_SYMBOL_GPL(ir_raw_event_unregister);
62
63 int ir_raw_event_store(struct input_dev *input_dev, enum raw_event_type type)
64 {
65         struct ir_input_dev     *ir = input_get_drvdata(input_dev);
66         struct timespec         ts;
67         struct ir_raw_event     event;
68         int                     rc;
69
70         if (!ir->raw)
71                 return -EINVAL;
72
73         event.type = type;
74         event.delta.tv_sec = 0;
75         event.delta.tv_nsec = 0;
76
77         ktime_get_ts(&ts);
78
79         if (timespec_equal(&ir->raw->last_event, &event.delta))
80                 event.type |= IR_START_EVENT;
81         else
82                 event.delta = timespec_sub(ts, ir->raw->last_event);
83
84         memcpy(&ir->raw->last_event, &ts, sizeof(ts));
85
86         if (event.delta.tv_sec) {
87                 event.type |= IR_START_EVENT;
88                 event.delta.tv_sec = 0;
89                 event.delta.tv_nsec = 0;
90         }
91
92         kfifo_in(&ir->raw->kfifo, &event, sizeof(event));
93
94         return rc;
95 }
96 EXPORT_SYMBOL_GPL(ir_raw_event_store);
97
98 int ir_raw_event_handle(struct input_dev *input_dev)
99 {
100         struct ir_input_dev             *ir = input_get_drvdata(input_dev);
101         int                             rc;
102         struct ir_raw_event             *evs;
103         int                             len, i;
104
105         /*
106          * Store the events into a temporary buffer. This allows calling more than
107          * one decoder to deal with the received data
108          */
109         len = kfifo_len(&ir->raw->kfifo) / sizeof(*evs);
110         if (!len)
111                 return 0;
112         evs = kmalloc(len * sizeof(*evs), GFP_ATOMIC);
113
114         for (i = 0; i < len; i++) {
115                 rc = kfifo_out(&ir->raw->kfifo, &evs[i], sizeof(*evs));
116                 if (rc != sizeof(*evs)) {
117                         IR_dprintk(1, "overflow error: received %d instead of %zd\n",
118                                    rc, sizeof(*evs));
119                         return -EINVAL;
120                 }
121                 IR_dprintk(2, "event type %d, time before event: %07luus\n",
122                         evs[i].type, (evs[i].delta.tv_nsec + 500) / 1000);
123         }
124
125         rc = ir_nec_decode(input_dev, evs, len);
126
127         kfree(evs);
128
129         return rc;
130 }
131 EXPORT_SYMBOL_GPL(ir_raw_event_handle);