diff options
Diffstat (limited to 'drivers/media/IR/ir-raw-event.c')
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 167 |
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 */ | ||
24 | static LIST_HEAD(ir_raw_client_list); | ||
25 | |||
23 | /* Used to handle IR raw handler extensions */ | 26 | /* Used to handle IR raw handler extensions */ |
24 | static LIST_HEAD(ir_raw_handler_list); | ||
25 | static DEFINE_SPINLOCK(ir_raw_handler_lock); | 27 | static DEFINE_SPINLOCK(ir_raw_handler_lock); |
26 | 28 | static LIST_HEAD(ir_raw_handler_list); | |
27 | /** | 29 | static 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; | |||
58 | static void ir_raw_event_work(struct work_struct *work) | 36 | static 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); | |
68 | int 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 | |||
99 | void 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 | } |
205 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 143 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
206 | 144 | ||
145 | /* used internally by the sysfs interface */ | ||
146 | u64 | ||
147 | ir_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 | */ | ||
159 | int 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 | |||
190 | void 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 | ||
211 | int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) | 216 | int 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 | } |
218 | EXPORT_SYMBOL(ir_raw_handler_register); | 230 | EXPORT_SYMBOL(ir_raw_handler_register); |
219 | 231 | ||
220 | void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) | 232 | void 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 | } |
226 | EXPORT_SYMBOL(ir_raw_handler_unregister); | 244 | EXPORT_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 |