aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-06-21 00:15:16 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:37 -0400
commit094f1649577dfc7f2c7407a8380e05a506b31f7f (patch)
tree5775c40d5c05f5427bb36c3c61d0db143c719bdd
parent8da608caa07d5c9745ec86bf7c25ad423352f9a4 (diff)
[PATCH] USB: add endpoint information to sysfs
This patch adds endpoint information for both devices and interfaces to sysfs. Previously it was only possible to get the endpoint information from usbfs, and never possible to get any information on endpoint 0. Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> drivers/usb/core/sysfs.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/usb.h | 4 2 files changed, 197 insertions(+), 2 deletions(-)
-rw-r--r--drivers/usb/core/sysfs.c195
-rw-r--r--include/linux/usb.h4
2 files changed, 197 insertions, 2 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 00297f113849..eae413bf8c2a 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -22,6 +22,174 @@
22 22
23#include "usb.h" 23#include "usb.h"
24 24
25/* endpoint stuff */
26struct endpoint_attribute {
27 struct device_attribute dev_attr;
28 struct usb_endpoint_descriptor *endpoint;
29 struct usb_device *udev;
30};
31#define to_endpoint_attr(_dev_attr) \
32 container_of(_dev_attr, struct endpoint_attribute, dev_attr)
33
34#define usb_ep_attr(field, format_string) \
35static ssize_t show_ep_##field(struct device *dev, struct device_attribute *attr, \
36 char *buf) \
37{ \
38 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr); \
39 \
40 return sprintf(buf, format_string, endpoint_attr->endpoint->field); \
41}
42usb_ep_attr(bLength, "%02x\n")
43usb_ep_attr(bDescriptorType, "%02x\n")
44usb_ep_attr(bEndpointAddress, "%02x\n")
45usb_ep_attr(bmAttributes, "%02x\n")
46usb_ep_attr(bInterval, "%02x\n")
47
48static ssize_t show_ep_wMaxPacketSize(struct device *dev,
49 struct device_attribute *attr, char *buf)
50{
51 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
52
53 return sprintf(buf, "%04x\n",
54 le16_to_cpu(endpoint_attr->endpoint->wMaxPacketSize) & 0x07ff);
55}
56
57static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, char *buf)
58{
59 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
60 char *type = "unknown";
61
62 switch (endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
63 case USB_ENDPOINT_XFER_CONTROL:
64 type = "Control";
65 break;
66 case USB_ENDPOINT_XFER_ISOC:
67 type = "Isoc";
68 break;
69 case USB_ENDPOINT_XFER_BULK:
70 type = "Bulk";
71 break;
72 case USB_ENDPOINT_XFER_INT:
73 type = "Interrupt";
74 break;
75 }
76 return sprintf(buf, "%s\n", type);
77}
78
79static ssize_t show_ep_interval(struct device *dev, struct device_attribute *attr, char *buf)
80{
81 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
82 struct usb_device *udev = endpoint_attr->udev;
83 struct usb_endpoint_descriptor *endpoint = endpoint_attr->endpoint;
84 char unit;
85 unsigned interval = 0;
86 unsigned in;
87
88 in = (endpoint->bEndpointAddress & USB_DIR_IN);
89
90 switch (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
91 case USB_ENDPOINT_XFER_CONTROL:
92 if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
93 interval = endpoint->bInterval;
94 break;
95 case USB_ENDPOINT_XFER_ISOC:
96 interval = 1 << (endpoint->bInterval - 1);
97 break;
98 case USB_ENDPOINT_XFER_BULK:
99 if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
100 interval = endpoint->bInterval;
101 break;
102 case USB_ENDPOINT_XFER_INT:
103 if (udev->speed == USB_SPEED_HIGH) {
104 interval = 1 << (endpoint->bInterval - 1);
105 } else
106 interval = endpoint->bInterval;
107 break;
108 }
109 interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
110 if (interval % 1000)
111 unit = 'u';
112 else {
113 unit = 'm';
114 interval /= 1000;
115 }
116
117 return sprintf(buf, "%d%cs\n", interval, unit);
118}
119
120static ssize_t show_ep_direction(struct device *dev, struct device_attribute *attr, char *buf)
121{
122 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
123 char *direction;
124
125 if ((endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
126 USB_ENDPOINT_XFER_CONTROL)
127 direction = "both";
128 else if (endpoint_attr->endpoint->bEndpointAddress & USB_DIR_IN)
129 direction = "in";
130 else
131 direction = "out";
132 return sprintf(buf, "%s\n", direction);
133}
134
135static struct endpoint_attribute *create_ep_attr(struct usb_endpoint_descriptor *endpoint,
136 struct usb_device *udev, char *name,
137 ssize_t (*show)(struct device *dev, struct device_attribute *attr, char *buf))
138{
139 struct endpoint_attribute *ep_attr;
140
141 ep_attr = kzalloc(sizeof(*ep_attr), GFP_KERNEL);
142 if (ep_attr) {
143 ep_attr->endpoint = endpoint;
144 ep_attr->udev = udev;
145 ep_attr->dev_attr.attr.name = name;
146 ep_attr->dev_attr.attr.mode = 0444;
147 ep_attr->dev_attr.attr.owner = THIS_MODULE;
148 ep_attr->dev_attr.show = show;
149 }
150 return ep_attr;
151}
152
153static void usb_create_ep_files(struct kobject *kobj, struct usb_host_endpoint *endpoint, struct usb_device *udev)
154{
155 struct usb_endpoint_descriptor *ep;
156
157 ep = &endpoint->desc;
158
159 endpoint->attrs = kzalloc(sizeof(struct attribute *) * 10, GFP_KERNEL);
160 endpoint->attrs[0] = &(create_ep_attr(ep, udev, "direction", show_ep_direction)->dev_attr.attr);
161 endpoint->attrs[1] = &(create_ep_attr(ep, udev, "type", show_ep_type)->dev_attr.attr);
162 endpoint->attrs[2] = &(create_ep_attr(ep, udev, "bLength", show_ep_bLength)->dev_attr.attr);
163 endpoint->attrs[3] = &(create_ep_attr(ep, udev, "bDescriptorType", show_ep_bDescriptorType)->dev_attr.attr);
164 endpoint->attrs[4] = &(create_ep_attr(ep, udev, "bEndpointAddress", show_ep_bEndpointAddress)->dev_attr.attr);
165 endpoint->attrs[5] = &(create_ep_attr(ep, udev, "bmAttributes", show_ep_bmAttributes)->dev_attr.attr);
166 endpoint->attrs[6] = &(create_ep_attr(ep, udev, "wMaxPacketSize", show_ep_wMaxPacketSize)->dev_attr.attr);
167 endpoint->attrs[7] = &(create_ep_attr(ep, udev, "bInterval", show_ep_bInterval)->dev_attr.attr);
168 endpoint->attrs[8] = &(create_ep_attr(ep, udev, "interval", show_ep_interval)->dev_attr.attr);
169 endpoint->attrs[9] = NULL;
170 endpoint->num_attrs = 9;
171
172 endpoint->attr_group = kzalloc(sizeof(*endpoint->attr_group), GFP_KERNEL);
173 endpoint->attr_name = kzalloc(10, GFP_KERNEL);
174 sprintf(endpoint->attr_name, "ep_%02x", endpoint->desc.bEndpointAddress);
175
176 endpoint->attr_group->attrs = endpoint->attrs;
177 endpoint->attr_group->name = endpoint->attr_name;
178 sysfs_create_group(kobj, endpoint->attr_group);
179}
180
181static void usb_remove_ep_files(struct kobject *kobj, struct usb_host_endpoint *endpoint)
182{
183 int i;
184
185 sysfs_remove_group(kobj, endpoint->attr_group);
186 kfree(endpoint->attr_group);
187 kfree(endpoint->attr_name);
188 for (i = 0; i < endpoint->num_attrs; ++i)
189 kfree(endpoint->attrs[i]);
190 kfree(endpoint->attrs);
191}
192
25/* Active configuration fields */ 193/* Active configuration fields */
26#define usb_actconfig_show(field, multiplier, format_string) \ 194#define usb_actconfig_show(field, multiplier, format_string) \
27static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \ 195static ssize_t show_##field (struct device *dev, struct device_attribute *attr, char *buf) \
@@ -236,12 +404,14 @@ void usb_create_sysfs_dev_files (struct usb_device *udev)
236 if (udev->serial) 404 if (udev->serial)
237 device_create_file (dev, &dev_attr_serial); 405 device_create_file (dev, &dev_attr_serial);
238 device_create_file (dev, &dev_attr_configuration); 406 device_create_file (dev, &dev_attr_configuration);
407 usb_create_ep_files(&dev->kobj, &udev->ep0, udev);
239} 408}
240 409
241void usb_remove_sysfs_dev_files (struct usb_device *udev) 410void usb_remove_sysfs_dev_files (struct usb_device *udev)
242{ 411{
243 struct device *dev = &udev->dev; 412 struct device *dev = &udev->dev;
244 413
414 usb_remove_ep_files(&dev->kobj, &udev->ep0);
245 sysfs_remove_group(&dev->kobj, &dev_attr_grp); 415 sysfs_remove_group(&dev->kobj, &dev_attr_grp);
246 416
247 if (udev->descriptor.iManufacturer) 417 if (udev->descriptor.iManufacturer)
@@ -333,20 +503,41 @@ static struct attribute_group intf_attr_grp = {
333 .attrs = intf_attrs, 503 .attrs = intf_attrs,
334}; 504};
335 505
506static void usb_create_intf_ep_files(struct usb_interface *intf)
507{
508 struct usb_host_interface *iface_desc;
509 int i;
510
511 iface_desc = intf->cur_altsetting;
512 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
513 usb_create_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i],
514 interface_to_usbdev(intf));
515}
516
517static void usb_remove_intf_ep_files(struct usb_interface *intf)
518{
519 struct usb_host_interface *iface_desc;
520 int i;
521
522 iface_desc = intf->cur_altsetting;
523 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i)
524 usb_remove_ep_files(&intf->dev.kobj, &iface_desc->endpoint[i]);
525}
526
336void usb_create_sysfs_intf_files (struct usb_interface *intf) 527void usb_create_sysfs_intf_files (struct usb_interface *intf)
337{ 528{
338 sysfs_create_group(&intf->dev.kobj, &intf_attr_grp); 529 sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
339 530
340 if (intf->cur_altsetting->string) 531 if (intf->cur_altsetting->string)
341 device_create_file(&intf->dev, &dev_attr_interface); 532 device_create_file(&intf->dev, &dev_attr_interface);
342 533 usb_create_intf_ep_files(intf);
343} 534}
344 535
345void usb_remove_sysfs_intf_files (struct usb_interface *intf) 536void usb_remove_sysfs_intf_files (struct usb_interface *intf)
346{ 537{
538 usb_remove_intf_ep_files(intf);
347 sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp); 539 sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
348 540
349 if (intf->cur_altsetting->string) 541 if (intf->cur_altsetting->string)
350 device_remove_file(&intf->dev, &dev_attr_interface); 542 device_remove_file(&intf->dev, &dev_attr_interface);
351
352} 543}
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 8f731e8f2821..4512210e97e7 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -57,6 +57,10 @@ struct usb_host_endpoint {
57 struct usb_endpoint_descriptor desc; 57 struct usb_endpoint_descriptor desc;
58 struct list_head urb_list; 58 struct list_head urb_list;
59 void *hcpriv; 59 void *hcpriv;
60 char *attr_name;
61 struct attribute_group *attr_group;
62 struct attribute **attrs;
63 int num_attrs;
60 64
61 unsigned char *extra; /* Extra descriptors */ 65 unsigned char *extra; /* Extra descriptors */
62 int extralen; 66 int extralen;