diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-03-25 22:49:46 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-05-17 23:53:01 -0400 |
commit | 20d5f116ec777c9c7ce5b74f0d17ee1d01a0d833 (patch) | |
tree | b25e179adb667c18e14dbd7088c3a850150f0c68 /drivers | |
parent | 93c312ff21b0a53e701a45741887208297646a1a (diff) |
V4L/DVB: ir-nec-decoder: Add sysfs node to enable/disable per irrcv
With the help of raw_register/raw_unregister, adds a sysfs group
associated with the decoder, inside the corresponding irrcv node.
Writing 1 to nec_decoder/enabled enables the decoder, while
writing 0 disables it.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/IR/ir-nec-decoder.c | 133 | ||||
-rw-r--r-- | drivers/media/IR/ir-raw-event.c | 2 |
2 files changed, 133 insertions, 2 deletions
diff --git a/drivers/media/IR/ir-nec-decoder.c b/drivers/media/IR/ir-nec-decoder.c index cb57cc287734..83a9912722f4 100644 --- a/drivers/media/IR/ir-nec-decoder.c +++ b/drivers/media/IR/ir-nec-decoder.c | |||
@@ -39,6 +39,85 @@ | |||
39 | 39 | ||
40 | #define REPEAT_TIME 240 /* ms */ | 40 | #define REPEAT_TIME 240 /* ms */ |
41 | 41 | ||
42 | /* Used to register nec_decoder clients */ | ||
43 | static LIST_HEAD(decoder_list); | ||
44 | static spinlock_t decoder_lock; | ||
45 | |||
46 | struct decoder_data { | ||
47 | struct list_head list; | ||
48 | struct ir_input_dev *ir_dev; | ||
49 | int enabled:1; | ||
50 | }; | ||
51 | |||
52 | |||
53 | /** | ||
54 | * get_decoder_data() - gets decoder data | ||
55 | * @input_dev: input device | ||
56 | * | ||
57 | * Returns the struct decoder_data that corresponds to a device | ||
58 | */ | ||
59 | |||
60 | static struct decoder_data *get_decoder_data(struct ir_input_dev *ir_dev) | ||
61 | { | ||
62 | struct decoder_data *data = NULL; | ||
63 | |||
64 | spin_lock(&decoder_lock); | ||
65 | list_for_each_entry(data, &decoder_list, list) { | ||
66 | if (data->ir_dev == ir_dev) | ||
67 | break; | ||
68 | } | ||
69 | spin_unlock(&decoder_lock); | ||
70 | return data; | ||
71 | } | ||
72 | |||
73 | static ssize_t store_enabled(struct device *d, | ||
74 | struct device_attribute *mattr, | ||
75 | const char *buf, | ||
76 | size_t len) | ||
77 | { | ||
78 | unsigned long value; | ||
79 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
80 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
81 | |||
82 | if (!data) | ||
83 | return -EINVAL; | ||
84 | |||
85 | if (strict_strtoul(buf, 10, &value) || value > 1) | ||
86 | return -EINVAL; | ||
87 | |||
88 | data->enabled = value; | ||
89 | |||
90 | return len; | ||
91 | } | ||
92 | |||
93 | static ssize_t show_enabled(struct device *d, | ||
94 | struct device_attribute *mattr, char *buf) | ||
95 | { | ||
96 | struct ir_input_dev *ir_dev = dev_get_drvdata(d); | ||
97 | struct decoder_data *data = get_decoder_data(ir_dev); | ||
98 | |||
99 | if (!data) | ||
100 | return -EINVAL; | ||
101 | |||
102 | if (data->enabled) | ||
103 | return sprintf(buf, "1\n"); | ||
104 | else | ||
105 | return sprintf(buf, "0\n"); | ||
106 | } | ||
107 | |||
108 | static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, show_enabled, store_enabled); | ||
109 | |||
110 | static struct attribute *decoder_attributes[] = { | ||
111 | &dev_attr_enabled.attr, | ||
112 | NULL | ||
113 | }; | ||
114 | |||
115 | static struct attribute_group decoder_attribute_group = { | ||
116 | .name = "nec_decoder", | ||
117 | .attrs = decoder_attributes, | ||
118 | }; | ||
119 | |||
120 | |||
42 | /** is_repeat - Check if it is a NEC repeat event | 121 | /** is_repeat - Check if it is a NEC repeat event |
43 | * @input_dev: the struct input_dev descriptor of the device | 122 | * @input_dev: the struct input_dev descriptor of the device |
44 | * @pos: the position of the first event | 123 | * @pos: the position of the first event |
@@ -184,9 +263,15 @@ static int ir_nec_decode(struct input_dev *input_dev, | |||
184 | struct ir_raw_event *evs, | 263 | struct ir_raw_event *evs, |
185 | int len) | 264 | int len) |
186 | { | 265 | { |
266 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
267 | struct decoder_data *data; | ||
187 | int pos = 0; | 268 | int pos = 0; |
188 | int rc = 0; | 269 | int rc = 0; |
189 | 270 | ||
271 | data = get_decoder_data(ir_dev); | ||
272 | if (!data || !data->enabled) | ||
273 | return 0; | ||
274 | |||
190 | while (pos < len) { | 275 | while (pos < len) { |
191 | if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) | 276 | if (__ir_nec_decode(input_dev, evs, len, &pos) > 0) |
192 | rc++; | 277 | rc++; |
@@ -194,8 +279,54 @@ static int ir_nec_decode(struct input_dev *input_dev, | |||
194 | return rc; | 279 | return rc; |
195 | } | 280 | } |
196 | 281 | ||
282 | static int ir_nec_register(struct input_dev *input_dev) | ||
283 | { | ||
284 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
285 | struct decoder_data *data; | ||
286 | int rc; | ||
287 | |||
288 | rc = sysfs_create_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
289 | if (rc < 0) | ||
290 | return rc; | ||
291 | |||
292 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
293 | if (!data) { | ||
294 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
295 | return -ENOMEM; | ||
296 | } | ||
297 | |||
298 | data->ir_dev = ir_dev; | ||
299 | data->enabled = 1; | ||
300 | |||
301 | spin_lock(&decoder_lock); | ||
302 | list_add_tail(&data->list, &decoder_list); | ||
303 | spin_unlock(&decoder_lock); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static int ir_nec_unregister(struct input_dev *input_dev) | ||
309 | { | ||
310 | struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); | ||
311 | static struct decoder_data *data; | ||
312 | |||
313 | data = get_decoder_data(ir_dev); | ||
314 | if (!data) | ||
315 | return 0; | ||
316 | |||
317 | sysfs_remove_group(&ir_dev->dev.kobj, &decoder_attribute_group); | ||
318 | |||
319 | spin_lock(&decoder_lock); | ||
320 | list_del(&data->list); | ||
321 | spin_unlock(&decoder_lock); | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
197 | static struct ir_raw_handler nec_handler = { | 326 | static struct ir_raw_handler nec_handler = { |
198 | .decode = ir_nec_decode, | 327 | .decode = ir_nec_decode, |
328 | .raw_register = ir_nec_register, | ||
329 | .raw_unregister = ir_nec_unregister, | ||
199 | }; | 330 | }; |
200 | 331 | ||
201 | static int __init ir_nec_decode_init(void) | 332 | static int __init ir_nec_decode_init(void) |
diff --git a/drivers/media/IR/ir-raw-event.c b/drivers/media/IR/ir-raw-event.c index 11f23f4491b2..371d88e5a586 100644 --- a/drivers/media/IR/ir-raw-event.c +++ b/drivers/media/IR/ir-raw-event.c | |||
@@ -223,7 +223,7 @@ static void init_decoders(struct work_struct *work) | |||
223 | void ir_raw_init(void) | 223 | void ir_raw_init(void) |
224 | { | 224 | { |
225 | spin_lock_init(&ir_raw_handler_lock); | 225 | spin_lock_init(&ir_raw_handler_lock); |
226 | 226 | ||
227 | #ifdef MODULE | 227 | #ifdef MODULE |
228 | INIT_WORK(&wq_load, init_decoders); | 228 | INIT_WORK(&wq_load, init_decoders); |
229 | schedule_work(&wq_load); | 229 | schedule_work(&wq_load); |