2006-07-02 06:08:06 +04:00
/*
* drivers / usb / generic . c - generic driver for USB devices ( not interfaces )
*
* ( C ) Copyright 2005 Greg Kroah - Hartman < gregkh @ suse . de >
*
* based on drivers / usb / usb . c which had the following copyrights :
* ( C ) Copyright Linus Torvalds 1999
* ( C ) Copyright Johannes Erdfelt 1999 - 2001
* ( C ) Copyright Andreas Gal 1999
* ( C ) Copyright Gregory P . Smith 1999
* ( C ) Copyright Deti Fliegl 1999 ( new USB architecture )
* ( C ) Copyright Randy Dunlap 2000
* ( C ) Copyright David Brownell 2000 - 2004
* ( C ) Copyright Yggdrasil Computing , Inc . 2000
* ( usb_device_id matching changes by Adam J . Richter )
* ( C ) Copyright Greg Kroah - Hartman 2002 - 2003
*
*/
# include <linux/usb.h>
2010-04-25 01:21:52 +04:00
# include <linux/usb/hcd.h>
2006-07-02 06:08:06 +04:00
# include "usb.h"
2006-07-02 06:09:35 +04:00
static inline const char * plural ( int n )
{
return ( n = = 1 ? " " : " s " ) ;
}
2006-12-15 03:01:28 +03:00
static int is_rndis ( struct usb_interface_descriptor * desc )
{
return desc - > bInterfaceClass = = USB_CLASS_COMM
& & desc - > bInterfaceSubClass = = 2
& & desc - > bInterfaceProtocol = = 0xff ;
}
static int is_activesync ( struct usb_interface_descriptor * desc )
{
return desc - > bInterfaceClass = = USB_CLASS_MISC
& & desc - > bInterfaceSubClass = = 1
& & desc - > bInterfaceProtocol = = 1 ;
}
2007-08-03 08:44:27 +04:00
int usb_choose_configuration ( struct usb_device * udev )
2006-07-02 06:09:35 +04:00
{
int i ;
int num_configs ;
int insufficient_power = 0 ;
struct usb_host_config * c , * best ;
2012-11-05 00:50:08 +04:00
if ( usb_device_is_owned ( udev ) )
return 0 ;
2006-07-02 06:09:35 +04:00
best = NULL ;
c = udev - > config ;
num_configs = udev - > descriptor . bNumConfigurations ;
for ( i = 0 ; i < num_configs ; ( i + + , c + + ) ) {
struct usb_interface_descriptor * desc = NULL ;
/* It's possible that a config has no interfaces! */
if ( c - > desc . bNumInterfaces > 0 )
desc = & c - > intf_cache [ 0 ] - > altsetting - > desc ;
/*
* HP ' s USB bus - powered keyboard has only one configuration
* and it claims to be self - powered ; other devices may have
* similar errors in their descriptors . If the next test
* were allowed to execute , such configurations would always
* be rejected and the devices would not work as expected .
* In the meantime , we run the risk of selecting a config
* that requires external power at a time when that power
* isn ' t available . It seems to be the lesser of two evils .
*
* Bugzilla # 6448 reports a device that appears to crash
* when it receives a GET_DEVICE_STATUS request ! We don ' t
* have any other way to tell whether a device is self - powered ,
* but since we don ' t use that information anywhere but here ,
* the call has been removed .
*
* Maybe the GET_DEVICE_STATUS call and the test below can
* be reinstated when device firmwares become more reliable .
* Don ' t hold your breath .
*/
#if 0
/* Rule out self-powered configs for a bus-powered device */
if ( bus_powered & & ( c - > desc . bmAttributes &
USB_CONFIG_ATT_SELFPOWER ) )
continue ;
# endif
/*
* The next test may not be as effective as it should be .
* Some hubs have errors in their descriptor , claiming
* to be self - powered when they are really bus - powered .
* We will overestimate the amount of current such hubs
* make available for each port .
*
* This is a fairly benign sort of failure . It won ' t
* cause us to reject configurations that we should have
* accepted .
*/
/* Rule out configs that draw too much bus current */
2012-12-18 18:25:46 +04:00
if ( usb_get_max_power ( udev , c ) > udev - > bus_mA ) {
2006-07-02 06:09:35 +04:00
insufficient_power + + ;
continue ;
}
2006-12-15 03:01:28 +03:00
/* When the first config's first interface is one of Microsoft's
* pet nonstandard Ethernet - over - USB protocols , ignore it unless
* this kernel has enabled the necessary host side driver .
2010-07-27 19:28:42 +04:00
* But : Don ' t ignore it if it ' s the only config .
2006-12-15 03:01:28 +03:00
*/
2010-07-27 19:28:42 +04:00
if ( i = = 0 & & num_configs > 1 & & desc & &
( is_rndis ( desc ) | | is_activesync ( desc ) ) ) {
2006-12-15 03:01:28 +03:00
# if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE)
2006-07-02 06:09:35 +04:00
continue ;
# else
best = c ;
# endif
}
/* From the remaining configs, choose the first one whose
* first interface is for a non - vendor - specific class .
* Reason : Linux is more likely to have a class driver
* than a vendor - specific driver . */
else if ( udev - > descriptor . bDeviceClass ! =
USB_CLASS_VENDOR_SPEC & &
2010-04-20 18:40:59 +04:00
( desc & & desc - > bInterfaceClass ! =
2006-07-02 06:09:35 +04:00
USB_CLASS_VENDOR_SPEC ) ) {
best = c ;
break ;
}
/* If all the remaining configs are vendor-specific,
* choose the first one . */
else if ( ! best )
best = c ;
}
if ( insufficient_power > 0 )
dev_info ( & udev - > dev , " rejected %d configuration%s "
" due to insufficient available bus power \n " ,
insufficient_power , plural ( insufficient_power ) ) ;
if ( best ) {
i = best - > desc . bConfigurationValue ;
2009-09-25 02:18:27 +04:00
dev_dbg ( & udev - > dev ,
2006-07-02 06:09:35 +04:00
" configuration #%d chosen from %d choice%s \n " ,
i , num_configs , plural ( num_configs ) ) ;
} else {
i = - 1 ;
dev_warn ( & udev - > dev ,
" no configuration chosen from %d choice%s \n " ,
num_configs , plural ( num_configs ) ) ;
}
return i ;
}
2014-01-24 01:12:29 +04:00
EXPORT_SYMBOL_GPL ( usb_choose_configuration ) ;
2006-07-02 06:09:35 +04:00
2006-07-02 06:08:49 +04:00
static int generic_probe ( struct usb_device * udev )
2006-07-02 06:08:06 +04:00
{
2006-07-02 06:09:35 +04:00
int err , c ;
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them .
*/
2012-11-05 00:50:08 +04:00
if ( udev - > authorized = = 0 )
2007-08-01 07:34:04 +04:00
dev_err ( & udev - > dev , " Device is not authorized for usage \n " ) ;
else {
2007-08-03 08:44:27 +04:00
c = usb_choose_configuration ( udev ) ;
2007-08-01 07:34:04 +04:00
if ( c > = 0 ) {
err = usb_set_configuration ( udev , c ) ;
2013-03-28 00:14:01 +04:00
if ( err & & err ! = - ENODEV ) {
2007-08-01 07:34:04 +04:00
dev_err ( & udev - > dev , " can't set config #%d, error %d \n " ,
2006-07-02 06:09:35 +04:00
c , err ) ;
2007-08-01 07:34:04 +04:00
/* This need not be fatal. The user can try to
* set other configurations . */
}
2006-07-02 06:09:35 +04:00
}
}
/* USB device state == configured ... usable */
usb_notify_add_device ( udev ) ;
2006-07-02 06:08:06 +04:00
return 0 ;
}
2006-07-02 06:09:35 +04:00
2006-07-02 06:08:49 +04:00
static void generic_disconnect ( struct usb_device * udev )
2006-07-02 06:08:06 +04:00
{
2006-07-02 06:09:35 +04:00
usb_notify_remove_device ( udev ) ;
2006-07-02 06:08:06 +04:00
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
2006-08-30 23:47:18 +04:00
if ( udev - > actconfig )
2007-02-09 00:40:43 +03:00
usb_set_configuration ( udev , - 1 ) ;
2006-07-02 06:08:06 +04:00
}
2006-07-02 06:09:35 +04:00
# ifdef CONFIG_PM
static int generic_suspend ( struct usb_device * udev , pm_message_t msg )
{
2007-05-04 19:51:54 +04:00
int rc ;
2007-05-30 23:34:36 +04:00
/* Normal USB devices suspend through their upstream port.
* Root hubs don ' t have upstream ports to suspend ,
* so we have to shut down their downstream HC - to - USB
* interfaces manually by doing a bus ( or " global " ) suspend .
2007-05-04 19:51:54 +04:00
*/
2007-05-30 23:34:36 +04:00
if ( ! udev - > parent )
2008-11-26 00:39:18 +03:00
rc = hcd_bus_suspend ( udev , msg ) ;
2007-09-10 19:31:43 +04:00
/* Non-root devices don't need to do anything for FREEZE or PRETHAW */
else if ( msg . event = = PM_EVENT_FREEZE | | msg . event = = PM_EVENT_PRETHAW )
rc = 0 ;
2007-05-30 23:34:36 +04:00
else
2008-11-26 00:39:18 +03:00
rc = usb_port_suspend ( udev , msg ) ;
2007-09-10 19:31:43 +04:00
2007-05-04 19:51:54 +04:00
return rc ;
2006-07-02 06:09:35 +04:00
}
2008-11-26 00:39:18 +03:00
static int generic_resume ( struct usb_device * udev , pm_message_t msg )
2006-07-02 06:09:35 +04:00
{
2007-05-04 19:51:54 +04:00
int rc ;
2007-05-30 23:34:36 +04:00
/* Normal USB devices resume/reset through their upstream port.
* Root hubs don ' t have upstream ports to resume or reset ,
* so we have to start up their downstream HC - to - USB
* interfaces manually by doing a bus ( or " global " ) resume .
*/
if ( ! udev - > parent )
2008-11-26 00:39:18 +03:00
rc = hcd_bus_resume ( udev , msg ) ;
2007-05-04 19:52:20 +04:00
else
2008-11-26 00:39:18 +03:00
rc = usb_port_resume ( udev , msg ) ;
2007-05-04 19:51:54 +04:00
return rc ;
2006-07-02 06:09:35 +04:00
}
# endif /* CONFIG_PM */
2006-07-02 06:08:49 +04:00
struct usb_device_driver usb_generic_driver = {
2006-07-02 06:08:06 +04:00
. name = " usb " ,
. probe = generic_probe ,
2006-07-02 06:08:49 +04:00
. disconnect = generic_disconnect ,
2006-07-02 06:09:35 +04:00
# ifdef CONFIG_PM
. suspend = generic_suspend ,
. resume = generic_resume ,
# endif
2006-08-30 23:47:18 +04:00
. supports_autosuspend = 1 ,
2006-07-02 06:08:06 +04:00
} ;