aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/IR/ir-sysfs.c')
-rw-r--r--drivers/media/IR/ir-sysfs.c202
1 files changed, 146 insertions, 56 deletions
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index e14e6c486b52..d7da63e16c92 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -1,6 +1,6 @@
1/* ir-register.c - handle IR scancode->keycode tables 1/* ir-sysfs.c - sysfs interface for RC devices (/sys/class/rc)
2 * 2 *
3 * Copyright (C) 2009 by Mauro Carvalho Chehab <mchehab@redhat.com> 3 * Copyright (C) 2009-2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
@@ -15,15 +15,23 @@
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/input.h> 16#include <linux/input.h>
17#include <linux/device.h> 17#include <linux/device.h>
18#include <media/ir-core.h> 18#include "ir-core-priv.h"
19 19
20#define IRRCV_NUM_DEVICES 256 20#define IRRCV_NUM_DEVICES 256
21 21
22/* bit array to represent IR sysfs device number */ 22/* bit array to represent IR sysfs device number */
23static unsigned long ir_core_dev_number; 23static unsigned long ir_core_dev_number;
24 24
25/* class for /sys/class/irrcv */ 25/* class for /sys/class/rc */
26static struct class *ir_input_class; 26static char *ir_devnode(struct device *dev, mode_t *mode)
27{
28 return kasprintf(GFP_KERNEL, "rc/%s", dev_name(dev));
29}
30
31static struct class ir_input_class = {
32 .name = "rc",
33 .devnode = ir_devnode,
34};
27 35
28/** 36/**
29 * show_protocol() - shows the current IR protocol 37 * show_protocol() - shows the current IR protocol
@@ -32,7 +40,7 @@ static struct class *ir_input_class;
32 * @buf: a pointer to the output buffer 40 * @buf: a pointer to the output buffer
33 * 41 *
34 * This routine is a callback routine for input read the IR protocol type. 42 * This routine is a callback routine for input read the IR protocol type.
35 * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. 43 * it is trigged by reading /sys/class/rc/rc?/current_protocol.
36 * It returns the protocol name, as understood by the driver. 44 * It returns the protocol name, as understood by the driver.
37 */ 45 */
38static ssize_t show_protocol(struct device *d, 46static ssize_t show_protocol(struct device *d,
@@ -48,13 +56,17 @@ static ssize_t show_protocol(struct device *d,
48 if (ir_type == IR_TYPE_UNKNOWN) 56 if (ir_type == IR_TYPE_UNKNOWN)
49 s = "Unknown"; 57 s = "Unknown";
50 else if (ir_type == IR_TYPE_RC5) 58 else if (ir_type == IR_TYPE_RC5)
51 s = "RC-5"; 59 s = "rc-5";
52 else if (ir_type == IR_TYPE_PD)
53 s = "Pulse/distance";
54 else if (ir_type == IR_TYPE_NEC) 60 else if (ir_type == IR_TYPE_NEC)
55 s = "NEC"; 61 s = "nec";
62 else if (ir_type == IR_TYPE_RC6)
63 s = "rc6";
64 else if (ir_type == IR_TYPE_JVC)
65 s = "jvc";
66 else if (ir_type == IR_TYPE_SONY)
67 s = "sony";
56 else 68 else
57 s = "Other"; 69 s = "other";
58 70
59 return sprintf(buf, "%s\n", s); 71 return sprintf(buf, "%s\n", s);
60} 72}
@@ -67,7 +79,7 @@ static ssize_t show_protocol(struct device *d,
67 * @len: length of the input buffer 79 * @len: length of the input buffer
68 * 80 *
69 * This routine is a callback routine for changing the IR protocol type. 81 * This routine is a callback routine for changing the IR protocol type.
70 * it is trigged by reading /sys/class/irrcv/irrcv?/current_protocol. 82 * it is trigged by reading /sys/class/rc/rc?/current_protocol.
71 * It changes the IR the protocol name, if the IR type is recognized 83 * It changes the IR the protocol name, if the IR type is recognized
72 * by the driver. 84 * by the driver.
73 * If an unknown protocol name is used, returns -EINVAL. 85 * If an unknown protocol name is used, returns -EINVAL.
@@ -78,23 +90,24 @@ static ssize_t store_protocol(struct device *d,
78 size_t len) 90 size_t len)
79{ 91{
80 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 92 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
81 u64 ir_type = IR_TYPE_UNKNOWN; 93 u64 ir_type = 0;
82 int rc = -EINVAL; 94 int rc = -EINVAL;
83 unsigned long flags; 95 unsigned long flags;
84 char *buf; 96 char *buf;
85 97
86 buf = strsep((char **) &data, "\n"); 98 while ((buf = strsep((char **) &data, " \n")) != NULL) {
87 99 if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5"))
88 if (!strcasecmp(buf, "rc-5")) 100 ir_type |= IR_TYPE_RC5;
89 ir_type = IR_TYPE_RC5; 101 if (!strcasecmp(buf, "nec"))
90 else if (!strcasecmp(buf, "pd")) 102 ir_type |= IR_TYPE_NEC;
91 ir_type = IR_TYPE_PD; 103 if (!strcasecmp(buf, "jvc"))
92 else if (!strcasecmp(buf, "nec")) 104 ir_type |= IR_TYPE_JVC;
93 ir_type = IR_TYPE_NEC; 105 if (!strcasecmp(buf, "sony"))
106 ir_type |= IR_TYPE_SONY;
107 }
94 108
95 if (ir_type == IR_TYPE_UNKNOWN) { 109 if (!ir_type) {
96 IR_dprintk(1, "Error setting protocol to %lld\n", 110 IR_dprintk(1, "Unknown protocol\n");
97 (long long)ir_type);
98 return -EINVAL; 111 return -EINVAL;
99 } 112 }
100 113
@@ -112,25 +125,87 @@ static ssize_t store_protocol(struct device *d,
112 ir_dev->rc_tab.ir_type = ir_type; 125 ir_dev->rc_tab.ir_type = ir_type;
113 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); 126 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
114 127
115 IR_dprintk(1, "Current protocol is %lld\n", 128 IR_dprintk(1, "Current protocol(s) is(are) %lld\n",
116 (long long)ir_type); 129 (long long)ir_type);
117 130
118 return len; 131 return len;
119} 132}
120 133
134static ssize_t show_supported_protocols(struct device *d,
135 struct device_attribute *mattr, char *buf)
136{
137 char *orgbuf = buf;
138 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
139
140 /* FIXME: doesn't support multiple protocols at the same time */
141 if (ir_dev->props->allowed_protos == IR_TYPE_UNKNOWN)
142 buf += sprintf(buf, "unknown ");
143 if (ir_dev->props->allowed_protos & IR_TYPE_RC5)
144 buf += sprintf(buf, "rc-5 ");
145 if (ir_dev->props->allowed_protos & IR_TYPE_NEC)
146 buf += sprintf(buf, "nec ");
147 if (buf == orgbuf)
148 buf += sprintf(buf, "other ");
149
150 buf += sprintf(buf - 1, "\n");
151
152 return buf - orgbuf;
153}
154
155#define ADD_HOTPLUG_VAR(fmt, val...) \
156 do { \
157 int err = add_uevent_var(env, fmt, val); \
158 if (err) \
159 return err; \
160 } while (0)
161
162static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
163{
164 struct ir_input_dev *ir_dev = dev_get_drvdata(device);
165
166 if (ir_dev->rc_tab.name)
167 ADD_HOTPLUG_VAR("NAME=%s", ir_dev->rc_tab.name);
168 if (ir_dev->driver_name)
169 ADD_HOTPLUG_VAR("DRV_NAME=%s", ir_dev->driver_name);
170
171 return 0;
172}
173
121/* 174/*
122 * Static device attribute struct with the sysfs attributes for IR's 175 * Static device attribute struct with the sysfs attributes for IR's
123 */ 176 */
124static DEVICE_ATTR(current_protocol, S_IRUGO | S_IWUSR, 177static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR,
125 show_protocol, store_protocol); 178 show_protocol, store_protocol);
126 179
127static struct attribute *ir_dev_attrs[] = { 180static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
128 &dev_attr_current_protocol.attr, 181 show_supported_protocols, NULL);
182
183static struct attribute *ir_hw_dev_attrs[] = {
184 &dev_attr_protocol.attr,
185 &dev_attr_supported_protocols.attr,
129 NULL, 186 NULL,
130}; 187};
131 188
189static struct attribute_group ir_hw_dev_attr_grp = {
190 .attrs = ir_hw_dev_attrs,
191};
192
193static const struct attribute_group *ir_hw_dev_attr_groups[] = {
194 &ir_hw_dev_attr_grp,
195 NULL
196};
197
198static struct device_type rc_dev_type = {
199 .groups = ir_hw_dev_attr_groups,
200 .uevent = ir_dev_uevent,
201};
202
203static struct device_type ir_raw_dev_type = {
204 .uevent = ir_dev_uevent,
205};
206
132/** 207/**
133 * ir_register_class() - creates the sysfs for /sys/class/irrcv/irrcv? 208 * ir_register_class() - creates the sysfs for /sys/class/rc/rc?
134 * @input_dev: the struct input_dev descriptor of the device 209 * @input_dev: the struct input_dev descriptor of the device
135 * 210 *
136 * This routine is used to register the syfs code for IR class 211 * This routine is used to register the syfs code for IR class
@@ -138,8 +213,7 @@ static struct attribute *ir_dev_attrs[] = {
138int ir_register_class(struct input_dev *input_dev) 213int ir_register_class(struct input_dev *input_dev)
139{ 214{
140 int rc; 215 int rc;
141 struct kobject *kobj; 216 const char *path;
142
143 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 217 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
144 int devno = find_first_zero_bit(&ir_core_dev_number, 218 int devno = find_first_zero_bit(&ir_core_dev_number,
145 IRRCV_NUM_DEVICES); 219 IRRCV_NUM_DEVICES);
@@ -147,19 +221,36 @@ int ir_register_class(struct input_dev *input_dev)
147 if (unlikely(devno < 0)) 221 if (unlikely(devno < 0))
148 return devno; 222 return devno;
149 223
150 ir_dev->attr.attrs = ir_dev_attrs; 224 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
151 ir_dev->class_dev = device_create(ir_input_class, NULL, 225 ir_dev->dev.type = &rc_dev_type;
152 input_dev->dev.devt, ir_dev, 226 else
153 "irrcv%d", devno); 227 ir_dev->dev.type = &ir_raw_dev_type;
154 kobj = &ir_dev->class_dev->kobj; 228
155 229 ir_dev->dev.class = &ir_input_class;
156 printk(KERN_WARNING "Creating IR device %s\n", kobject_name(kobj)); 230 ir_dev->dev.parent = input_dev->dev.parent;
157 rc = sysfs_create_group(kobj, &ir_dev->attr); 231 dev_set_name(&ir_dev->dev, "rc%d", devno);
158 if (unlikely(rc < 0)) { 232 dev_set_drvdata(&ir_dev->dev, ir_dev);
159 device_destroy(ir_input_class, input_dev->dev.devt); 233 rc = device_register(&ir_dev->dev);
160 return -ENOMEM; 234 if (rc)
235 return rc;
236
237
238 input_dev->dev.parent = &ir_dev->dev;
239 rc = input_register_device(input_dev);
240 if (rc < 0) {
241 device_del(&ir_dev->dev);
242 return rc;
161 } 243 }
162 244
245 __module_get(THIS_MODULE);
246
247 path = kobject_get_path(&ir_dev->dev.kobj, GFP_KERNEL);
248 printk(KERN_INFO "%s: %s as %s\n",
249 dev_name(&ir_dev->dev),
250 input_dev->name ? input_dev->name : "Unspecified device",
251 path ? path : "N/A");
252 kfree(path);
253
163 ir_dev->devno = devno; 254 ir_dev->devno = devno;
164 set_bit(devno, &ir_core_dev_number); 255 set_bit(devno, &ir_core_dev_number);
165 256
@@ -168,7 +259,7 @@ int ir_register_class(struct input_dev *input_dev)
168 259
169/** 260/**
170 * ir_unregister_class() - removes the sysfs for sysfs for 261 * ir_unregister_class() - removes the sysfs for sysfs for
171 * /sys/class/irrcv/irrcv? 262 * /sys/class/rc/rc?
172 * @input_dev: the struct input_dev descriptor of the device 263 * @input_dev: the struct input_dev descriptor of the device
173 * 264 *
174 * This routine is used to unregister the syfs code for IR class 265 * This routine is used to unregister the syfs code for IR class
@@ -176,36 +267,35 @@ int ir_register_class(struct input_dev *input_dev)
176void ir_unregister_class(struct input_dev *input_dev) 267void ir_unregister_class(struct input_dev *input_dev)
177{ 268{
178 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); 269 struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
179 struct kobject *kobj;
180 270
181 clear_bit(ir_dev->devno, &ir_core_dev_number); 271 clear_bit(ir_dev->devno, &ir_core_dev_number);
272 input_unregister_device(input_dev);
273 device_del(&ir_dev->dev);
182 274
183 kobj = &ir_dev->class_dev->kobj; 275 module_put(THIS_MODULE);
184
185 sysfs_remove_group(kobj, &ir_dev->attr);
186 device_destroy(ir_input_class, input_dev->dev.devt);
187
188 kfree(ir_dev->attr.name);
189} 276}
190 277
191/* 278/*
192 * Init/exit code for the module. Basically, creates/removes /sys/class/irrcv 279 * Init/exit code for the module. Basically, creates/removes /sys/class/rc
193 */ 280 */
194 281
195static int __init ir_core_init(void) 282static int __init ir_core_init(void)
196{ 283{
197 ir_input_class = class_create(THIS_MODULE, "irrcv"); 284 int rc = class_register(&ir_input_class);
198 if (IS_ERR(ir_input_class)) { 285 if (rc) {
199 printk(KERN_ERR "ir_core: unable to register irrcv class\n"); 286 printk(KERN_ERR "ir_core: unable to register rc class\n");
200 return PTR_ERR(ir_input_class); 287 return rc;
201 } 288 }
202 289
290 /* Initialize/load the decoders/keymap code that will be used */
291 ir_raw_init();
292
203 return 0; 293 return 0;
204} 294}
205 295
206static void __exit ir_core_exit(void) 296static void __exit ir_core_exit(void)
207{ 297{
208 class_destroy(ir_input_class); 298 class_unregister(&ir_input_class);
209} 299}
210 300
211module_init(ir_core_init); 301module_init(ir_core_init);