aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/sysfs.c')
-rw-r--r--drivers/usb/core/sysfs.c319
1 files changed, 268 insertions, 51 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 00297f113849..edd83e014452 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -22,9 +22,207 @@
22 22
23#include "usb.h" 23#include "usb.h"
24 24
25/* endpoint stuff */
26struct ep_object {
27 struct usb_endpoint_descriptor *desc;
28 struct usb_device *udev;
29 struct kobject kobj;
30};
31#define to_ep_object(_kobj) \
32 container_of(_kobj, struct ep_object, kobj)
33
34struct ep_attribute {
35 struct attribute attr;
36 ssize_t (*show)(struct usb_device *,
37 struct usb_endpoint_descriptor *, char *);
38};
39#define to_ep_attribute(_attr) \
40 container_of(_attr, struct ep_attribute, attr)
41
42#define EP_ATTR(_name) \
43struct ep_attribute ep_##_name = { \
44 .attr = {.name = #_name, .owner = THIS_MODULE, \
45 .mode = S_IRUGO}, \
46 .show = show_ep_##_name}
47
48#define usb_ep_attr(field, format_string) \
49static ssize_t show_ep_##field(struct usb_device *udev, \
50 struct usb_endpoint_descriptor *desc, \
51 char *buf) \
52{ \
53 return sprintf(buf, format_string, desc->field); \
54} \
55static EP_ATTR(field);
56
57usb_ep_attr(bLength, "%02x\n")
58usb_ep_attr(bEndpointAddress, "%02x\n")
59usb_ep_attr(bmAttributes, "%02x\n")
60usb_ep_attr(bInterval, "%02x\n")
61
62static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
63 struct usb_endpoint_descriptor *desc, char *buf)
64{
65 return sprintf(buf, "%04x\n",
66 le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
67}
68static EP_ATTR(wMaxPacketSize);
69
70static ssize_t show_ep_type(struct usb_device *udev,
71 struct usb_endpoint_descriptor *desc, char *buf)
72{
73 char *type = "unknown";
74
75 switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
76 case USB_ENDPOINT_XFER_CONTROL:
77 type = "Control";
78 break;
79 case USB_ENDPOINT_XFER_ISOC:
80 type = "Isoc";
81 break;
82 case USB_ENDPOINT_XFER_BULK:
83 type = "Bulk";
84 break;
85 case USB_ENDPOINT_XFER_INT:
86 type = "Interrupt";
87 break;
88 }
89 return sprintf(buf, "%s\n", type);
90}
91static EP_ATTR(type);
92
93static ssize_t show_ep_interval(struct usb_device *udev,
94 struct usb_endpoint_descriptor *desc, char *buf)
95{
96 char unit;
97 unsigned interval = 0;
98 unsigned in;
99
100 in = (desc->bEndpointAddress & USB_DIR_IN);
101
102 switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
103 case USB_ENDPOINT_XFER_CONTROL:
104 if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
105 interval = desc->bInterval;
106 break;
107 case USB_ENDPOINT_XFER_ISOC:
108 interval = 1 << (desc->bInterval - 1);
109 break;
110 case USB_ENDPOINT_XFER_BULK:
111 if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
112 interval = desc->bInterval;
113 break;
114 case USB_ENDPOINT_XFER_INT:
115 if (udev->speed == USB_SPEED_HIGH)
116 interval = 1 << (desc->bInterval - 1);
117 else
118 interval = desc->bInterval;
119 break;
120 }
121 interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
122 if (interval % 1000)
123 unit = 'u';
124 else {
125 unit = 'm';
126 interval /= 1000;
127 }
128
129 return sprintf(buf, "%d%cs\n", interval, unit);
130}
131static EP_ATTR(interval);
132
133static ssize_t show_ep_direction(struct usb_device *udev,
134 struct usb_endpoint_descriptor *desc, char *buf)
135{
136 char *direction;
137
138 if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
139 USB_ENDPOINT_XFER_CONTROL)
140 direction = "both";
141 else if (desc->bEndpointAddress & USB_DIR_IN)
142 direction = "in";
143 else
144 direction = "out";
145 return sprintf(buf, "%s\n", direction);
146}
147static EP_ATTR(direction);
148
149static struct attribute *ep_attrs[] = {
150 &ep_bLength.attr,
151 &ep_bEndpointAddress.attr,
152 &ep_bmAttributes.attr,
153 &ep_bInterval.attr,
154 &ep_wMaxPacketSize.attr,
155 &ep_type.attr,
156 &ep_interval.attr,
157 &ep_direction.attr,
158 NULL,
159};
160
161static void ep_object_release(struct kobject *kobj)
162{
163 kfree(to_ep_object(kobj));
164}
165
166static ssize_t ep_object_show(struct kobject *kobj, struct attribute *attr,
167 char *buf)
168{
169 struct ep_object *ep_obj = to_ep_object(kobj);
170 struct ep_attribute *ep_attr = to_ep_attribute(attr);
171
172 return (ep_attr->show)(ep_obj->udev, ep_obj->desc, buf);
173}
174
175static struct sysfs_ops ep_object_sysfs_ops = {
176 .show = ep_object_show,
177};
178
179static struct kobj_type ep_object_ktype = {
180 .release = ep_object_release,
181 .sysfs_ops = &ep_object_sysfs_ops,
182 .default_attrs = ep_attrs,
183};
184
185static void usb_create_ep_files(struct kobject *parent,
186 struct usb_host_endpoint *endpoint,
187 struct usb_device *udev)
188{
189 struct ep_object *ep_obj;
190 struct kobject *kobj;
191
192 ep_obj = kzalloc(sizeof(struct ep_object), GFP_KERNEL);
193 if (!ep_obj)
194 return;
195
196 ep_obj->desc = &endpoint->desc;
197 ep_obj->udev = udev;
198
199 kobj = &ep_obj->kobj;
200 kobject_set_name(kobj, "ep_%02x", endpoint->desc.bEndpointAddress);
201 kobj->parent = parent;
202 kobj->ktype = &ep_object_ktype;
203
204 /* Don't use kobject_register, because it generates a hotplug event */
205 kobject_init(kobj);
206 if (kobject_add(kobj) == 0)
207 endpoint->kobj = kobj;
208 else
209 kobject_put(kobj);
210}
211
212static void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
213{
214
215 if (endpoint->kobj) {
216 kobject_del(endpoint->kobj);
217 kobject_put(endpoint->kobj);
218 endpoint->kobj = NULL;
219 }
220}
221
25/* Active configuration fields */ 222/* Active configuration fields */
26#define usb_actconfig_show(field, multiplier, format_string) \ 223#define usb_actconfig_show(field, multiplier, format_string) \
27static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ 224static ssize_t show_##field (struct device *dev, \
225 struct device_attribute *attr, char *buf) \
28{ \ 226{ \
29 struct usb_device *udev; \ 227 struct usb_device *udev; \
30 struct usb_host_config *actconfig; \ 228 struct usb_host_config *actconfig; \
@@ -46,22 +244,17 @@ usb_actconfig_attr (bNumInterfaces, 1, "%2d\n")
46usb_actconfig_attr (bmAttributes, 1, "%2x\n") 244usb_actconfig_attr (bmAttributes, 1, "%2x\n")
47usb_actconfig_attr (bMaxPower, 2, "%3dmA\n") 245usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
48 246
49static ssize_t show_configuration_string(struct device *dev, struct device_attribute *attr, char *buf) 247static ssize_t show_configuration_string(struct device *dev,
248 struct device_attribute *attr, char *buf)
50{ 249{
51 struct usb_device *udev; 250 struct usb_device *udev;
52 struct usb_host_config *actconfig; 251 struct usb_host_config *actconfig;
53 int len;
54 252
55 udev = to_usb_device (dev); 253 udev = to_usb_device (dev);
56 actconfig = udev->actconfig; 254 actconfig = udev->actconfig;
57 if ((!actconfig) || (!actconfig->string)) 255 if ((!actconfig) || (!actconfig->string))
58 return 0; 256 return 0;
59 len = sprintf(buf, actconfig->string, PAGE_SIZE); 257 return sprintf(buf, "%s\n", actconfig->string);
60 if (len < 0)
61 return 0;
62 buf[len] = '\n';
63 buf[len+1] = 0;
64 return len+1;
65} 258}
66static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL); 259static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
67 260
@@ -69,7 +262,8 @@ static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
69usb_actconfig_show(bConfigurationValue, 1, "%u\n"); 262usb_actconfig_show(bConfigurationValue, 1, "%u\n");
70 263
71static ssize_t 264static ssize_t
72set_bConfigurationValue (struct device *dev, struct device_attribute *attr, const char *buf, size_t count) 265set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
266 const char *buf, size_t count)
73{ 267{
74 struct usb_device *udev = udev = to_usb_device (dev); 268 struct usb_device *udev = udev = to_usb_device (dev);
75 int config, value; 269 int config, value;
@@ -87,18 +281,13 @@ static DEVICE_ATTR(bConfigurationValue, S_IRUGO | S_IWUSR,
87 281
88/* String fields */ 282/* String fields */
89#define usb_string_attr(name) \ 283#define usb_string_attr(name) \
90static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 284static ssize_t show_##name(struct device *dev, \
285 struct device_attribute *attr, char *buf) \
91{ \ 286{ \
92 struct usb_device *udev; \ 287 struct usb_device *udev; \
93 int len; \
94 \ 288 \
95 udev = to_usb_device (dev); \ 289 udev = to_usb_device (dev); \
96 len = snprintf(buf, 256, "%s", udev->name); \ 290 return sprintf(buf, "%s\n", udev->name); \
97 if (len < 0) \
98 return 0; \
99 buf[len] = '\n'; \
100 buf[len+1] = 0; \
101 return len+1; \
102} \ 291} \
103static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); 292static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
104 293
@@ -167,7 +356,8 @@ static DEVICE_ATTR(maxchild, S_IRUGO, show_maxchild, NULL);
167/* Descriptor fields */ 356/* Descriptor fields */
168#define usb_descriptor_attr_le16(field, format_string) \ 357#define usb_descriptor_attr_le16(field, format_string) \
169static ssize_t \ 358static ssize_t \
170show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ 359show_##field (struct device *dev, struct device_attribute *attr, \
360 char *buf) \
171{ \ 361{ \
172 struct usb_device *udev; \ 362 struct usb_device *udev; \
173 \ 363 \
@@ -183,7 +373,8 @@ usb_descriptor_attr_le16(bcdDevice, "%04x\n")
183 373
184#define usb_descriptor_attr(field, format_string) \ 374#define usb_descriptor_attr(field, format_string) \
185static ssize_t \ 375static ssize_t \
186show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ 376show_##field (struct device *dev, struct device_attribute *attr, \
377 char *buf) \
187{ \ 378{ \
188 struct usb_device *udev; \ 379 struct usb_device *udev; \
189 \ 380 \
@@ -236,19 +427,21 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
236 if (udev->serial) 427 if (udev->serial)
237 device_create_file (dev, &dev_attr_serial); 428 device_create_file (dev, &dev_attr_serial);
238 device_create_file (dev, &dev_attr_configuration); 429 device_create_file (dev, &dev_attr_configuration);
430 usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
239} 431}
240 432
241void usb_remove_sysfs_dev_files (struct usb_device *udev) 433void usb_remove_sysfs_dev_files (struct usb_device *udev)
242{ 434{
243 struct device *dev = &udev->dev; 435 struct device *dev = &udev->dev;
244 436
437 usb_remove_ep_files(&udev->ep0);
245 sysfs_remove_group(&dev->kobj, &dev_attr_grp); 438 sysfs_remove_group(&dev->kobj, &dev_attr_grp);
246 439
247 if (udev->descriptor.iManufacturer) 440 if (udev->manufacturer)
248 device_remove_file(dev, &dev_attr_manufacturer); 441 device_remove_file(dev, &dev_attr_manufacturer);
249 if (udev->descriptor.iProduct) 442 if (udev->product)
250 device_remove_file(dev, &dev_attr_product); 443 device_remove_file(dev, &dev_attr_product);
251 if (udev->descriptor.iSerialNumber) 444 if (udev->serial)
252 device_remove_file(dev, &dev_attr_serial); 445 device_remove_file(dev, &dev_attr_serial);
253 device_remove_file (dev, &dev_attr_configuration); 446 device_remove_file (dev, &dev_attr_configuration);
254} 447}
@@ -256,11 +449,13 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
256/* Interface fields */ 449/* Interface fields */
257#define usb_intf_attr(field, format_string) \ 450#define usb_intf_attr(field, format_string) \
258static ssize_t \ 451static ssize_t \
259show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ 452show_##field (struct device *dev, struct device_attribute *attr, \
453 char *buf) \
260{ \ 454{ \
261 struct usb_interface *intf = to_usb_interface (dev); \ 455 struct usb_interface *intf = to_usb_interface (dev); \
262 \ 456 \
263 return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \ 457 return sprintf (buf, format_string, \
458 intf->cur_altsetting->desc.field); \
264} \ 459} \
265static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 460static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
266 461
@@ -271,7 +466,8 @@ usb_intf_attr (bInterfaceClass, "%02x\n")
271usb_intf_attr (bInterfaceSubClass, "%02x\n") 466usb_intf_attr (bInterfaceSubClass, "%02x\n")
272usb_intf_attr (bInterfaceProtocol, "%02x\n") 467usb_intf_attr (bInterfaceProtocol, "%02x\n")
273 468
274static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf) 469static ssize_t show_interface_string(struct device *dev,
470 struct device_attribute *attr, char *buf)
275{ 471{
276 struct usb_interface *intf; 472 struct usb_interface *intf;
277 struct usb_device *udev; 473 struct usb_device *udev;
@@ -288,34 +484,28 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute
288} 484}
289static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); 485static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
290 486
291static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf) 487static ssize_t show_modalias(struct device *dev,
488 struct device_attribute *attr, char *buf)
292{ 489{
293 struct usb_interface *intf; 490 struct usb_interface *intf;
294 struct usb_device *udev; 491 struct usb_device *udev;
295 int len; 492 struct usb_host_interface *alt;
296 493
297 intf = to_usb_interface(dev); 494 intf = to_usb_interface(dev);
298 udev = interface_to_usbdev(intf); 495 udev = interface_to_usbdev(intf);
299 496 alt = intf->cur_altsetting;
300 len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic", 497
301 le16_to_cpu(udev->descriptor.idVendor), 498 return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02X"
302 le16_to_cpu(udev->descriptor.idProduct), 499 "ic%02Xisc%02Xip%02X\n",
303 le16_to_cpu(udev->descriptor.bcdDevice), 500 le16_to_cpu(udev->descriptor.idVendor),
304 udev->descriptor.bDeviceClass, 501 le16_to_cpu(udev->descriptor.idProduct),
305 udev->descriptor.bDeviceSubClass, 502 le16_to_cpu(udev->descriptor.bcdDevice),
306 udev->descriptor.bDeviceProtocol); 503 udev->descriptor.bDeviceClass,
307 buf += len; 504 udev->descriptor.bDeviceSubClass,
308 505 udev->descriptor.bDeviceProtocol,
309 if (udev->descriptor.bDeviceClass == 0) { 506 alt->desc.bInterfaceClass,
310 struct usb_host_interface *alt = intf->cur_altsetting; 507 alt->desc.bInterfaceSubClass,
311 508 alt->desc.bInterfaceProtocol);
312 return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
313 alt->desc.bInterfaceClass,
314 alt->desc.bInterfaceSubClass,
315 alt->desc.bInterfaceProtocol);
316 } else {
317 return len + sprintf(buf, "*isc*ip*\n");
318 }
319} 509}
320static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); 510static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
321 511
@@ -333,20 +523,47 @@ static struct attribute_group intf_attr_grp = {
333 .attrs = intf_attrs, 523 .attrs = intf_attrs,
334}; 524};
335 525
526static inline void usb_create_intf_ep_files(struct usb_interface *intf,
527 struct usb_device *udev)
528{
529 struct usb_host_interface *iface_desc;
530 int i;
531
532 iface_desc = intf->cur_altsetting;
533 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
534 usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
535 udev);
536}
537
538static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
539{
540 struct usb_host_interface *iface_desc;
541 int i;
542
543 iface_desc = intf->cur_altsetting;
544 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
545 usb_remove_ep_files(&iface_desc->endpoint[i]);
546}
547
336void usb_create_sysfs_intf_files (struct usb_interface *intf) 548void usb_create_sysfs_intf_files (struct usb_interface *intf)
337{ 549{
550 struct usb_device *udev = interface_to_usbdev(intf);
551 struct usb_host_interface *alt = intf->cur_altsetting;
552
338 sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); 553 sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
339 554
340 if (intf->cur_altsetting->string) 555 if (alt->string == NULL)
556 alt->string = usb_cache_string(udev, alt->desc.iInterface);
557 if (alt->string)
341 device_create_file(&intf->dev, &dev_attr_interface); 558 device_create_file(&intf->dev, &dev_attr_interface);
342 559 usb_create_intf_ep_files(intf, udev);
343} 560}
344 561
345void usb_remove_sysfs_intf_files (struct usb_interface *intf) 562void usb_remove_sysfs_intf_files (struct usb_interface *intf)
346{ 563{
564 usb_remove_intf_ep_files(intf);
347 sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); 565 sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
348 566
349 if (intf->cur_altsetting->string) 567 if (intf->cur_altsetting->string)
350 device_remove_file(&intf->dev, &dev_attr_interface); 568 device_remove_file(&intf->dev, &dev_attr_interface);
351
352} 569}