aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/IR/ir-sysfs.c
diff options
context:
space:
mode:
authorDavid Härdeman <david@hardeman.nu>2010-06-13 16:29:31 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-08-02 13:54:27 -0400
commit667c9ebe97f7e5f1e48e7eb321644c6fb1668de5 (patch)
tree11dae4e3d480960fe697964776222b16ee0ecce8 /drivers/media/IR/ir-sysfs.c
parent0dc50942d6f23989ffb3024aa2271941ec44aea8 (diff)
V4L/DVB: ir-core: centralize sysfs raw decoder enabling/disabling
With the current logic, each raw decoder needs to add a copy of the exact same sysfs code. This is both unnecessary and also means that (re)loading an IR driver after raw decoder modules have been loaded won't work as expected. This patch moves that logic into ir-raw-event and adds a single sysfs file per device. Reading that file returns something like: "rc5 [rc6] nec jvc [sony]" (with enabled protocols in [] brackets) Writing either "+protocol" or "-protocol" to that file will enable or disable the according protocol decoder. An additional benefit is that the disabling of a decoder will be remembered across module removal/insertion so a previously disabled decoder won't suddenly be activated again. The default setting is to enable all decoders. This is also necessary for the next patch which moves even more decoder state into the central raw decoding structs. Signed-off-by: David Härdeman <david@hardeman.nu> Acked-by: Jarod Wilson <jarod@redhat.com> Tested-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/IR/ir-sysfs.c')
-rw-r--r--drivers/media/IR/ir-sysfs.c252
1 files changed, 148 insertions, 104 deletions
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 2098dd1488e0..005621d067f0 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -34,122 +34,178 @@ static struct class ir_input_class = {
34}; 34};
35 35
36/** 36/**
37 * show_protocol() - shows the current IR protocol 37 * show_protocols() - shows the current IR protocol(s)
38 * @d: the device descriptor 38 * @d: the device descriptor
39 * @mattr: the device attribute struct (unused) 39 * @mattr: the device attribute struct (unused)
40 * @buf: a pointer to the output buffer 40 * @buf: a pointer to the output buffer
41 * 41 *
42 * 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(s).
43 * it is trigged by reading /sys/class/rc/rc?/current_protocol. 43 * it is trigged by reading /sys/class/rc/rc?/protocols.
44 * It returns the protocol name, as understood by the driver. 44 * It returns the protocol names of supported protocols.
45 * Enabled protocols are printed in brackets.
45 */ 46 */
46static ssize_t show_protocol(struct device *d, 47static ssize_t show_protocols(struct device *d,
47 struct device_attribute *mattr, char *buf) 48 struct device_attribute *mattr, char *buf)
48{ 49{
49 char *s;
50 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 50 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
51 u64 ir_type = ir_dev->rc_tab.ir_type; 51 u64 allowed, enabled;
52 52 char *tmp = buf;
53 IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); 53
54 54 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
55 /* FIXME: doesn't support multiple protocols at the same time */ 55 enabled = ir_dev->rc_tab.ir_type;
56 if (ir_type == IR_TYPE_UNKNOWN) 56 allowed = ir_dev->props->allowed_protos;
57 s = "Unknown"; 57 } else {
58 else if (ir_type == IR_TYPE_RC5) 58 enabled = ir_dev->raw->enabled_protocols;
59 s = "rc-5"; 59 allowed = ir_raw_get_allowed_protocols();
60 else if (ir_type == IR_TYPE_NEC) 60 }
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";
68 else
69 s = "other";
70 61
71 return sprintf(buf, "%s\n", s); 62 IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
63 (long long)allowed,
64 (long long)enabled);
65
66 if (allowed & enabled & IR_TYPE_UNKNOWN)
67 tmp += sprintf(tmp, "[unknown] ");
68 else if (allowed & IR_TYPE_UNKNOWN)
69 tmp += sprintf(tmp, "unknown ");
70
71 if (allowed & enabled & IR_TYPE_RC5)
72 tmp += sprintf(tmp, "[rc5] ");
73 else if (allowed & IR_TYPE_RC5)
74 tmp += sprintf(tmp, "rc5 ");
75
76 if (allowed & enabled & IR_TYPE_NEC)
77 tmp += sprintf(tmp, "[nec] ");
78 else if (allowed & IR_TYPE_NEC)
79 tmp += sprintf(tmp, "nec ");
80
81 if (allowed & enabled & IR_TYPE_RC6)
82 tmp += sprintf(tmp, "[rc6] ");
83 else if (allowed & IR_TYPE_RC6)
84 tmp += sprintf(tmp, "rc6 ");
85
86 if (allowed & enabled & IR_TYPE_JVC)
87 tmp += sprintf(tmp, "[jvc] ");
88 else if (allowed & IR_TYPE_JVC)
89 tmp += sprintf(tmp, "jvc ");
90
91 if (allowed & enabled & IR_TYPE_SONY)
92 tmp += sprintf(tmp, "[sony] ");
93 else if (allowed & IR_TYPE_SONY)
94 tmp += sprintf(tmp, "sony ");
95
96 if (tmp != buf)
97 tmp--;
98 *tmp = '\n';
99 return tmp + 1 - buf;
72} 100}
73 101
74/** 102/**
75 * store_protocol() - shows the current IR protocol 103 * store_protocols() - changes the current IR protocol(s)
76 * @d: the device descriptor 104 * @d: the device descriptor
77 * @mattr: the device attribute struct (unused) 105 * @mattr: the device attribute struct (unused)
78 * @buf: a pointer to the input buffer 106 * @buf: a pointer to the input buffer
79 * @len: length of the input buffer 107 * @len: length of the input buffer
80 * 108 *
81 * This routine is a callback routine for changing the IR protocol type. 109 * This routine is a callback routine for changing the IR protocol type.
82 * it is trigged by reading /sys/class/rc/rc?/current_protocol. 110 * It is trigged by writing to /sys/class/rc/rc?/protocols.
83 * It changes the IR the protocol name, if the IR type is recognized 111 * Writing "+proto" will add a protocol to the list of enabled protocols.
84 * by the driver. 112 * Writing "-proto" will remove a protocol from the list of enabled protocols.
85 * If an unknown protocol name is used, returns -EINVAL. 113 * Writing "proto" will enable only "proto".
114 * Returns -EINVAL if an invalid protocol combination or unknown protocol name
115 * is used, otherwise @len.
86 */ 116 */
87static ssize_t store_protocol(struct device *d, 117static ssize_t store_protocols(struct device *d,
88 struct device_attribute *mattr, 118 struct device_attribute *mattr,
89 const char *data, 119 const char *data,
90 size_t len) 120 size_t len)
91{ 121{
92 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 122 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
93 u64 ir_type = 0; 123 bool enable, disable;
94 int rc = -EINVAL; 124 const char *tmp;
125 u64 type;
126 u64 mask;
127 int rc;
95 unsigned long flags; 128 unsigned long flags;
96 char *buf; 129
97 130 tmp = skip_spaces(data);
98 while ((buf = strsep((char **) &data, " \n")) != NULL) { 131
99 if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) 132 if (*tmp == '+') {
100 ir_type |= IR_TYPE_RC5; 133 enable = true;
101 if (!strcasecmp(buf, "nec")) 134 disable = false;
102 ir_type |= IR_TYPE_NEC; 135 tmp++;
103 if (!strcasecmp(buf, "jvc")) 136 } else if (*tmp == '-') {
104 ir_type |= IR_TYPE_JVC; 137 enable = false;
105 if (!strcasecmp(buf, "sony")) 138 disable = true;
106 ir_type |= IR_TYPE_SONY; 139 tmp++;
140 } else {
141 enable = false;
142 disable = false;
107 } 143 }
108 144
109 if (!ir_type) { 145 if (!strncasecmp(tmp, "unknown", 7)) {
146 tmp += 7;
147 mask = IR_TYPE_UNKNOWN;
148 } else if (!strncasecmp(tmp, "rc5", 3)) {
149 tmp += 3;
150 mask = IR_TYPE_RC5;
151 } else if (!strncasecmp(tmp, "nec", 3)) {
152 tmp += 3;
153 mask = IR_TYPE_NEC;
154 } else if (!strncasecmp(tmp, "rc6", 3)) {
155 tmp += 3;
156 mask = IR_TYPE_RC6;
157 } else if (!strncasecmp(tmp, "jvc", 3)) {
158 tmp += 3;
159 mask = IR_TYPE_JVC;
160 } else if (!strncasecmp(tmp, "sony", 4)) {
161 tmp += 4;
162 mask = IR_TYPE_SONY;
163 } else {
110 IR_dprintk(1, "Unknown protocol\n"); 164 IR_dprintk(1, "Unknown protocol\n");
111 return -EINVAL; 165 return -EINVAL;
112 } 166 }
113 167
114 if (ir_dev->props && ir_dev->props->change_protocol) 168 tmp = skip_spaces(tmp);
115 rc = ir_dev->props->change_protocol(ir_dev->props->priv, 169 if (*tmp != '\0') {
116 ir_type); 170 IR_dprintk(1, "Invalid trailing characters\n");
117
118 if (rc < 0) {
119 IR_dprintk(1, "Error setting protocol to %lld\n",
120 (long long)ir_type);
121 return -EINVAL; 171 return -EINVAL;
122 } 172 }
123 173
124 spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); 174 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
125 ir_dev->rc_tab.ir_type = ir_type; 175 type = ir_dev->rc_tab.ir_type;
126 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); 176 else
177 type = ir_dev->raw->enabled_protocols;
127 178
128 IR_dprintk(1, "Current protocol(s) is(are) %lld\n", 179 if (enable)
129 (long long)ir_type); 180 type |= mask;
181 else if (disable)
182 type &= ~mask;
183 else
184 type = mask;
130 185
131 return len; 186 if (ir_dev->props && ir_dev->props->change_protocol) {
132} 187 rc = ir_dev->props->change_protocol(ir_dev->props->priv,
188 type);
189 if (rc < 0) {
190 IR_dprintk(1, "Error setting protocols to 0x%llx\n",
191 (long long)type);
192 return -EINVAL;
193 }
194 }
133 195
134static ssize_t show_supported_protocols(struct device *d, 196 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
135 struct device_attribute *mattr, char *buf) 197 spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
136{ 198 ir_dev->rc_tab.ir_type = type;
137 char *orgbuf = buf; 199 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
138 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 200 } else {
201 ir_dev->raw->enabled_protocols = type;
202 }
139 203
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 204
150 buf += sprintf(buf - 1, "\n"); 205 IR_dprintk(1, "Current protocol(s): 0x%llx\n",
206 (long long)type);
151 207
152 return buf - orgbuf; 208 return len;
153} 209}
154 210
155#define ADD_HOTPLUG_VAR(fmt, val...) \ 211#define ADD_HOTPLUG_VAR(fmt, val...) \
@@ -159,7 +215,7 @@ static ssize_t show_supported_protocols(struct device *d,
159 return err; \ 215 return err; \
160 } while (0) 216 } while (0)
161 217
162static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) 218static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
163{ 219{
164 struct ir_input_dev *ir_dev = dev_get_drvdata(device); 220 struct ir_input_dev *ir_dev = dev_get_drvdata(device);
165 221
@@ -174,34 +230,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
174/* 230/*
175 * Static device attribute struct with the sysfs attributes for IR's 231 * Static device attribute struct with the sysfs attributes for IR's
176 */ 232 */
177static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, 233static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
178 show_protocol, store_protocol); 234 show_protocols, store_protocols);
179
180static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR,
181 show_supported_protocols, NULL);
182 235
183static struct attribute *ir_hw_dev_attrs[] = { 236static struct attribute *rc_dev_attrs[] = {
184 &dev_attr_protocol.attr, 237 &dev_attr_protocols.attr,
185 &dev_attr_supported_protocols.attr,
186 NULL, 238 NULL,
187}; 239};
188 240
189static struct attribute_group ir_hw_dev_attr_grp = { 241static struct attribute_group rc_dev_attr_grp = {
190 .attrs = ir_hw_dev_attrs, 242 .attrs = rc_dev_attrs,
191}; 243};
192 244
193static const struct attribute_group *ir_hw_dev_attr_groups[] = { 245static const struct attribute_group *rc_dev_attr_groups[] = {
194 &ir_hw_dev_attr_grp, 246 &rc_dev_attr_grp,
195 NULL 247 NULL
196}; 248};
197 249
198static struct device_type rc_dev_type = { 250static struct device_type rc_dev_type = {
199 .groups = ir_hw_dev_attr_groups, 251 .groups = rc_dev_attr_groups,
200 .uevent = ir_dev_uevent, 252 .uevent = rc_dev_uevent,
201};
202
203static struct device_type ir_raw_dev_type = {
204 .uevent = ir_dev_uevent,
205}; 253};
206 254
207/** 255/**
@@ -221,11 +269,7 @@ int ir_register_class(struct input_dev *input_dev)
221 if (unlikely(devno < 0)) 269 if (unlikely(devno < 0))
222 return devno; 270 return devno;
223 271
224 if (ir_dev->props) { 272 ir_dev->dev.type = &rc_dev_type;
225 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
226 ir_dev->dev.type = &rc_dev_type;
227 } else
228 ir_dev->dev.type = &ir_raw_dev_type;
229 273
230 ir_dev->dev.class = &ir_input_class; 274 ir_dev->dev.class = &ir_input_class;
231 ir_dev->dev.parent = input_dev->dev.parent; 275 ir_dev->dev.parent = input_dev->dev.parent;