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.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;