aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2007-07-31 23:34:06 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2007-10-12 17:55:07 -0400
commit93993a0a3e528357ae4b9b0eb82fd4b428ebbf64 (patch)
treed97f96f9fc8f11431570a15d00731fc246c3724a /drivers
parentd9d16e8a92e385c9f57d2081b7aa737770a0a829 (diff)
usb: introduce usb_authorize/deauthorize()
These USB API functions will do the full authorization/deauthorization to be used for a device. When authorized we effectively allow a configuration to be set. Reverse that when deauthorized. Effectively this means that we have to clean all the configuration descriptors on deauthorize and reload them when we authorized. We could do without throwing them out for wired devices, but for wireless, we can read them only after authenticating, and thus, when authorizing an authenticated device we would need to read them. So to simplify, always release them on deauthorize(), re-read them on authorize(). Also fix leak reported by Ragner Magalhaes; in usb_deauthorize_device(), bNumConfigurations was being set to zero before the for loop, and thus the different raw descriptors where never being freed. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/generic.c2
-rw-r--r--drivers/usb/core/hub.c81
-rw-r--r--drivers/usb/core/usb.h3
3 files changed, 85 insertions, 1 deletions
diff --git a/drivers/usb/core/generic.c b/drivers/usb/core/generic.c
index 20b095050a16..7b9e1ec718d2 100644
--- a/drivers/usb/core/generic.c
+++ b/drivers/usb/core/generic.c
@@ -40,7 +40,7 @@ static int is_activesync(struct usb_interface_descriptor *desc)
40 && desc->bInterfaceProtocol == 1; 40 && desc->bInterfaceProtocol == 1;
41} 41}
42 42
43static int choose_configuration(struct usb_device *udev) 43int choose_configuration(struct usb_device *udev)
44{ 44{
45 int i; 45 int i;
46 int num_configs; 46 int num_configs;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 65d9ea1e6d71..f725d9e62b5b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1399,6 +1399,87 @@ fail:
1399 return err; 1399 return err;
1400} 1400}
1401 1401
1402
1403/**
1404 * Similar to usb_disconnect()
1405 *
1406 * We share a lock (that we have) with device_del(), so we need to
1407 * defer its call.
1408 */
1409int usb_deauthorize_device(struct usb_device *usb_dev)
1410{
1411 unsigned cnt;
1412 usb_lock_device(usb_dev);
1413 if (usb_dev->authorized == 0)
1414 goto out_unauthorized;
1415 usb_dev->authorized = 0;
1416 usb_set_configuration(usb_dev, -1);
1417 usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL);
1418 usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL);
1419 usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL);
1420 kfree(usb_dev->config);
1421 usb_dev->config = NULL;
1422 for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++)
1423 kfree(usb_dev->rawdescriptors[cnt]);
1424 usb_dev->descriptor.bNumConfigurations = 0;
1425 kfree(usb_dev->rawdescriptors);
1426out_unauthorized:
1427 usb_unlock_device(usb_dev);
1428 return 0;
1429}
1430
1431
1432int usb_authorize_device(struct usb_device *usb_dev)
1433{
1434 int result = 0, c;
1435 usb_lock_device(usb_dev);
1436 if (usb_dev->authorized == 1)
1437 goto out_authorized;
1438 kfree(usb_dev->product);
1439 usb_dev->product = NULL;
1440 kfree(usb_dev->manufacturer);
1441 usb_dev->manufacturer = NULL;
1442 kfree(usb_dev->serial);
1443 usb_dev->serial = NULL;
1444 result = usb_autoresume_device(usb_dev);
1445 if (result < 0) {
1446 dev_err(&usb_dev->dev,
1447 "can't autoresume for authorization: %d\n", result);
1448 goto error_autoresume;
1449 }
1450 result = usb_get_device_descriptor(usb_dev, sizeof(usb_dev->descriptor));
1451 if (result < 0) {
1452 dev_err(&usb_dev->dev, "can't re-read device descriptor for "
1453 "authorization: %d\n", result);
1454 goto error_device_descriptor;
1455 }
1456 usb_dev->authorized = 1;
1457 result = usb_configure_device(usb_dev);
1458 if (result < 0)
1459 goto error_configure;
1460 /* Choose and set the configuration. This registers the interfaces
1461 * with the driver core and lets interface drivers bind to them.
1462 */
1463 c = choose_configuration(usb_dev);
1464 if (c >= 0) {
1465 result = usb_set_configuration(usb_dev, c);
1466 if (result) {
1467 dev_err(&usb_dev->dev,
1468 "can't set config #%d, error %d\n", c, result);
1469 /* This need not be fatal. The user can try to
1470 * set other configurations. */
1471 }
1472 }
1473 dev_info(&usb_dev->dev, "authorized to connect\n");
1474error_configure:
1475error_device_descriptor:
1476error_autoresume:
1477out_authorized:
1478 usb_unlock_device(usb_dev); // complements locktree
1479 return result;
1480}
1481
1482
1402static int hub_port_status(struct usb_hub *hub, int port1, 1483static int hub_port_status(struct usb_hub *hub, int port1,
1403 u16 *status, u16 *change) 1484 u16 *status, u16 *change)
1404{ 1485{
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index cde6e52b84fe..e22ec7f8eb15 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -15,12 +15,15 @@ extern void usb_disable_interface (struct usb_device *dev,
15 struct usb_interface *intf); 15 struct usb_interface *intf);
16extern void usb_release_interface_cache(struct kref *ref); 16extern void usb_release_interface_cache(struct kref *ref);
17extern void usb_disable_device (struct usb_device *dev, int skip_ep0); 17extern void usb_disable_device (struct usb_device *dev, int skip_ep0);
18extern int usb_deauthorize_device (struct usb_device *);
19extern int usb_authorize_device (struct usb_device *);
18extern void usb_detect_quirks(struct usb_device *udev); 20extern void usb_detect_quirks(struct usb_device *udev);
19 21
20extern int usb_get_device_descriptor(struct usb_device *dev, 22extern int usb_get_device_descriptor(struct usb_device *dev,
21 unsigned int size); 23 unsigned int size);
22extern char *usb_cache_string(struct usb_device *udev, int index); 24extern char *usb_cache_string(struct usb_device *udev, int index);
23extern int usb_set_configuration(struct usb_device *dev, int configuration); 25extern int usb_set_configuration(struct usb_device *dev, int configuration);
26extern int choose_configuration(struct usb_device *udev);
24 27
25extern void usb_kick_khubd(struct usb_device *dev); 28extern void usb_kick_khubd(struct usb_device *dev);
26extern int usb_match_device(struct usb_device *dev, 29extern int usb_match_device(struct usb_device *dev,