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.c251
1 files changed, 143 insertions, 108 deletions
diff --git a/drivers/media/IR/ir-sysfs.c b/drivers/media/IR/ir-sysfs.c
index 2098dd1488e..6273047e915 100644
--- a/drivers/media/IR/ir-sysfs.c
+++ b/drivers/media/IR/ir-sysfs.c
@@ -33,125 +33,172 @@ static struct class ir_input_class = {
33 .devnode = ir_devnode, 33 .devnode = ir_devnode,
34}; 34};
35 35
36static struct {
37 u64 type;
38 char *name;
39} proto_names[] = {
40 { IR_TYPE_UNKNOWN, "unknown" },
41 { IR_TYPE_RC5, "rc-5" },
42 { IR_TYPE_NEC, "nec" },
43 { IR_TYPE_RC6, "rc-6" },
44 { IR_TYPE_JVC, "jvc" },
45 { IR_TYPE_SONY, "sony" },
46 { IR_TYPE_LIRC, "lirc" },
47};
48
49#define PROTO_NONE "none"
50
36/** 51/**
37 * show_protocol() - shows the current IR protocol 52 * show_protocols() - shows the current IR protocol(s)
38 * @d: the device descriptor 53 * @d: the device descriptor
39 * @mattr: the device attribute struct (unused) 54 * @mattr: the device attribute struct (unused)
40 * @buf: a pointer to the output buffer 55 * @buf: a pointer to the output buffer
41 * 56 *
42 * This routine is a callback routine for input read the IR protocol type. 57 * 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. 58 * it is trigged by reading /sys/class/rc/rc?/protocols.
44 * It returns the protocol name, as understood by the driver. 59 * It returns the protocol names of supported protocols.
60 * Enabled protocols are printed in brackets.
45 */ 61 */
46static ssize_t show_protocol(struct device *d, 62static ssize_t show_protocols(struct device *d,
47 struct device_attribute *mattr, char *buf) 63 struct device_attribute *mattr, char *buf)
48{ 64{
49 char *s;
50 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 65 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
51 u64 ir_type = ir_dev->rc_tab.ir_type; 66 u64 allowed, enabled;
52 67 char *tmp = buf;
53 IR_dprintk(1, "Current protocol is %lld\n", (long long)ir_type); 68 int i;
54 69
55 /* FIXME: doesn't support multiple protocols at the same time */ 70 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
56 if (ir_type == IR_TYPE_UNKNOWN) 71 enabled = ir_dev->rc_tab.ir_type;
57 s = "Unknown"; 72 allowed = ir_dev->props->allowed_protos;
58 else if (ir_type == IR_TYPE_RC5) 73 } else {
59 s = "rc-5"; 74 enabled = ir_dev->raw->enabled_protocols;
60 else if (ir_type == IR_TYPE_NEC) 75 allowed = ir_raw_get_allowed_protocols();
61 s = "nec"; 76 }
62 else if (ir_type == IR_TYPE_RC6) 77
63 s = "rc6"; 78 IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n",
64 else if (ir_type == IR_TYPE_JVC) 79 (long long)allowed,
65 s = "jvc"; 80 (long long)enabled);
66 else if (ir_type == IR_TYPE_SONY)
67 s = "sony";
68 else
69 s = "other";
70 81
71 return sprintf(buf, "%s\n", s); 82 for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
83 if (allowed & enabled & proto_names[i].type)
84 tmp += sprintf(tmp, "[%s] ", proto_names[i].name);
85 else if (allowed & proto_names[i].type)
86 tmp += sprintf(tmp, "%s ", proto_names[i].name);
87 }
88
89 if (tmp != buf)
90 tmp--;
91 *tmp = '\n';
92 return tmp + 1 - buf;
72} 93}
73 94
74/** 95/**
75 * store_protocol() - shows the current IR protocol 96 * store_protocols() - changes the current IR protocol(s)
76 * @d: the device descriptor 97 * @d: the device descriptor
77 * @mattr: the device attribute struct (unused) 98 * @mattr: the device attribute struct (unused)
78 * @buf: a pointer to the input buffer 99 * @buf: a pointer to the input buffer
79 * @len: length of the input buffer 100 * @len: length of the input buffer
80 * 101 *
81 * This routine is a callback routine for changing the IR protocol type. 102 * This routine is a callback routine for changing the IR protocol type.
82 * it is trigged by reading /sys/class/rc/rc?/current_protocol. 103 * 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 104 * Writing "+proto" will add a protocol to the list of enabled protocols.
84 * by the driver. 105 * Writing "-proto" will remove a protocol from the list of enabled protocols.
85 * If an unknown protocol name is used, returns -EINVAL. 106 * Writing "proto" will enable only "proto".
107 * Writing "none" will disable all protocols.
108 * Returns -EINVAL if an invalid protocol combination or unknown protocol name
109 * is used, otherwise @len.
86 */ 110 */
87static ssize_t store_protocol(struct device *d, 111static ssize_t store_protocols(struct device *d,
88 struct device_attribute *mattr, 112 struct device_attribute *mattr,
89 const char *data, 113 const char *data,
90 size_t len) 114 size_t len)
91{ 115{
92 struct ir_input_dev *ir_dev = dev_get_drvdata(d); 116 struct ir_input_dev *ir_dev = dev_get_drvdata(d);
93 u64 ir_type = 0; 117 bool enable, disable;
94 int rc = -EINVAL; 118 const char *tmp;
119 u64 type;
120 u64 mask;
121 int rc, i, count = 0;
95 unsigned long flags; 122 unsigned long flags;
96 char *buf; 123
97 124 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE)
98 while ((buf = strsep((char **) &data, " \n")) != NULL) { 125 type = ir_dev->rc_tab.ir_type;
99 if (!strcasecmp(buf, "rc-5") || !strcasecmp(buf, "rc5")) 126 else
100 ir_type |= IR_TYPE_RC5; 127 type = ir_dev->raw->enabled_protocols;
101 if (!strcasecmp(buf, "nec")) 128
102 ir_type |= IR_TYPE_NEC; 129 while ((tmp = strsep((char **) &data, " \n")) != NULL) {
103 if (!strcasecmp(buf, "jvc")) 130 if (!*tmp)
104 ir_type |= IR_TYPE_JVC; 131 break;
105 if (!strcasecmp(buf, "sony")) 132
106 ir_type |= IR_TYPE_SONY; 133 if (*tmp == '+') {
134 enable = true;
135 disable = false;
136 tmp++;
137 } else if (*tmp == '-') {
138 enable = false;
139 disable = true;
140 tmp++;
141 } else {
142 enable = false;
143 disable = false;
144 }
145
146 if (!enable && !disable && !strncasecmp(tmp, PROTO_NONE, sizeof(PROTO_NONE))) {
147 tmp += sizeof(PROTO_NONE);
148 mask = 0;
149 count++;
150 } else {
151 for (i = 0; i < ARRAY_SIZE(proto_names); i++) {
152 if (!strncasecmp(tmp, proto_names[i].name, strlen(proto_names[i].name))) {
153 tmp += strlen(proto_names[i].name);
154 mask = proto_names[i].type;
155 break;
156 }
157 }
158 if (i == ARRAY_SIZE(proto_names)) {
159 IR_dprintk(1, "Unknown protocol: '%s'\n", tmp);
160 return -EINVAL;
161 }
162 count++;
163 }
164
165 if (enable)
166 type |= mask;
167 else if (disable)
168 type &= ~mask;
169 else
170 type = mask;
107 } 171 }
108 172
109 if (!ir_type) { 173 if (!count) {
110 IR_dprintk(1, "Unknown protocol\n"); 174 IR_dprintk(1, "Protocol not specified\n");
111 return -EINVAL; 175 return -EINVAL;
112 } 176 }
113 177
114 if (ir_dev->props && ir_dev->props->change_protocol) 178 if (ir_dev->props && ir_dev->props->change_protocol) {
115 rc = ir_dev->props->change_protocol(ir_dev->props->priv, 179 rc = ir_dev->props->change_protocol(ir_dev->props->priv,
116 ir_type); 180 type);
117 181 if (rc < 0) {
118 if (rc < 0) { 182 IR_dprintk(1, "Error setting protocols to 0x%llx\n",
119 IR_dprintk(1, "Error setting protocol to %lld\n", 183 (long long)type);
120 (long long)ir_type); 184 return -EINVAL;
121 return -EINVAL; 185 }
122 } 186 }
123 187
124 spin_lock_irqsave(&ir_dev->rc_tab.lock, flags); 188 if (ir_dev->props->driver_type == RC_DRIVER_SCANCODE) {
125 ir_dev->rc_tab.ir_type = ir_type; 189 spin_lock_irqsave(&ir_dev->rc_tab.lock, flags);
126 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags); 190 ir_dev->rc_tab.ir_type = type;
191 spin_unlock_irqrestore(&ir_dev->rc_tab.lock, flags);
192 } else {
193 ir_dev->raw->enabled_protocols = type;
194 }
127 195
128 IR_dprintk(1, "Current protocol(s) is(are) %lld\n", 196 IR_dprintk(1, "Current protocol(s): 0x%llx\n",
129 (long long)ir_type); 197 (long long)type);
130 198
131 return len; 199 return len;
132} 200}
133 201
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...) \ 202#define ADD_HOTPLUG_VAR(fmt, val...) \
156 do { \ 203 do { \
157 int err = add_uevent_var(env, fmt, val); \ 204 int err = add_uevent_var(env, fmt, val); \
@@ -159,7 +206,7 @@ static ssize_t show_supported_protocols(struct device *d,
159 return err; \ 206 return err; \
160 } while (0) 207 } while (0)
161 208
162static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env) 209static int rc_dev_uevent(struct device *device, struct kobj_uevent_env *env)
163{ 210{
164 struct ir_input_dev *ir_dev = dev_get_drvdata(device); 211 struct ir_input_dev *ir_dev = dev_get_drvdata(device);
165 212
@@ -174,34 +221,26 @@ static int ir_dev_uevent(struct device *device, struct kobj_uevent_env *env)
174/* 221/*
175 * Static device attribute struct with the sysfs attributes for IR's 222 * Static device attribute struct with the sysfs attributes for IR's
176 */ 223 */
177static DEVICE_ATTR(protocol, S_IRUGO | S_IWUSR, 224static DEVICE_ATTR(protocols, S_IRUGO | S_IWUSR,
178 show_protocol, store_protocol); 225 show_protocols, store_protocols);
179 226
180static DEVICE_ATTR(supported_protocols, S_IRUGO | S_IWUSR, 227static struct attribute *rc_dev_attrs[] = {
181 show_supported_protocols, NULL); 228 &dev_attr_protocols.attr,
182
183static struct attribute *ir_hw_dev_attrs[] = {
184 &dev_attr_protocol.attr,
185 &dev_attr_supported_protocols.attr,
186 NULL, 229 NULL,
187}; 230};
188 231
189static struct attribute_group ir_hw_dev_attr_grp = { 232static struct attribute_group rc_dev_attr_grp = {
190 .attrs = ir_hw_dev_attrs, 233 .attrs = rc_dev_attrs,
191}; 234};
192 235
193static const struct attribute_group *ir_hw_dev_attr_groups[] = { 236static const struct attribute_group *rc_dev_attr_groups[] = {
194 &ir_hw_dev_attr_grp, 237 &rc_dev_attr_grp,
195 NULL 238 NULL
196}; 239};
197 240
198static struct device_type rc_dev_type = { 241static struct device_type rc_dev_type = {
199 .groups = ir_hw_dev_attr_groups, 242 .groups = rc_dev_attr_groups,
200 .uevent = ir_dev_uevent, 243 .uevent = rc_dev_uevent,
201};
202
203static struct device_type ir_raw_dev_type = {
204 .uevent = ir_dev_uevent,
205}; 244};
206 245
207/** 246/**
@@ -221,11 +260,7 @@ int ir_register_class(struct input_dev *input_dev)
221 if (unlikely(devno < 0)) 260 if (unlikely(devno < 0))
222 return devno; 261 return devno;
223 262
224 if (ir_dev->props) { 263 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 264
230 ir_dev->dev.class = &ir_input_class; 265 ir_dev->dev.class = &ir_input_class;
231 ir_dev->dev.parent = input_dev->dev.parent; 266 ir_dev->dev.parent = input_dev->dev.parent;