aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-raw-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/IR/ir-raw-event.c')
-rw-r--r--drivers/media/IR/ir-raw-event.c167
1 files changed, 93 insertions, 74 deletions
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index ea68a3f2effa..6f192ef31db1 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -20,35 +20,13 @@
20/* Define the max number of pulse/space transitions to buffer */ 20/* Define the max number of pulse/space transitions to buffer */
21#define MAX_IR_EVENT_SIZE 512 21#define MAX_IR_EVENT_SIZE 512
22 22
23/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
24static LIST_HEAD(ir_raw_client_list);
25
23/* Used to handle IR raw handler extensions */ 26/* Used to handle IR raw handler extensions */
24static LIST_HEAD(ir_raw_handler_list);
25static DEFINE_SPINLOCK(ir_raw_handler_lock); 27static DEFINE_SPINLOCK(ir_raw_handler_lock);
26 28static LIST_HEAD(ir_raw_handler_list);
27/** 29static u64 available_protocols;
28 * RUN_DECODER() - runs an operation on all IR decoders
29 * @ops: IR raw handler operation to be called
30 * @arg: arguments to be passed to the callback
31 *
32 * Calls ir_raw_handler::ops for all registered IR handlers. It prevents
33 * new decode addition/removal while running, by locking ir_raw_handler_lock
34 * mutex. If an error occurs, it stops the ops. Otherwise, it returns a sum
35 * of the return codes.
36 */
37#define RUN_DECODER(ops, ...) ({ \
38 struct ir_raw_handler *_ir_raw_handler; \
39 int _sumrc = 0, _rc; \
40 spin_lock(&ir_raw_handler_lock); \
41 list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \
42 if (_ir_raw_handler->ops) { \
43 _rc = _ir_raw_handler->ops(__VA_ARGS__); \
44 if (_rc < 0) \
45 break; \
46 _sumrc += _rc; \
47 } \
48 } \
49 spin_unlock(&ir_raw_handler_lock); \
50 _sumrc; \
51})
52 30
53#ifdef MODULE 31#ifdef MODULE
54/* Used to load the decoders */ 32/* Used to load the decoders */
@@ -58,57 +36,17 @@ static struct work_struct wq_load;
58static void ir_raw_event_work(struct work_struct *work) 36static void ir_raw_event_work(struct work_struct *work)
59{ 37{
60 struct ir_raw_event ev; 38 struct ir_raw_event ev;
39 struct ir_raw_handler *handler;
61 struct ir_raw_event_ctrl *raw = 40 struct ir_raw_event_ctrl *raw =
62 container_of(work, struct ir_raw_event_ctrl, rx_work); 41 container_of(work, struct ir_raw_event_ctrl, rx_work);
63 42
64 while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) 43 while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
65 RUN_DECODER(decode, raw->input_dev, ev); 44 spin_lock(&ir_raw_handler_lock);
66} 45 list_for_each_entry(handler, &ir_raw_handler_list, list)
67 46 handler->decode(raw->input_dev, ev);
68int ir_raw_event_register(struct input_dev *input_dev) 47 spin_unlock(&ir_raw_handler_lock);
69{ 48 raw->prev_ev = ev;
70 struct ir_input_dev *ir = input_get_drvdata(input_dev);
71 int rc;
72
73 ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
74 if (!ir->raw)
75 return -ENOMEM;
76
77 ir->raw->input_dev = input_dev;
78 INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
79
80 rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
81 GFP_KERNEL);
82 if (rc < 0) {
83 kfree(ir->raw);
84 ir->raw = NULL;
85 return rc;
86 }
87
88 rc = RUN_DECODER(raw_register, input_dev);
89 if (rc < 0) {
90 kfifo_free(&ir->raw->kfifo);
91 kfree(ir->raw);
92 ir->raw = NULL;
93 return rc;
94 } 49 }
95
96 return rc;
97}
98
99void ir_raw_event_unregister(struct input_dev *input_dev)
100{
101 struct ir_input_dev *ir = input_get_drvdata(input_dev);
102
103 if (!ir->raw)
104 return;
105
106 cancel_work_sync(&ir->raw->rx_work);
107 RUN_DECODER(raw_unregister, input_dev);
108
109 kfifo_free(&ir->raw->kfifo);
110 kfree(ir->raw);
111 ir->raw = NULL;
112} 50}
113 51
114/** 52/**
@@ -204,23 +142,103 @@ void ir_raw_event_handle(struct input_dev *input_dev)
204} 142}
205EXPORT_SYMBOL_GPL(ir_raw_event_handle); 143EXPORT_SYMBOL_GPL(ir_raw_event_handle);
206 144
145/* used internally by the sysfs interface */
146u64
147ir_raw_get_allowed_protocols()
148{
149 u64 protocols;
150 spin_lock(&ir_raw_handler_lock);
151 protocols = available_protocols;
152 spin_unlock(&ir_raw_handler_lock);
153 return protocols;
154}
155
156/*
157 * Used to (un)register raw event clients
158 */
159int ir_raw_event_register(struct input_dev *input_dev)
160{
161 struct ir_input_dev *ir = input_get_drvdata(input_dev);
162 int rc;
163 struct ir_raw_handler *handler;
164
165 ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
166 if (!ir->raw)
167 return -ENOMEM;
168
169 ir->raw->input_dev = input_dev;
170 INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
171 ir->raw->enabled_protocols = ~0;
172 rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
173 GFP_KERNEL);
174 if (rc < 0) {
175 kfree(ir->raw);
176 ir->raw = NULL;
177 return rc;
178 }
179
180 spin_lock(&ir_raw_handler_lock);
181 list_add_tail(&ir->raw->list, &ir_raw_client_list);
182 list_for_each_entry(handler, &ir_raw_handler_list, list)
183 if (handler->raw_register)
184 handler->raw_register(ir->raw->input_dev);
185 spin_unlock(&ir_raw_handler_lock);
186
187 return 0;
188}
189
190void ir_raw_event_unregister(struct input_dev *input_dev)
191{
192 struct ir_input_dev *ir = input_get_drvdata(input_dev);
193 struct ir_raw_handler *handler;
194
195 if (!ir->raw)
196 return;
197
198 cancel_work_sync(&ir->raw->rx_work);
199
200 spin_lock(&ir_raw_handler_lock);
201 list_del(&ir->raw->list);
202 list_for_each_entry(handler, &ir_raw_handler_list, list)
203 if (handler->raw_unregister)
204 handler->raw_unregister(ir->raw->input_dev);
205 spin_unlock(&ir_raw_handler_lock);
206
207 kfifo_free(&ir->raw->kfifo);
208 kfree(ir->raw);
209 ir->raw = NULL;
210}
211
207/* 212/*
208 * Extension interface - used to register the IR decoders 213 * Extension interface - used to register the IR decoders
209 */ 214 */
210 215
211int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) 216int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
212{ 217{
218 struct ir_raw_event_ctrl *raw;
219
213 spin_lock(&ir_raw_handler_lock); 220 spin_lock(&ir_raw_handler_lock);
214 list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); 221 list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
222 if (ir_raw_handler->raw_register)
223 list_for_each_entry(raw, &ir_raw_client_list, list)
224 ir_raw_handler->raw_register(raw->input_dev);
225 available_protocols |= ir_raw_handler->protocols;
215 spin_unlock(&ir_raw_handler_lock); 226 spin_unlock(&ir_raw_handler_lock);
227
216 return 0; 228 return 0;
217} 229}
218EXPORT_SYMBOL(ir_raw_handler_register); 230EXPORT_SYMBOL(ir_raw_handler_register);
219 231
220void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) 232void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
221{ 233{
234 struct ir_raw_event_ctrl *raw;
235
222 spin_lock(&ir_raw_handler_lock); 236 spin_lock(&ir_raw_handler_lock);
223 list_del(&ir_raw_handler->list); 237 list_del(&ir_raw_handler->list);
238 if (ir_raw_handler->raw_unregister)
239 list_for_each_entry(raw, &ir_raw_client_list, list)
240 ir_raw_handler->raw_unregister(raw->input_dev);
241 available_protocols &= ~ir_raw_handler->protocols;
224 spin_unlock(&ir_raw_handler_lock); 242 spin_unlock(&ir_raw_handler_lock);
225} 243}
226EXPORT_SYMBOL(ir_raw_handler_unregister); 244EXPORT_SYMBOL(ir_raw_handler_unregister);
@@ -235,6 +253,7 @@ static void init_decoders(struct work_struct *work)
235 load_rc6_decode(); 253 load_rc6_decode();
236 load_jvc_decode(); 254 load_jvc_decode();
237 load_sony_decode(); 255 load_sony_decode();
256 load_lirc_codec();
238 257
239 /* If needed, we may later add some init code. In this case, 258 /* If needed, we may later add some init code. In this case,
240 it is needed to change the CONFIG_MODULE test at ir-core.h 259 it is needed to change the CONFIG_MODULE test at ir-core.h