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.c73
1 files changed, 37 insertions, 36 deletions
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c
index fb3336c37191..5f98ab823057 100644
--- a/drivers/media/IR/ir-raw-event.c
+++ b/drivers/media/IR/ir-raw-event.c
@@ -20,36 +20,14 @@
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 DEFINE_SPINLOCK(ir_raw_handler_lock); 27static DEFINE_SPINLOCK(ir_raw_handler_lock);
25static LIST_HEAD(ir_raw_handler_list); 28static LIST_HEAD(ir_raw_handler_list);
26static u64 available_protocols; 29static u64 available_protocols;
27 30
28/**
29 * RUN_DECODER() - runs an operation on all IR decoders
30 * @ops: IR raw handler operation to be called
31 * @arg: arguments to be passed to the callback
32 *
33 * Calls ir_raw_handler::ops for all registered IR handlers. It prevents
34 * new decode addition/removal while running, by locking ir_raw_handler_lock
35 * mutex. If an error occurs, we keep going, as in the decode case, each
36 * decoder must have a crack at decoding the data. We return a sum of the
37 * return codes, which will be either 0 or negative for current callers.
38 */
39#define RUN_DECODER(ops, ...) ({ \
40 struct ir_raw_handler *_ir_raw_handler; \
41 int _sumrc = 0, _rc; \
42 spin_lock(&ir_raw_handler_lock); \
43 list_for_each_entry(_ir_raw_handler, &ir_raw_handler_list, list) { \
44 if (_ir_raw_handler->ops) { \
45 _rc = _ir_raw_handler->ops(__VA_ARGS__); \
46 _sumrc += _rc; \
47 } \
48 } \
49 spin_unlock(&ir_raw_handler_lock); \
50 _sumrc; \
51})
52
53#ifdef MODULE 31#ifdef MODULE
54/* Used to load the decoders */ 32/* Used to load the decoders */
55static struct work_struct wq_load; 33static struct work_struct wq_load;
@@ -58,11 +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);
45 list_for_each_entry(handler, &ir_raw_handler_list, list)
46 handler->decode(raw->input_dev, ev);
47 spin_unlock(&ir_raw_handler_lock);
48 raw->prev_ev = ev;
49 }
66} 50}
67 51
68/** 52/**
@@ -176,6 +160,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
176{ 160{
177 struct ir_input_dev *ir = input_get_drvdata(input_dev); 161 struct ir_input_dev *ir = input_get_drvdata(input_dev);
178 int rc; 162 int rc;
163 struct ir_raw_handler *handler;
179 164
180 ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); 165 ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL);
181 if (!ir->raw) 166 if (!ir->raw)
@@ -192,26 +177,32 @@ int ir_raw_event_register(struct input_dev *input_dev)
192 return rc; 177 return rc;
193 } 178 }
194 179
195 rc = RUN_DECODER(raw_register, input_dev); 180 spin_lock(&ir_raw_handler_lock);
196 if (rc < 0) { 181 list_add_tail(&ir->raw->list, &ir_raw_client_list);
197 kfifo_free(&ir->raw->kfifo); 182 list_for_each_entry(handler, &ir_raw_handler_list, list)
198 kfree(ir->raw); 183 if (handler->raw_register)
199 ir->raw = NULL; 184 handler->raw_register(ir->raw->input_dev);
200 return rc; 185 spin_unlock(&ir_raw_handler_lock);
201 }
202 186
203 return rc; 187 return 0;
204} 188}
205 189
206void ir_raw_event_unregister(struct input_dev *input_dev) 190void ir_raw_event_unregister(struct input_dev *input_dev)
207{ 191{
208 struct ir_input_dev *ir = input_get_drvdata(input_dev); 192 struct ir_input_dev *ir = input_get_drvdata(input_dev);
193 struct ir_raw_handler *handler;
209 194
210 if (!ir->raw) 195 if (!ir->raw)
211 return; 196 return;
212 197
213 cancel_work_sync(&ir->raw->rx_work); 198 cancel_work_sync(&ir->raw->rx_work);
214 RUN_DECODER(raw_unregister, input_dev); 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);
215 206
216 kfifo_free(&ir->raw->kfifo); 207 kfifo_free(&ir->raw->kfifo);
217 kfree(ir->raw); 208 kfree(ir->raw);
@@ -224,8 +215,13 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
224 215
225int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) 216int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
226{ 217{
218 struct ir_raw_event_ctrl *raw;
219
227 spin_lock(&ir_raw_handler_lock); 220 spin_lock(&ir_raw_handler_lock);
228 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);
229 available_protocols |= ir_raw_handler->protocols; 225 available_protocols |= ir_raw_handler->protocols;
230 spin_unlock(&ir_raw_handler_lock); 226 spin_unlock(&ir_raw_handler_lock);
231 227
@@ -235,8 +231,13 @@ EXPORT_SYMBOL(ir_raw_handler_register);
235 231
236void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) 232void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
237{ 233{
234 struct ir_raw_event_ctrl *raw;
235
238 spin_lock(&ir_raw_handler_lock); 236 spin_lock(&ir_raw_handler_lock);
239 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);
240 available_protocols &= ~ir_raw_handler->protocols; 241 available_protocols &= ~ir_raw_handler->protocols;
241 spin_unlock(&ir_raw_handler_lock); 242 spin_unlock(&ir_raw_handler_lock);
242} 243}