diff options
Diffstat (limited to 'drivers/media/IR/ir-raw-event.c')
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 112 |
1 files changed, 65 insertions, 47 deletions
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index d3bd3f98e008..fb3336c37191 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c | |||
@@ -21,8 +21,9 @@ | |||
21 | #define MAX_IR_EVENT_SIZE 512 | 21 | #define MAX_IR_EVENT_SIZE 512 |
22 | 22 | ||
23 | /* Used to handle IR raw handler extensions */ | 23 | /* Used to handle IR raw handler extensions */ |
24 | static LIST_HEAD(ir_raw_handler_list); | ||
25 | static DEFINE_SPINLOCK(ir_raw_handler_lock); | 24 | static DEFINE_SPINLOCK(ir_raw_handler_lock); |
25 | static LIST_HEAD(ir_raw_handler_list); | ||
26 | static u64 available_protocols; | ||
26 | 27 | ||
27 | /** | 28 | /** |
28 | * RUN_DECODER() - runs an operation on all IR decoders | 29 | * RUN_DECODER() - runs an operation on all IR decoders |
@@ -64,52 +65,6 @@ static void ir_raw_event_work(struct work_struct *work) | |||
64 | RUN_DECODER(decode, raw->input_dev, ev); | 65 | RUN_DECODER(decode, raw->input_dev, ev); |
65 | } | 66 | } |
66 | 67 | ||
67 | int ir_raw_event_register(struct input_dev *input_dev) | ||
68 | { | ||
69 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
70 | int rc; | ||
71 | |||
72 | ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); | ||
73 | if (!ir->raw) | ||
74 | return -ENOMEM; | ||
75 | |||
76 | ir->raw->input_dev = input_dev; | ||
77 | INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); | ||
78 | |||
79 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, | ||
80 | GFP_KERNEL); | ||
81 | if (rc < 0) { | ||
82 | kfree(ir->raw); | ||
83 | ir->raw = NULL; | ||
84 | return rc; | ||
85 | } | ||
86 | |||
87 | rc = RUN_DECODER(raw_register, input_dev); | ||
88 | if (rc < 0) { | ||
89 | kfifo_free(&ir->raw->kfifo); | ||
90 | kfree(ir->raw); | ||
91 | ir->raw = NULL; | ||
92 | return rc; | ||
93 | } | ||
94 | |||
95 | return rc; | ||
96 | } | ||
97 | |||
98 | void ir_raw_event_unregister(struct input_dev *input_dev) | ||
99 | { | ||
100 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
101 | |||
102 | if (!ir->raw) | ||
103 | return; | ||
104 | |||
105 | cancel_work_sync(&ir->raw->rx_work); | ||
106 | RUN_DECODER(raw_unregister, input_dev); | ||
107 | |||
108 | kfifo_free(&ir->raw->kfifo); | ||
109 | kfree(ir->raw); | ||
110 | ir->raw = NULL; | ||
111 | } | ||
112 | |||
113 | /** | 68 | /** |
114 | * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders | 69 | * ir_raw_event_store() - pass a pulse/space duration to the raw ir decoders |
115 | * @input_dev: the struct input_dev device descriptor | 70 | * @input_dev: the struct input_dev device descriptor |
@@ -203,6 +158,66 @@ void ir_raw_event_handle(struct input_dev *input_dev) | |||
203 | } | 158 | } |
204 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); | 159 | EXPORT_SYMBOL_GPL(ir_raw_event_handle); |
205 | 160 | ||
161 | /* used internally by the sysfs interface */ | ||
162 | u64 | ||
163 | ir_raw_get_allowed_protocols() | ||
164 | { | ||
165 | u64 protocols; | ||
166 | spin_lock(&ir_raw_handler_lock); | ||
167 | protocols = available_protocols; | ||
168 | spin_unlock(&ir_raw_handler_lock); | ||
169 | return protocols; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Used to (un)register raw event clients | ||
174 | */ | ||
175 | int ir_raw_event_register(struct input_dev *input_dev) | ||
176 | { | ||
177 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
178 | int rc; | ||
179 | |||
180 | ir->raw = kzalloc(sizeof(*ir->raw), GFP_KERNEL); | ||
181 | if (!ir->raw) | ||
182 | return -ENOMEM; | ||
183 | |||
184 | ir->raw->input_dev = input_dev; | ||
185 | INIT_WORK(&ir->raw->rx_work, ir_raw_event_work); | ||
186 | ir->raw->enabled_protocols = ~0; | ||
187 | rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, | ||
188 | GFP_KERNEL); | ||
189 | if (rc < 0) { | ||
190 | kfree(ir->raw); | ||
191 | ir->raw = NULL; | ||
192 | return rc; | ||
193 | } | ||
194 | |||
195 | rc = RUN_DECODER(raw_register, input_dev); | ||
196 | if (rc < 0) { | ||
197 | kfifo_free(&ir->raw->kfifo); | ||
198 | kfree(ir->raw); | ||
199 | ir->raw = NULL; | ||
200 | return rc; | ||
201 | } | ||
202 | |||
203 | return rc; | ||
204 | } | ||
205 | |||
206 | void ir_raw_event_unregister(struct input_dev *input_dev) | ||
207 | { | ||
208 | struct ir_input_dev *ir = input_get_drvdata(input_dev); | ||
209 | |||
210 | if (!ir->raw) | ||
211 | return; | ||
212 | |||
213 | cancel_work_sync(&ir->raw->rx_work); | ||
214 | RUN_DECODER(raw_unregister, input_dev); | ||
215 | |||
216 | kfifo_free(&ir->raw->kfifo); | ||
217 | kfree(ir->raw); | ||
218 | ir->raw = NULL; | ||
219 | } | ||
220 | |||
206 | /* | 221 | /* |
207 | * Extension interface - used to register the IR decoders | 222 | * Extension interface - used to register the IR decoders |
208 | */ | 223 | */ |
@@ -211,7 +226,9 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) | |||
211 | { | 226 | { |
212 | spin_lock(&ir_raw_handler_lock); | 227 | spin_lock(&ir_raw_handler_lock); |
213 | list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); | 228 | list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); |
229 | available_protocols |= ir_raw_handler->protocols; | ||
214 | spin_unlock(&ir_raw_handler_lock); | 230 | spin_unlock(&ir_raw_handler_lock); |
231 | |||
215 | return 0; | 232 | return 0; |
216 | } | 233 | } |
217 | EXPORT_SYMBOL(ir_raw_handler_register); | 234 | EXPORT_SYMBOL(ir_raw_handler_register); |
@@ -220,6 +237,7 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) | |||
220 | { | 237 | { |
221 | spin_lock(&ir_raw_handler_lock); | 238 | spin_lock(&ir_raw_handler_lock); |
222 | list_del(&ir_raw_handler->list); | 239 | list_del(&ir_raw_handler->list); |
240 | available_protocols &= ~ir_raw_handler->protocols; | ||
223 | spin_unlock(&ir_raw_handler_lock); | 241 | spin_unlock(&ir_raw_handler_lock); |
224 | } | 242 | } |
225 | EXPORT_SYMBOL(ir_raw_handler_unregister); | 243 | EXPORT_SYMBOL(ir_raw_handler_unregister); |