aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2009-05-04 13:48:32 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2009-06-16 00:44:45 -0400
commit5512966643adb17483efc5f61481a38fc33088bb (patch)
treeb9dfc19787e3a43b14a767f490a9903bea7190d5 /drivers/usb/core
parent9636b683769a6c3acfe121314ee9d7e19157f109 (diff)
usb: convert endpoint devices to bus-less childs of the usb interface
The endpoint devices look like simple attribute groups now, and no longer like devices with a specific subsystem. They will also no longer emit uevents. It also removes the device node requests for endpoint devices, which are not implemented for now. Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/driver.c25
-rw-r--r--drivers/usb/core/endpoint.c160
-rw-r--r--drivers/usb/core/usb.c3
-rw-r--r--drivers/usb/core/usb.h11
4 files changed, 29 insertions, 170 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index c115eed0fdc..77de8d65862 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -154,16 +154,11 @@ static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *in
154static int usb_probe_device(struct device *dev) 154static int usb_probe_device(struct device *dev)
155{ 155{
156 struct usb_device_driver *udriver = to_usb_device_driver(dev->driver); 156 struct usb_device_driver *udriver = to_usb_device_driver(dev->driver);
157 struct usb_device *udev; 157 struct usb_device *udev = to_usb_device(dev);
158 int error = -ENODEV; 158 int error = -ENODEV;
159 159
160 dev_dbg(dev, "%s\n", __func__); 160 dev_dbg(dev, "%s\n", __func__);
161 161
162 if (!is_usb_device(dev)) /* Sanity check */
163 return error;
164
165 udev = to_usb_device(dev);
166
167 /* TODO: Add real matching code */ 162 /* TODO: Add real matching code */
168 163
169 /* The device should always appear to be in use 164 /* The device should always appear to be in use
@@ -203,18 +198,13 @@ static void usb_cancel_queued_reset(struct usb_interface *iface)
203static int usb_probe_interface(struct device *dev) 198static int usb_probe_interface(struct device *dev)
204{ 199{
205 struct usb_driver *driver = to_usb_driver(dev->driver); 200 struct usb_driver *driver = to_usb_driver(dev->driver);
206 struct usb_interface *intf; 201 struct usb_interface *intf = to_usb_interface(dev);
207 struct usb_device *udev; 202 struct usb_device *udev = interface_to_usbdev(intf);
208 const struct usb_device_id *id; 203 const struct usb_device_id *id;
209 int error = -ENODEV; 204 int error = -ENODEV;
210 205
211 dev_dbg(dev, "%s\n", __func__); 206 dev_dbg(dev, "%s\n", __func__);
212 207
213 if (is_usb_device(dev)) /* Sanity check */
214 return error;
215
216 intf = to_usb_interface(dev);
217 udev = interface_to_usbdev(intf);
218 intf->needs_binding = 0; 208 intf->needs_binding = 0;
219 209
220 if (udev->authorized == 0) { 210 if (udev->authorized == 0) {
@@ -593,7 +583,7 @@ static int usb_device_match(struct device *dev, struct device_driver *drv)
593 /* TODO: Add real matching code */ 583 /* TODO: Add real matching code */
594 return 1; 584 return 1;
595 585
596 } else { 586 } else if (is_usb_interface(dev)) {
597 struct usb_interface *intf; 587 struct usb_interface *intf;
598 struct usb_driver *usb_drv; 588 struct usb_driver *usb_drv;
599 const struct usb_device_id *id; 589 const struct usb_device_id *id;
@@ -625,11 +615,14 @@ static int usb_uevent(struct device *dev, struct kobj_uevent_env *env)
625 /* driver is often null here; dev_dbg() would oops */ 615 /* driver is often null here; dev_dbg() would oops */
626 pr_debug("usb %s: uevent\n", dev_name(dev)); 616 pr_debug("usb %s: uevent\n", dev_name(dev));
627 617
628 if (is_usb_device(dev)) 618 if (is_usb_device(dev)) {
629 usb_dev = to_usb_device(dev); 619 usb_dev = to_usb_device(dev);
630 else { 620 } else if (is_usb_interface(dev)) {
631 struct usb_interface *intf = to_usb_interface(dev); 621 struct usb_interface *intf = to_usb_interface(dev);
622
632 usb_dev = interface_to_usbdev(intf); 623 usb_dev = interface_to_usbdev(intf);
624 } else {
625 return 0;
633 } 626 }
634 627
635 if (usb_dev->devnum < 0) { 628 if (usb_dev->devnum < 0) {
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 40dee2ac013..bc39fc40bbd 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -15,19 +15,18 @@
15#include <linux/usb.h> 15#include <linux/usb.h>
16#include "usb.h" 16#include "usb.h"
17 17
18#define MAX_ENDPOINT_MINORS (64*128*32)
19static int usb_endpoint_major;
20static DEFINE_IDR(endpoint_idr);
21
22struct ep_device { 18struct ep_device {
23 struct usb_endpoint_descriptor *desc; 19 struct usb_endpoint_descriptor *desc;
24 struct usb_device *udev; 20 struct usb_device *udev;
25 struct device dev; 21 struct device dev;
26 int minor;
27}; 22};
28#define to_ep_device(_dev) \ 23#define to_ep_device(_dev) \
29 container_of(_dev, struct ep_device, dev) 24 container_of(_dev, struct ep_device, dev)
30 25
26struct device_type usb_ep_device_type = {
27 .name = "usb_endpoint",
28};
29
31struct ep_attribute { 30struct ep_attribute {
32 struct attribute attr; 31 struct attribute attr;
33 ssize_t (*show)(struct usb_device *, 32 ssize_t (*show)(struct usb_device *,
@@ -160,118 +159,10 @@ static struct attribute_group *ep_dev_groups[] = {
160 NULL 159 NULL
161}; 160};
162 161
163static int usb_endpoint_major_init(void)
164{
165 dev_t dev;
166 int error;
167
168 error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
169 "usb_endpoint");
170 if (error) {
171 printk(KERN_ERR "Unable to get a dynamic major for "
172 "usb endpoints.\n");
173 return error;
174 }
175 usb_endpoint_major = MAJOR(dev);
176
177 return error;
178}
179
180static void usb_endpoint_major_cleanup(void)
181{
182 unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
183 MAX_ENDPOINT_MINORS);
184}
185
186static int endpoint_get_minor(struct ep_device *ep_dev)
187{
188 static DEFINE_MUTEX(minor_lock);
189 int retval = -ENOMEM;
190 int id;
191
192 mutex_lock(&minor_lock);
193 if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
194 goto exit;
195
196 retval = idr_get_new(&endpoint_idr, ep_dev, &id);
197 if (retval < 0) {
198 if (retval == -EAGAIN)
199 retval = -ENOMEM;
200 goto exit;
201 }
202 ep_dev->minor = id & MAX_ID_MASK;
203exit:
204 mutex_unlock(&minor_lock);
205 return retval;
206}
207
208static void endpoint_free_minor(struct ep_device *ep_dev)
209{
210 idr_remove(&endpoint_idr, ep_dev->minor);
211}
212
213static struct endpoint_class {
214 struct kref kref;
215 struct class *class;
216} *ep_class;
217
218static int init_endpoint_class(void)
219{
220 int result = 0;
221
222 if (ep_class != NULL) {
223 kref_get(&ep_class->kref);
224 goto exit;
225 }
226
227 ep_class = kmalloc(sizeof(*ep_class), GFP_KERNEL);
228 if (!ep_class) {
229 result = -ENOMEM;
230 goto exit;
231 }
232
233 kref_init(&ep_class->kref);
234 ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
235 if (IS_ERR(ep_class->class)) {
236 result = PTR_ERR(ep_class->class);
237 goto class_create_error;
238 }
239
240 result = usb_endpoint_major_init();
241 if (result)
242 goto endpoint_major_error;
243
244 goto exit;
245
246endpoint_major_error:
247 class_destroy(ep_class->class);
248class_create_error:
249 kfree(ep_class);
250 ep_class = NULL;
251exit:
252 return result;
253}
254
255static void release_endpoint_class(struct kref *kref)
256{
257 /* Ok, we cheat as we know we only have one ep_class */
258 class_destroy(ep_class->class);
259 kfree(ep_class);
260 ep_class = NULL;
261 usb_endpoint_major_cleanup();
262}
263
264static void destroy_endpoint_class(void)
265{
266 if (ep_class)
267 kref_put(&ep_class->kref, release_endpoint_class);
268}
269
270static void ep_device_release(struct device *dev) 162static void ep_device_release(struct device *dev)
271{ 163{
272 struct ep_device *ep_dev = to_ep_device(dev); 164 struct ep_device *ep_dev = to_ep_device(dev);
273 165
274 endpoint_free_minor(ep_dev);
275 kfree(ep_dev); 166 kfree(ep_dev);
276} 167}
277 168
@@ -279,62 +170,32 @@ int usb_create_ep_devs(struct device *parent,
279 struct usb_host_endpoint *endpoint, 170 struct usb_host_endpoint *endpoint,
280 struct usb_device *udev) 171 struct usb_device *udev)
281{ 172{
282 char name[8];
283 struct ep_device *ep_dev; 173 struct ep_device *ep_dev;
284 int retval; 174 int retval;
285 175
286 retval = init_endpoint_class();
287 if (retval)
288 goto exit;
289
290 ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL); 176 ep_dev = kzalloc(sizeof(*ep_dev), GFP_KERNEL);
291 if (!ep_dev) { 177 if (!ep_dev) {
292 retval = -ENOMEM; 178 retval = -ENOMEM;
293 goto error_alloc; 179 goto exit;
294 }
295
296 retval = endpoint_get_minor(ep_dev);
297 if (retval) {
298 dev_err(parent, "can not allocate minor number for %s\n",
299 dev_name(&ep_dev->dev));
300 goto error_register;
301 } 180 }
302 181
303 ep_dev->desc = &endpoint->desc; 182 ep_dev->desc = &endpoint->desc;
304 ep_dev->udev = udev; 183 ep_dev->udev = udev;
305 ep_dev->dev.groups = ep_dev_groups; 184 ep_dev->dev.groups = ep_dev_groups;
306 ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor); 185 ep_dev->dev.type = &usb_ep_device_type;
307 ep_dev->dev.class = ep_class->class;
308 ep_dev->dev.parent = parent; 186 ep_dev->dev.parent = parent;
309 ep_dev->dev.release = ep_device_release; 187 ep_dev->dev.release = ep_device_release;
310 dev_set_name(&ep_dev->dev, "usbdev%d.%d_ep%02x", 188 dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
311 udev->bus->busnum, udev->devnum,
312 endpoint->desc.bEndpointAddress);
313 189
314 retval = device_register(&ep_dev->dev); 190 retval = device_register(&ep_dev->dev);
315 if (retval) 191 if (retval)
316 goto error_chrdev; 192 goto error_register;
317 193
318 /* create the symlink to the old-style "ep_XX" directory */
319 sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
320 retval = sysfs_create_link(&parent->kobj, &ep_dev->dev.kobj, name);
321 if (retval)
322 goto error_link;
323 endpoint->ep_dev = ep_dev; 194 endpoint->ep_dev = ep_dev;
324 return retval; 195 return retval;
325 196
326error_link:
327 device_unregister(&ep_dev->dev);
328 destroy_endpoint_class();
329 return retval;
330
331error_chrdev:
332 endpoint_free_minor(ep_dev);
333
334error_register: 197error_register:
335 kfree(ep_dev); 198 kfree(ep_dev);
336error_alloc:
337 destroy_endpoint_class();
338exit: 199exit:
339 return retval; 200 return retval;
340} 201}
@@ -344,12 +205,7 @@ void usb_remove_ep_devs(struct usb_host_endpoint *endpoint)
344 struct ep_device *ep_dev = endpoint->ep_dev; 205 struct ep_device *ep_dev = endpoint->ep_dev;
345 206
346 if (ep_dev) { 207 if (ep_dev) {
347 char name[8];
348
349 sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
350 sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
351 device_unregister(&ep_dev->dev); 208 device_unregister(&ep_dev->dev);
352 endpoint->ep_dev = NULL; 209 endpoint->ep_dev = NULL;
353 destroy_endpoint_class();
354 } 210 }
355} 211}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index eb810bbe7bb..c32811ae128 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -140,8 +140,7 @@ static int __find_interface(struct device *dev, void *data)
140 struct find_interface_arg *arg = data; 140 struct find_interface_arg *arg = data;
141 struct usb_interface *intf; 141 struct usb_interface *intf;
142 142
143 /* can't look at usb devices, only interfaces */ 143 if (!is_usb_interface(dev))
144 if (is_usb_device(dev))
145 return 0; 144 return 0;
146 145
147 intf = to_usb_interface(dev); 146 intf = to_usb_interface(dev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index dabf9255a10..e2a8cfaade1 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -104,6 +104,7 @@ extern struct workqueue_struct *ksuspend_usb_wq;
104extern struct bus_type usb_bus_type; 104extern struct bus_type usb_bus_type;
105extern struct device_type usb_device_type; 105extern struct device_type usb_device_type;
106extern struct device_type usb_if_device_type; 106extern struct device_type usb_if_device_type;
107extern struct device_type usb_ep_device_type;
107extern struct usb_device_driver usb_generic_driver; 108extern struct usb_device_driver usb_generic_driver;
108 109
109static inline int is_usb_device(const struct device *dev) 110static inline int is_usb_device(const struct device *dev)
@@ -111,6 +112,16 @@ static inline int is_usb_device(const struct device *dev)
111 return dev->type == &usb_device_type; 112 return dev->type == &usb_device_type;
112} 113}
113 114
115static inline int is_usb_interface(const struct device *dev)
116{
117 return dev->type == &usb_if_device_type;
118}
119
120static inline int is_usb_endpoint(const struct device *dev)
121{
122 return dev->type == &usb_ep_device_type;
123}
124
114/* Do the same for device drivers and interface drivers. */ 125/* Do the same for device drivers and interface drivers. */
115 126
116static inline int is_usb_device_driver(struct device_driver *drv) 127static inline int is_usb_device_driver(struct device_driver *drv)