aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-10-25 15:56:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:50 -0400
commitbe69e5b1900a19a545becda822b18d6f09168ba5 (patch)
tree7730b17e403cc03ea7c7cee8fc56f06171af0ebe
parente52783206ada0c0276c8dd74c0ecd0007ead7c00 (diff)
[PATCH] usbcore: Improve endpoint sysfs file handling
This revised patch (as587b) improves the implementation of USB endpoint sysfs files. Instead of storing a whole bunch of attributes for every single endpoint, each endpoint now gets its own kobject and they can share a static list of attributes. The number of extra fields added to struct usb_host_endpoint has been reduced from 4 to 1. The bEndpointAddress field is retained even though it is redundant (it repeats the same information as the attributes' directory name). The code avoids calling kobject_register, to prevent generating unwanted hotplug events. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/core/sysfs.c219
-rw-r--r--include/linux/usb.h5
2 files changed, 125 insertions, 99 deletions
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 4bdbc9df6e03..f18317fb49ee 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -23,43 +23,56 @@
23#include "usb.h" 23#include "usb.h"
24 24
25/* endpoint stuff */ 25/* endpoint stuff */
26struct endpoint_attribute { 26struct ep_object {
27 struct device_attribute dev_attr; 27 struct usb_endpoint_descriptor *desc;
28 struct usb_endpoint_descriptor *endpoint;
29 struct usb_device *udev; 28 struct usb_device *udev;
29 struct kobject kobj;
30}; 30};
31#define to_endpoint_attr(_dev_attr) \ 31#define to_ep_object(_kobj) \
32 container_of(_dev_attr, struct endpoint_attribute, dev_attr) 32 container_of(_kobj, struct ep_object, kobj)
33 33
34#define usb_ep_attr(field, format_string) \ 34struct ep_attribute {
35static ssize_t show_ep_##field(struct device *dev, struct device_attribute *attr, \ 35 struct attribute attr;
36 char *buf) \ 36 ssize_t (*show)(struct usb_device *,
37{ \ 37 struct usb_endpoint_descriptor *, char *);
38 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr); \ 38};
39 \ 39#define to_ep_attribute(_attr) \
40 return sprintf(buf, format_string, endpoint_attr->endpoint->field); \ 40 container_of(_attr, struct ep_attribute, attr)
41} 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
42usb_ep_attr(bLength, "%02x\n") 57usb_ep_attr(bLength, "%02x\n")
43usb_ep_attr(bDescriptorType, "%02x\n")
44usb_ep_attr(bEndpointAddress, "%02x\n") 58usb_ep_attr(bEndpointAddress, "%02x\n")
45usb_ep_attr(bmAttributes, "%02x\n") 59usb_ep_attr(bmAttributes, "%02x\n")
46usb_ep_attr(bInterval, "%02x\n") 60usb_ep_attr(bInterval, "%02x\n")
47 61
48static ssize_t show_ep_wMaxPacketSize(struct device *dev, 62static ssize_t show_ep_wMaxPacketSize(struct usb_device *udev,
49 struct device_attribute *attr, char *buf) 63 struct usb_endpoint_descriptor *desc, char *buf)
50{ 64{
51 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
52
53 return sprintf(buf, "%04x\n", 65 return sprintf(buf, "%04x\n",
54 le16_to_cpu(endpoint_attr->endpoint->wMaxPacketSize) & 0x07ff); 66 le16_to_cpu(desc->wMaxPacketSize) & 0x07ff);
55} 67}
68static EP_ATTR(wMaxPacketSize);
56 69
57static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, char *buf) 70static ssize_t show_ep_type(struct usb_device *udev,
71 struct usb_endpoint_descriptor *desc, char *buf)
58{ 72{
59 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
60 char *type = "unknown"; 73 char *type = "unknown";
61 74
62 switch (endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { 75 switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
63 case USB_ENDPOINT_XFER_CONTROL: 76 case USB_ENDPOINT_XFER_CONTROL:
64 type = "Control"; 77 type = "Control";
65 break; 78 break;
@@ -75,35 +88,34 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, c
75 } 88 }
76 return sprintf(buf, "%s\n", type); 89 return sprintf(buf, "%s\n", type);
77} 90}
91static EP_ATTR(type);
78 92
79static ssize_t show_ep_interval(struct device *dev, struct device_attribute *attr, char *buf) 93static ssize_t show_ep_interval(struct usb_device *udev,
94 struct usb_endpoint_descriptor *desc, char *buf)
80{ 95{
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; 96 char unit;
85 unsigned interval = 0; 97 unsigned interval = 0;
86 unsigned in; 98 unsigned in;
87 99
88 in = (endpoint->bEndpointAddress & USB_DIR_IN); 100 in = (desc->bEndpointAddress & USB_DIR_IN);
89 101
90 switch (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { 102 switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
91 case USB_ENDPOINT_XFER_CONTROL: 103 case USB_ENDPOINT_XFER_CONTROL:
92 if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ 104 if (udev->speed == USB_SPEED_HIGH) /* uframes per NAK */
93 interval = endpoint->bInterval; 105 interval = desc->bInterval;
94 break; 106 break;
95 case USB_ENDPOINT_XFER_ISOC: 107 case USB_ENDPOINT_XFER_ISOC:
96 interval = 1 << (endpoint->bInterval - 1); 108 interval = 1 << (desc->bInterval - 1);
97 break; 109 break;
98 case USB_ENDPOINT_XFER_BULK: 110 case USB_ENDPOINT_XFER_BULK:
99 if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ 111 if (udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */
100 interval = endpoint->bInterval; 112 interval = desc->bInterval;
101 break; 113 break;
102 case USB_ENDPOINT_XFER_INT: 114 case USB_ENDPOINT_XFER_INT:
103 if (udev->speed == USB_SPEED_HIGH) { 115 if (udev->speed == USB_SPEED_HIGH)
104 interval = 1 << (endpoint->bInterval - 1); 116 interval = 1 << (desc->bInterval - 1);
105 } else 117 else
106 interval = endpoint->bInterval; 118 interval = desc->bInterval;
107 break; 119 break;
108 } 120 }
109 interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000; 121 interval *= (udev->speed == USB_SPEED_HIGH) ? 125 : 1000;
@@ -116,78 +128,95 @@ static ssize_t show_ep_interval(struct device *dev, struct device_attribute *att
116 128
117 return sprintf(buf, "%d%cs\n", interval, unit); 129 return sprintf(buf, "%d%cs\n", interval, unit);
118} 130}
131static EP_ATTR(interval);
119 132
120static ssize_t show_ep_direction(struct device *dev, struct device_attribute *attr, char *buf) 133static ssize_t show_ep_direction(struct usb_device *udev,
134 struct usb_endpoint_descriptor *desc, char *buf)
121{ 135{
122 struct endpoint_attribute *endpoint_attr = to_endpoint_attr(attr);
123 char *direction; 136 char *direction;
124 137
125 if ((endpoint_attr->endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == 138 if ((desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
126 USB_ENDPOINT_XFER_CONTROL) 139 USB_ENDPOINT_XFER_CONTROL)
127 direction = "both"; 140 direction = "both";
128 else if (endpoint_attr->endpoint->bEndpointAddress & USB_DIR_IN) 141 else if (desc->bEndpointAddress & USB_DIR_IN)
129 direction = "in"; 142 direction = "in";
130 else 143 else
131 direction = "out"; 144 direction = "out";
132 return sprintf(buf, "%s\n", direction); 145 return sprintf(buf, "%s\n", direction);
133} 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};
134 160
135static struct endpoint_attribute *create_ep_attr(struct usb_endpoint_descriptor *endpoint, 161static void ep_object_release(struct kobject *kobj)
136