2005-11-17 00:41:28 +03:00
/*
* drivers / usb / driver . c - most of the driver model stuff for usb
*
* ( 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
*
* NOTE ! This is not actually a driver at all , rather this is
* just a collection of helper routines that implement the
2006-07-02 06:08:06 +04:00
* matching , probing , releasing , suspending and resuming for
* real drivers .
2005-11-17 00:41:28 +03:00
*
*/
# include <linux/device.h>
# include <linux/usb.h>
2007-05-04 19:53:03 +04:00
# include <linux/usb/quirks.h>
2006-09-19 18:14:07 +04:00
# include <linux/workqueue.h>
2005-11-17 00:41:28 +03:00
# include "hcd.h"
# include "usb.h"
2007-05-22 19:50:17 +04:00
2005-11-17 00:41:28 +03:00
# ifdef CONFIG_HOTPLUG
/*
* Adds a new dynamic USBdevice ID to this driver ,
* and cause the driver to probe for all devices again .
*/
2006-12-17 23:50:23 +03:00
ssize_t usb_store_new_id ( struct usb_dynids * dynids ,
struct device_driver * driver ,
const char * buf , size_t count )
2005-11-17 00:41:28 +03:00
{
struct usb_dynid * dynid ;
u32 idVendor = 0 ;
u32 idProduct = 0 ;
int fields = 0 ;
2006-08-28 22:43:25 +04:00
int retval = 0 ;
2005-11-17 00:41:28 +03:00
fields = sscanf ( buf , " %x %x " , & idVendor , & idProduct ) ;
if ( fields < 2 )
return - EINVAL ;
dynid = kzalloc ( sizeof ( * dynid ) , GFP_KERNEL ) ;
if ( ! dynid )
return - ENOMEM ;
INIT_LIST_HEAD ( & dynid - > node ) ;
dynid - > id . idVendor = idVendor ;
dynid - > id . idProduct = idProduct ;
dynid - > id . match_flags = USB_DEVICE_ID_MATCH_DEVICE ;
2006-12-17 23:50:23 +03:00
spin_lock ( & dynids - > lock ) ;
2007-09-04 13:46:23 +04:00
list_add_tail ( & dynid - > node , & dynids - > list ) ;
2006-12-17 23:50:23 +03:00
spin_unlock ( & dynids - > lock ) ;
2005-11-17 00:41:28 +03:00
if ( get_driver ( driver ) ) {
2006-08-28 22:43:25 +04:00
retval = driver_attach ( driver ) ;
2005-11-17 00:41:28 +03:00
put_driver ( driver ) ;
}
2006-08-28 22:43:25 +04:00
if ( retval )
return retval ;
2005-11-17 00:41:28 +03:00
return count ;
}
2006-12-17 23:50:23 +03:00
EXPORT_SYMBOL_GPL ( usb_store_new_id ) ;
static ssize_t store_new_id ( struct device_driver * driver ,
const char * buf , size_t count )
{
struct usb_driver * usb_drv = to_usb_driver ( driver ) ;
return usb_store_new_id ( & usb_drv - > dynids , driver , buf , count ) ;
}
2005-11-17 00:41:28 +03:00
static DRIVER_ATTR ( new_id , S_IWUSR , NULL , store_new_id ) ;
static int usb_create_newid_file ( struct usb_driver * usb_drv )
{
int error = 0 ;
2005-11-17 00:41:28 +03:00
if ( usb_drv - > no_dynamic_id )
goto exit ;
2005-11-17 00:41:28 +03:00
if ( usb_drv - > probe ! = NULL )
2006-07-02 06:08:49 +04:00
error = sysfs_create_file ( & usb_drv - > drvwrap . driver . kobj ,
2005-11-17 00:41:28 +03:00
& driver_attr_new_id . attr ) ;
2005-11-17 00:41:28 +03:00
exit :
2005-11-17 00:41:28 +03:00
return error ;
}
2005-11-17 00:41:28 +03:00
static void usb_remove_newid_file ( struct usb_driver * usb_drv )
{
if ( usb_drv - > no_dynamic_id )
return ;
if ( usb_drv - > probe ! = NULL )
2006-07-02 06:08:49 +04:00
sysfs_remove_file ( & usb_drv - > drvwrap . driver . kobj ,
2005-11-17 00:41:28 +03:00
& driver_attr_new_id . attr ) ;
}
2005-11-17 00:41:28 +03:00
static void usb_free_dynids ( struct usb_driver * usb_drv )
{
struct usb_dynid * dynid , * n ;
spin_lock ( & usb_drv - > dynids . lock ) ;
list_for_each_entry_safe ( dynid , n , & usb_drv - > dynids . list , node ) {
list_del ( & dynid - > node ) ;
kfree ( dynid ) ;
}
spin_unlock ( & usb_drv - > dynids . lock ) ;
}
# else
static inline int usb_create_newid_file ( struct usb_driver * usb_drv )
{
return 0 ;
}
2005-11-17 00:41:28 +03:00
static void usb_remove_newid_file ( struct usb_driver * usb_drv )
{
}
2005-11-17 00:41:28 +03:00
static inline void usb_free_dynids ( struct usb_driver * usb_drv )
{
}
# endif
static const struct usb_device_id * usb_match_dynamic_id ( struct usb_interface * intf ,
struct usb_driver * drv )
{
struct usb_dynid * dynid ;
spin_lock ( & drv - > dynids . lock ) ;
list_for_each_entry ( dynid , & drv - > dynids . list , node ) {
if ( usb_match_one_id ( intf , & dynid - > id ) ) {
spin_unlock ( & drv - > dynids . lock ) ;
return & dynid - > id ;
}
}
spin_unlock ( & drv - > dynids . lock ) ;
return NULL ;
}
2006-07-02 06:08:49 +04:00
/* called from driver core with dev locked */
static int usb_probe_device ( struct device * dev )
{
struct usb_device_driver * udriver = to_usb_device_driver ( dev - > driver ) ;
struct usb_device * udev ;
int error = - ENODEV ;
dev_dbg ( dev , " %s \n " , __FUNCTION__ ) ;
if ( ! is_usb_device ( dev ) ) /* Sanity check */
return error ;
udev = to_usb_device ( dev ) ;
/* TODO: Add real matching code */
2006-08-30 23:47:02 +04:00
/* The device should always appear to be in use
* unless the driver suports autosuspend .
*/
udev - > pm_usage_cnt = ! ( udriver - > supports_autosuspend ) ;
2006-07-02 06:08:49 +04:00
error = udriver - > probe ( udev ) ;
return error ;
}
/* called from driver core with dev locked */
static int usb_unbind_device ( struct device * dev )
{
struct usb_device_driver * udriver = to_usb_device_driver ( dev - > driver ) ;
udriver - > disconnect ( to_usb_device ( dev ) ) ;
return 0 ;
}
/* called from driver core with dev locked */
2005-11-17 00:41:28 +03:00
static int usb_probe_interface ( struct device * dev )
{
2006-07-02 06:08:49 +04:00
struct usb_driver * driver = to_usb_driver ( dev - > driver ) ;
struct usb_interface * intf ;
2006-08-30 23:47:02 +04:00
struct usb_device * udev ;
2005-11-17 00:41:28 +03:00
const struct usb_device_id * id ;
int error = - ENODEV ;
dev_dbg ( dev , " %s \n " , __FUNCTION__ ) ;
2006-07-02 06:08:49 +04:00
if ( is_usb_device ( dev ) ) /* Sanity check */
2005-11-17 00:41:28 +03:00
return error ;
2006-07-02 06:08:49 +04:00
intf = to_usb_interface ( dev ) ;
2006-08-30 23:47:02 +04:00
udev = interface_to_usbdev ( intf ) ;
2005-11-17 00:41:28 +03:00
2007-08-01 07:34:03 +04:00
if ( udev - > authorized = = 0 ) {
dev_err ( & intf - > dev , " Device is not authorized for usage \n " ) ;
return - ENODEV ;
}
2005-11-17 00:41:28 +03:00
id = usb_match_id ( intf , driver - > id_table ) ;
2005-11-17 00:41:28 +03:00
if ( ! id )
id = usb_match_dynamic_id ( intf , driver ) ;
2005-11-17 00:41:28 +03:00
if ( id ) {
dev_dbg ( dev , " %s - got id \n " , __FUNCTION__ ) ;
2006-11-20 19:38:46 +03:00
error = usb_autoresume_device ( udev ) ;
2006-08-30 23:47:02 +04:00
if ( error )
return error ;
2005-11-17 00:41:28 +03:00
/* Interface "power state" doesn't correspond to any hardware
* state whatsoever . We use it to record when it ' s bound to
* a driver that may start I / 0 : it ' s not frozen / quiesced .
*/
mark_active ( intf ) ;
intf - > condition = USB_INTERFACE_BINDING ;
2006-08-30 23:47:02 +04:00
/* The interface should always appear to be in use
* unless the driver suports autosuspend .
*/
intf - > pm_usage_cnt = ! ( driver - > supports_autosuspend ) ;
2005-11-17 00:41:28 +03:00
error = driver - > probe ( intf , id ) ;
if ( error ) {
mark_quiesced ( intf ) ;
2006-08-30 23:47:02 +04:00
intf - > needs_remote_wakeup = 0 ;
2005-11-17 00:41:28 +03:00
intf - > condition = USB_INTERFACE_UNBOUND ;
} else
intf - > condition = USB_INTERFACE_BOUND ;
2006-08-30 23:47:02 +04:00
2006-11-20 19:38:46 +03:00
usb_autosuspend_device ( udev ) ;
2005-11-17 00:41:28 +03:00
}
return error ;
}
2006-07-02 06:08:49 +04:00
/* called from driver core with dev locked */
2005-11-17 00:41:28 +03:00
static int usb_unbind_interface ( struct device * dev )
{
2006-07-02 06:08:49 +04:00
struct usb_driver * driver = to_usb_driver ( dev - > driver ) ;
2005-11-17 00:41:28 +03:00
struct usb_interface * intf = to_usb_interface ( dev ) ;
2006-08-30 23:47:02 +04:00
struct usb_device * udev ;
int error ;
2005-11-17 00:41:28 +03:00
intf - > condition = USB_INTERFACE_UNBINDING ;
2006-08-30 23:47:02 +04:00
/* Autoresume for set_interface call below */
udev = interface_to_usbdev ( intf ) ;
2006-11-20 19:38:46 +03:00
error = usb_autoresume_device ( udev ) ;
2006-08-30 23:47:02 +04:00
2005-11-17 00:41:28 +03:00
/* release all urbs for this interface */
usb_disable_interface ( interface_to_usbdev ( intf ) , intf ) ;
2006-07-02 06:08:49 +04:00
driver - > disconnect ( intf ) ;
2005-11-17 00:41:28 +03:00
/* reset other interface state */
usb_set_interface ( interface_to_usbdev ( intf ) ,
intf - > altsetting [ 0 ] . desc . bInterfaceNumber ,
0 ) ;
usb_set_intfdata ( intf , NULL ) ;
2006-08-30 23:47:02 +04:00
2005-11-17 00:41:28 +03:00
intf - > condition = USB_INTERFACE_UNBOUND ;
mark_quiesced ( intf ) ;
2006-08-30 23:47:02 +04:00
intf - > needs_remote_wakeup = 0 ;
if ( ! error )
2006-11-20 19:38:46 +03:00
usb_autosuspend_device ( udev ) ;
2005-11-17 00:41:28 +03:00
return 0 ;
}
2006-07-02 06:08:06 +04:00
/**
* usb_driver_claim_interface - bind a driver to an interface
* @ driver : the driver to be bound
* @ iface : the interface to which it will be bound ; must be in the
* usb device ' s active configuration
* @ priv : driver data associated with that interface
*
* This is used by usb device drivers that need to claim more than one
* interface on a device when probing ( audio and acm are current examples ) .
* No device driver should directly modify internal usb_interface or
* usb_device structure members .
*
* Few drivers should need to use this routine , since the most natural
* way to bind to an interface is to return the private data from
* the driver ' s probe ( ) method .
*
2007-04-09 19:52:31 +04:00
* Callers must own the device lock , so driver probe ( ) entries don ' t need
* extra locking , but other call contexts may need to explicitly claim that
* lock .
2006-07-02 06:08:06 +04:00
*/
int usb_driver_claim_interface ( struct usb_driver * driver ,
struct usb_interface * iface , void * priv )
{
struct device * dev = & iface - > dev ;
2006-08-30 23:47:02 +04:00
struct usb_device * udev = interface_to_usbdev ( iface ) ;
2006-08-28 22:43:25 +04:00
int retval = 0 ;
2006-07-02 06:08:06 +04:00
if ( dev - > driver )
return - EBUSY ;
2006-07-02 06:08:49 +04:00
dev - > driver = & driver - > drvwrap . driver ;
2006-07-02 06:08:06 +04:00
usb_set_intfdata ( iface , priv ) ;
2006-08-30 23:47:02 +04:00
2006-09-26 22:50:20 +04:00
usb_pm_lock ( udev ) ;
2006-07-02 06:08:06 +04:00
iface - > condition = USB_INTERFACE_BOUND ;
mark_active ( iface ) ;
2006-08-30 23:47:02 +04:00
iface - > pm_usage_cnt = ! ( driver - > supports_autosuspend ) ;
2006-09-26 22:50:20 +04:00
usb_pm_unlock ( udev ) ;
2006-07-02 06:08:06 +04:00
/* if interface was already added, bind now; else let
* the future device_add ( ) bind it , bypassing probe ( )
*/
if ( device_is_registered ( dev ) )
2006-08-28 22:43:25 +04:00
retval = device_bind_driver ( dev ) ;
2006-07-02 06:08:06 +04:00
2006-08-28 22:43:25 +04:00
return retval ;
2006-07-02 06:08:06 +04:00
}
EXPORT_SYMBOL ( usb_driver_claim_interface ) ;
/**
* usb_driver_release_interface - unbind a driver from an interface
* @ driver : the driver to be unbound
* @ iface : the interface from which it will be unbound
*
* This can be used by drivers to release an interface without waiting
* for their disconnect ( ) methods to be called . In typical cases this
* also causes the driver disconnect ( ) method to be called .
*
* This call is synchronous , and may not be used in an interrupt context .
2007-04-09 19:52:31 +04:00
* Callers must own the device lock , so driver disconnect ( ) entries don ' t
* need extra locking , but other call contexts may need to explicitly claim
* that lock .
2006-07-02 06:08:06 +04:00
*/
void usb_driver_release_interface ( struct usb_driver * driver ,
struct usb_interface * iface )
{
struct device * dev = & iface - > dev ;
2006-08-30 23:47:02 +04:00
struct usb_device * udev = interface_to_usbdev ( iface ) ;
2006-07-02 06:08:06 +04:00
/* this should never happen, don't release something that's not ours */
2006-07-02 06:08:49 +04:00
if ( ! dev - > driver | | dev - > driver ! = & driver - > drvwrap . driver )
2006-07-02 06:08:06 +04:00
return ;
/* don't release from within disconnect() */
if ( iface - > condition ! = USB_INTERFACE_BOUND )
return ;
/* don't release if the interface hasn't been added yet */
if ( device_is_registered ( dev ) ) {
iface - > condition = USB_INTERFACE_UNBINDING ;
device_release_driver ( dev ) ;
}
dev - > driver = NULL ;
usb_set_intfdata ( iface , NULL ) ;
2006-08-30 23:47:02 +04:00
2006-09-26 22:50:20 +04:00
usb_pm_lock ( udev ) ;
2006-07-02 06:08:06 +04:00
iface - > condition = USB_INTERFACE_UNBOUND ;
mark_quiesced ( iface ) ;
2006-08-30 23:47:02 +04:00
iface - > needs_remote_wakeup = 0 ;
2006-09-26 22:50:20 +04:00
usb_pm_unlock ( udev ) ;
2006-07-02 06:08:06 +04:00
}
EXPORT_SYMBOL ( usb_driver_release_interface ) ;
2005-11-17 00:41:28 +03:00
/* returns 0 if no match, 1 if match */
2007-01-26 16:26:21 +03:00
int usb_match_device ( struct usb_device * dev , const struct usb_device_id * id )
2005-11-17 00:41:28 +03:00
{
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_VENDOR ) & &
id - > idVendor ! = le16_to_cpu ( dev - > descriptor . idVendor ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_PRODUCT ) & &
id - > idProduct ! = le16_to_cpu ( dev - > descriptor . idProduct ) )
return 0 ;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number . */
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_DEV_LO ) & &
( id - > bcdDevice_lo > le16_to_cpu ( dev - > descriptor . bcdDevice ) ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_DEV_HI ) & &
( id - > bcdDevice_hi < le16_to_cpu ( dev - > descriptor . bcdDevice ) ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS ) & &
( id - > bDeviceClass ! = dev - > descriptor . bDeviceClass ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS ) & &
( id - > bDeviceSubClass ! = dev - > descriptor . bDeviceSubClass ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL ) & &
( id - > bDeviceProtocol ! = dev - > descriptor . bDeviceProtocol ) )
return 0 ;
2007-01-26 16:26:21 +03:00
return 1 ;
}
/* returns 0 if no match, 1 if match */
int usb_match_one_id ( struct usb_interface * interface ,
const struct usb_device_id * id )
{
struct usb_host_interface * intf ;
struct usb_device * dev ;
/* proc_connectinfo in devio.c may call us with id == NULL. */
if ( id = = NULL )
return 0 ;
intf = interface - > cur_altsetting ;
dev = interface_to_usbdev ( interface ) ;
if ( ! usb_match_device ( dev , id ) )
return 0 ;
2006-10-19 00:41:51 +04:00
/* The interface class, subclass, and protocol should never be
* checked for a match if the device class is Vendor Specific ,
* unless the match record specifies the Vendor ID . */
if ( dev - > descriptor . bDeviceClass = = USB_CLASS_VENDOR_SPEC & &
! ( id - > match_flags & USB_DEVICE_ID_MATCH_VENDOR ) & &
( id - > match_flags & ( USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS |
USB_DEVICE_ID_MATCH_INT_PROTOCOL ) ) )
return 0 ;
2005-11-17 00:41:28 +03:00
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_INT_CLASS ) & &
( id - > bInterfaceClass ! = intf - > desc . bInterfaceClass ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS ) & &
( id - > bInterfaceSubClass ! = intf - > desc . bInterfaceSubClass ) )
return 0 ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL ) & &
( id - > bInterfaceProtocol ! = intf - > desc . bInterfaceProtocol ) )
return 0 ;
return 1 ;
}
2006-12-17 23:50:23 +03:00
EXPORT_SYMBOL_GPL ( usb_match_one_id ) ;
2005-11-17 00:41:28 +03:00
/**
* usb_match_id - find first usb_device_id matching device or interface
* @ interface : the interface of interest
* @ id : array of usb_device_id structures , terminated by zero entry
*
* usb_match_id searches an array of usb_device_id ' s and returns
* the first one matching the device or interface , or null .
* This is used when binding ( or rebinding ) a driver to an interface .
* Most USB device drivers will use this indirectly , through the usb core ,
* but some layered driver frameworks use it directly .
* These device tables are exported with MODULE_DEVICE_TABLE , through
* modutils , to support the driver loading functionality of USB hotplugging .
*
* What Matches :
*
* The " match_flags " element in a usb_device_id controls which
* members are used . If the corresponding bit is set , the
* value in the device_id must match its corresponding member
* in the device or interface descriptor , or else the device_id
* does not match .
*
* " driver_info " is normally used only by device drivers ,
* but you can create a wildcard " matches anything " usb_device_id
* as a driver ' s " modules.usbmap " entry if you provide an id with
* only a nonzero " driver_info " field . If you do this , the USB device
* driver ' s probe ( ) routine should use additional intelligence to
* decide whether to bind to the specified interface .
*
* What Makes Good usb_device_id Tables :
*
* The match algorithm is very simple , so that intelligence in
* driver selection must come from smart driver id records .
* Unless you have good reasons to use another selection policy ,
* provide match elements only in related groups , and order match
* specifiers from specific to general . Use the macros provided
* for that purpose if you can .
*
* The most specific match specifiers use device descriptor
* data . These are commonly used with product - specific matches ;
* the USB_DEVICE macro lets you provide vendor and product IDs ,
* and you can also match against ranges of product revisions .
* These are widely used for devices with application or vendor
* specific bDeviceClass values .
*
* Matches based on device class / subclass / protocol specifications
* are slightly more general ; use the USB_DEVICE_INFO macro , or
* its siblings . These are used with single - function devices
* where bDeviceClass doesn ' t specify that each interface has
* its own class .
*
* Matches based on interface class / subclass / protocol are the
* most general ; they let drivers bind to any interface on a
* multiple - function device . Use the USB_INTERFACE_INFO
* macro , or its siblings , to match class - per - interface style
2006-10-19 00:41:51 +04:00
* devices ( as recorded in bInterfaceClass ) .
*
* Note that an entry created by USB_INTERFACE_INFO won ' t match
* any interface if the device class is set to Vendor - Specific .
* This is deliberate ; according to the USB spec the meanings of
* the interface class / subclass / protocol for these devices are also
* vendor - specific , and hence matching against a standard product
* class wouldn ' t work anyway . If you really want to use an
* interface - based match for such a device , create a match record
* that also specifies the vendor ID . ( Unforunately there isn ' t a
* standard macro for creating records like this . )
2005-11-17 00:41:28 +03:00
*
* Within those groups , remember that not all combinations are
* meaningful . For example , don ' t give a product version range
* without vendor and product IDs ; or specify a protocol without
* its associated class and subclass .
*/
const struct usb_device_id * usb_match_id ( struct usb_interface * interface ,
const struct usb_device_id * id )
{
/* proc_connectinfo in devio.c may call us with id == NULL. */
if ( id = = NULL )
return NULL ;
/* It is important to check that id->driver_info is nonzero,
since an entry that is all zeroes except for a nonzero
id - > driver_info is the way to create an entry that
indicates that the driver want to examine every
device and interface . */
for ( ; id - > idVendor | | id - > bDeviceClass | | id - > bInterfaceClass | |
id - > driver_info ; id + + ) {
2005-11-17 00:41:28 +03:00
if ( usb_match_one_id ( interface , id ) )
return id ;
2005-11-17 00:41:28 +03:00
}
return NULL ;
}
2006-03-21 00:17:13 +03:00
EXPORT_SYMBOL_GPL_FUTURE ( usb_match_id ) ;
2005-11-17 00:41:28 +03:00
2006-11-22 00:02:54 +03:00
static int usb_device_match ( struct device * dev , struct device_driver * drv )
2005-11-17 00:41:28 +03:00
{
2006-07-02 06:08:49 +04:00
/* devices and interfaces are handled separately */
if ( is_usb_device ( dev ) ) {
2005-11-17 00:41:28 +03:00
2006-07-02 06:08:49 +04:00
/* interface drivers never match devices */
if ( ! is_usb_device_driver ( drv ) )
return 0 ;
2005-11-17 00:41:28 +03:00
2006-07-02 06:08:49 +04:00
/* TODO: Add real matching code */
2005-11-17 00:41:28 +03:00
return 1 ;
2006-07-02 06:08:49 +04:00
} else {
struct usb_interface * intf ;
struct usb_driver * usb_drv ;
const struct usb_device_id * id ;
/* device drivers never match interfaces */
if ( is_usb_device_driver ( drv ) )
return 0 ;
intf = to_usb_interface ( dev ) ;
usb_drv = to_usb_driver ( drv ) ;
id = usb_match_id ( intf , usb_drv - > id_table ) ;
if ( id )
return 1 ;
id = usb_match_dynamic_id ( intf , usb_drv ) ;
if ( id )
return 1 ;
}
2005-11-17 00:41:28 +03:00
return 0 ;
}
2006-07-02 06:08:06 +04:00
# ifdef CONFIG_HOTPLUG
2007-08-14 17:15:12 +04:00
static int usb_uevent ( struct device * dev , struct kobj_uevent_env * env )
2006-07-02 06:08:06 +04:00
{
struct usb_device * usb_dev ;
/* driver is often null here; dev_dbg() would oops */
pr_debug ( " usb %s: uevent \n " , dev - > bus_id ) ;
2007-03-13 17:59:31 +03:00
if ( is_usb_device ( dev ) )
2006-07-02 06:09:35 +04:00
usb_dev = to_usb_device ( dev ) ;
2007-03-13 17:59:31 +03:00
else {
struct usb_interface * intf = to_usb_interface ( dev ) ;
2006-07-02 06:08:49 +04:00
usb_dev = interface_to_usbdev ( intf ) ;
}
2006-07-02 06:08:06 +04:00
if ( usb_dev - > devnum < 0 ) {
pr_debug ( " usb %s: already deleted? \n " , dev - > bus_id ) ;
return - ENODEV ;
}
if ( ! usb_dev - > bus ) {
pr_debug ( " usb %s: bus removed? \n " , dev - > bus_id ) ;
return - ENODEV ;
}
# ifdef CONFIG_USB_DEVICEFS
/* If this is available, userspace programs can directly read
* all the device descriptors we don ' t tell them about . Or
2007-03-13 17:59:31 +03:00
* act as usermode drivers .
2006-07-02 06:08:06 +04:00
*/
2007-08-14 17:15:12 +04:00
if ( add_uevent_var ( env , " DEVICE=/proc/bus/usb/%03d/%03d " ,
2006-07-02 06:08:06 +04:00
usb_dev - > bus - > busnum , usb_dev - > devnum ) )
return - ENOMEM ;
# endif
/* per-device configurations are common */
2007-08-14 17:15:12 +04:00
if ( add_uevent_var ( env , " PRODUCT=%x/%x/%x " ,
2006-07-02 06:08:06 +04:00
le16_to_cpu ( usb_dev - > descriptor . idVendor ) ,
le16_to_cpu ( usb_dev - > descriptor . idProduct ) ,
le16_to_cpu ( usb_dev - > descriptor . bcdDevice ) ) )
return - ENOMEM ;
/* class-based driver binding models */
2007-08-14 17:15:12 +04:00
if ( add_uevent_var ( env , " TYPE=%d/%d/%d " ,
2006-07-02 06:08:06 +04:00
usb_dev - > descriptor . bDeviceClass ,
usb_dev - > descriptor . bDeviceSubClass ,
usb_dev - > descriptor . bDeviceProtocol ) )
return - ENOMEM ;
return 0 ;
}
# else
2007-08-14 17:15:12 +04:00
static int usb_uevent ( struct device * dev , struct kobj_uevent_env * env )
2006-07-02 06:08:06 +04:00
{
return - ENODEV ;
}
# endif /* CONFIG_HOTPLUG */
2005-11-17 00:41:28 +03:00
/**
2006-07-02 06:08:49 +04:00
* usb_register_device_driver - register a USB device ( not interface ) driver
* @ new_udriver : USB operations for the device driver
2005-11-22 01:53:03 +03:00
* @ owner : module owner of this driver .
2005-11-17 00:41:28 +03:00
*
2006-07-02 06:08:49 +04:00
* Registers a USB device driver with the USB core . The list of
* unattached devices will be rescanned whenever a new driver is
* added , allowing the new driver to attach to any recognized devices .
* Returns a negative error code on failure and 0 on success .
*/
int usb_register_device_driver ( struct usb_device_driver * new_udriver ,
struct module * owner )
{
int retval = 0 ;
if ( usb_disabled ( ) )
return - ENODEV ;
new_udriver - > drvwrap . for_devices = 1 ;
new_udriver - > drvwrap . driver . name = ( char * ) new_udriver - > name ;
new_udriver - > drvwrap . driver . bus = & usb_bus_type ;
new_udriver - > drvwrap . driver . probe = usb_probe_device ;
new_udriver - > drvwrap . driver . remove = usb_unbind_device ;
new_udriver - > drvwrap . driver . owner = owner ;
retval = driver_register ( & new_udriver - > drvwrap . driver ) ;
if ( ! retval ) {
pr_info ( " %s: registered new device driver %s \n " ,
usbcore_name , new_udriver - > name ) ;
usbfs_update_special ( ) ;
} else {
printk ( KERN_ERR " %s: error %d registering device "
" driver %s \n " ,
usbcore_name , retval , new_udriver - > name ) ;
}
return retval ;
}
EXPORT_SYMBOL_GPL ( usb_register_device_driver ) ;
/**
* usb_deregister_device_driver - unregister a USB device ( not interface ) driver
* @ udriver : USB operations of the device driver to unregister
* Context : must be able to sleep
*
* Unlinks the specified driver from the internal USB driver list .
*/
void usb_deregister_device_driver ( struct usb_device_driver * udriver )
{
pr_info ( " %s: deregistering device driver %s \n " ,
usbcore_name , udriver - > name ) ;
driver_unregister ( & udriver - > drvwrap . driver ) ;
usbfs_update_special ( ) ;
}
EXPORT_SYMBOL_GPL ( usb_deregister_device_driver ) ;
/**
* usb_register_driver - register a USB interface driver
* @ new_driver : USB operations for the interface driver
* @ owner : module owner of this driver .
2007-02-11 01:41:41 +03:00
* @ mod_name : module name string
2006-07-02 06:08:49 +04:00
*
* Registers a USB interface driver with the USB core . The list of
* unattached interfaces will be rescanned whenever a new driver is
* added , allowing the new driver to attach to any recognized interfaces .
2005-11-17 00:41:28 +03:00
* Returns a negative error code on failure and 0 on success .
*
* NOTE : if you want your driver to use the USB major number , you must call
* usb_register_dev ( ) to enable that functionality . This function no longer
* takes care of that .
*/
2007-01-15 22:50:02 +03:00
int usb_register_driver ( struct usb_driver * new_driver , struct module * owner ,
const char * mod_name )
2005-11-17 00:41:28 +03:00
{
int retval = 0 ;
if ( usb_disabled ( ) )
return - ENODEV ;
2006-07-02 06:08:49 +04:00
new_driver - > drvwrap . for_devices = 0 ;
new_driver - > drvwrap . driver . name = ( char * ) new_driver - > name ;
new_driver - > drvwrap . driver . bus = & usb_bus_type ;
new_driver - > drvwrap . driver . probe = usb_probe_interface ;
new_driver - > drvwrap . driver . remove = usb_unbind_interface ;
new_driver - > drvwrap . driver . owner = owner ;
2007-01-15 22:50:02 +03:00
new_driver - > drvwrap . driver . mod_name = mod_name ;
2005-11-17 00:41:28 +03:00
spin_lock_init ( & new_driver - > dynids . lock ) ;
INIT_LIST_HEAD ( & new_driver - > dynids . list ) ;
2005-11-17 00:41:28 +03:00
2006-07-02 06:08:49 +04:00
retval = driver_register ( & new_driver - > drvwrap . driver ) ;
2005-11-17 00:41:28 +03:00
if ( ! retval ) {
2006-07-02 06:08:49 +04:00
pr_info ( " %s: registered new interface driver %s \n " ,
2005-11-17 00:41:28 +03:00
usbcore_name , new_driver - > name ) ;
usbfs_update_special ( ) ;
2005-11-17 00:41:28 +03:00
usb_create_newid_file ( new_driver ) ;
2005-11-17 00:41:28 +03:00
} else {
2006-07-02 06:08:49 +04:00
printk ( KERN_ERR " %s: error %d registering interface "
" driver %s \n " ,
2005-11-17 00:41:28 +03:00
usbcore_name , retval , new_driver - > name ) ;
}
return retval ;
}
2006-03-21 00:17:13 +03:00
EXPORT_SYMBOL_GPL_FUTURE ( usb_register_driver ) ;
2005-11-17 00:41:28 +03:00
/**
2006-07-02 06:08:49 +04:00
* usb_deregister - unregister a USB interface driver
* @ driver : USB operations of the interface driver to unregister
2005-11-17 00:41:28 +03:00
* Context : must be able to sleep
*
* Unlinks the specified driver from the internal USB driver list .
*
* NOTE : If you called usb_register_dev ( ) , you still need to call
* usb_deregister_dev ( ) to clean up your driver ' s allocated minor numbers ,
* this * call will no longer do it for you .
*/
void usb_deregister ( struct usb_driver * driver )
{
2006-07-02 06:08:49 +04:00
pr_info ( " %s: deregistering interface driver %s \n " ,
usbcore_name , driver - > name ) ;
2005-11-17 00:41:28 +03:00
2005-11-17 00:41:28 +03:00
usb_remove_newid_file ( driver ) ;
2005-11-17 00:41:28 +03:00
usb_free_dynids ( driver ) ;
2006-07-02 06:08:49 +04:00
driver_unregister ( & driver - > drvwrap . driver ) ;
2005-11-17 00:41:28 +03:00
usbfs_update_special ( ) ;
}
2006-03-21 00:17:13 +03:00
EXPORT_SYMBOL_GPL_FUTURE ( usb_deregister ) ;
2006-07-02 06:08:06 +04:00
# ifdef CONFIG_PM
2006-09-26 22:50:20 +04:00
/* Caller has locked udev's pm_mutex */
2006-11-14 21:06:17 +03:00
static int usb_suspend_device ( struct usb_device * udev , pm_message_t msg )
2006-07-02 06:08:06 +04:00
{
2006-07-02 06:09:35 +04:00
struct usb_device_driver * udriver ;
2006-07-02 06:12:19 +04:00
int status = 0 ;
2006-07-02 06:08:06 +04:00
2006-07-02 06:13:04 +04:00
if ( udev - > state = = USB_STATE_NOTATTACHED | |
udev - > state = = USB_STATE_SUSPENDED )
goto done ;
2007-05-04 19:51:54 +04:00
/* For devices that don't have a driver, we do a generic suspend. */
if ( udev - > dev . driver )
udriver = to_usb_device_driver ( udev - > dev . driver ) ;
else {
2006-08-30 23:47:02 +04:00
udev - > do_remote_wakeup = 0 ;
2007-05-04 19:51:54 +04:00
udriver = & usb_generic_driver ;
2006-07-02 06:13:50 +04:00
}
2006-07-02 06:12:19 +04:00
status = udriver - > suspend ( udev , msg ) ;
2007-05-22 19:50:17 +04:00
done :
dev_vdbg ( & udev - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2006-07-02 06:12:19 +04:00
if ( status = = 0 )
udev - > dev . power . power_state . event = msg . event ;
return status ;
2006-07-02 06:10:15 +04:00
}
2006-09-26 22:50:20 +04:00
/* Caller has locked udev's pm_mutex */
2006-11-14 21:06:17 +03:00
static int usb_resume_device ( struct usb_device * udev )
2006-07-02 06:10:15 +04:00
{
struct usb_device_driver * udriver ;
2006-07-02 06:12:19 +04:00
int status = 0 ;
2006-07-02 06:08:06 +04:00
2007-05-04 19:52:20 +04:00
if ( udev - > state = = USB_STATE_NOTATTACHED )
goto done ;
if ( udev - > state ! = USB_STATE_SUSPENDED & & ! udev - > reset_resume )
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:10:15 +04:00
2006-07-02 06:13:50 +04:00
/* Can't resume it if it doesn't have a driver. */
if ( udev - > dev . driver = = NULL ) {
status = - ENOTCONN ;
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:13:50 +04:00
}
2007-05-04 19:53:03 +04:00
if ( udev - > quirks & USB_QUIRK_RESET_RESUME )
udev - > reset_resume = 1 ;
2006-07-02 06:10:15 +04:00
udriver = to_usb_device_driver ( udev - > dev . driver ) ;
2006-07-02 06:12:19 +04:00
status = udriver - > resume ( udev ) ;
2007-05-22 19:50:17 +04:00
done :
dev_vdbg ( & udev - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2007-03-20 21:59:39 +03:00
if ( status = = 0 ) {
udev - > autoresume_disabled = 0 ;
2006-07-02 06:12:19 +04:00
udev - > dev . power . power_state . event = PM_EVENT_ON ;
2007-03-20 21:59:39 +03:00
}
2006-07-02 06:12:19 +04:00
return status ;
2006-07-02 06:10:15 +04:00
}
2006-09-26 22:50:20 +04:00
/* Caller has locked intf's usb_device's pm mutex */
2006-11-14 21:06:17 +03:00
static int usb_suspend_interface ( struct usb_interface * intf , pm_message_t msg )
2006-07-02 06:10:15 +04:00
{
struct usb_driver * driver ;
2006-07-02 06:12:19 +04:00
int status = 0 ;
2006-07-02 06:10:15 +04:00
2006-07-02 06:13:04 +04:00
/* with no hardware, USB interfaces only use FREEZE and ON states */
if ( interface_to_usbdev ( intf ) - > state = = USB_STATE_NOTATTACHED | |
! is_active ( intf ) )
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:10:15 +04:00
2006-08-30 23:47:02 +04:00
if ( intf - > condition = = USB_INTERFACE_UNBOUND ) /* This can't happen */
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:13:04 +04:00
driver = to_usb_driver ( intf - > dev . driver ) ;
2006-07-02 06:08:06 +04:00
if ( driver - > suspend & & driver - > resume ) {
2006-07-02 06:10:15 +04:00
status = driver - > suspend ( intf , msg ) ;
2006-08-30 23:47:02 +04:00
if ( status = = 0 )
mark_quiesced ( intf ) ;
else if ( ! interface_to_usbdev ( intf ) - > auto_pm )
2006-07-02 06:10:15 +04:00
dev_err ( & intf - > dev , " %s error %d \n " ,
" suspend " , status ) ;
2006-07-02 06:08:06 +04:00
} else {
// FIXME else if there's no suspend method, disconnect...
2006-08-30 23:47:02 +04:00
// Not possible if auto_pm is set...
2006-07-02 06:10:15 +04:00
dev_warn ( & intf - > dev , " no suspend for driver %s? \n " ,
driver - > name ) ;
2006-07-02 06:08:06 +04:00
mark_quiesced ( intf ) ;
}
2006-07-02 06:12:19 +04:00
2007-05-22 19:50:17 +04:00
done :
dev_vdbg ( & intf - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2006-07-02 06:08:06 +04:00
return status ;
}
2006-08-30 23:47:02 +04:00
/* Caller has locked intf's usb_device's pm_mutex */
2007-05-04 19:52:20 +04:00
static int usb_resume_interface ( struct usb_interface * intf , int reset_resume )
2006-07-02 06:08:06 +04:00
{
2006-07-02 06:10:15 +04:00
struct usb_driver * driver ;
2006-07-02 06:12:19 +04:00
int status = 0 ;
2006-07-02 06:08:06 +04:00
2006-07-02 06:13:04 +04:00
if ( interface_to_usbdev ( intf ) - > state = = USB_STATE_NOTATTACHED | |
is_active ( intf ) )
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:08:06 +04:00
2006-08-30 23:47:02 +04:00
/* Don't let autoresume interfere with unbinding */
if ( intf - > condition = = USB_INTERFACE_UNBINDING )
goto done ;
2006-07-02 06:13:50 +04:00
/* Can't resume it if it doesn't have a driver. */
2006-08-30 23:47:02 +04:00
if ( intf - > condition = = USB_INTERFACE_UNBOUND ) {
2006-07-02 06:13:50 +04:00
status = - ENOTCONN ;
2006-07-02 06:12:19 +04:00
goto done ;
2006-07-02 06:13:50 +04:00
}
2006-07-02 06:10:15 +04:00
driver = to_usb_driver ( intf - > dev . driver ) ;
2006-07-02 06:08:06 +04:00
2007-05-30 23:38:16 +04:00
if ( reset_resume ) {
if ( driver - > reset_resume ) {
status = driver - > reset_resume ( intf ) ;
if ( status )
dev_err ( & intf - > dev , " %s error %d \n " ,
" reset_resume " , status ) ;
} else {
// status = -EOPNOTSUPP;
dev_warn ( & intf - > dev , " no %s for driver %s? \n " ,
" reset_resume " , driver - > name ) ;
}
} else {
if ( driver - > resume ) {
status = driver - > resume ( intf ) ;
if ( status )
dev_err ( & intf - > dev , " %s error %d \n " ,
" resume " , status ) ;
} else {
// status = -EOPNOTSUPP;
dev_warn ( & intf - > dev , " no %s for driver %s? \n " ,
" resume " , driver - > name ) ;
}
}
2006-07-02 06:12:19 +04:00
done :
2007-05-22 19:50:17 +04:00
dev_vdbg ( & intf - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2007-05-04 19:52:20 +04:00
if ( status = = 0 )
mark_active ( intf ) ;
2007-05-30 23:38:16 +04:00
/* FIXME: Unbind the driver and reprobe if the resume failed
* ( not possible if auto_pm is set ) */
2006-07-02 06:12:19 +04:00
return status ;
2006-07-02 06:08:06 +04:00
}
2006-11-20 19:38:46 +03:00
# ifdef CONFIG_USB_SUSPEND
2006-10-31 01:06:45 +03:00
/* Internal routine to check whether we may autosuspend a device. */
2007-10-12 00:47:36 +04:00
static int autosuspend_check ( struct usb_device * udev , int reschedule )
2006-10-31 01:06:45 +03:00
{
int i ;
struct usb_interface * intf ;
2007-10-12 00:47:36 +04:00
unsigned long suspend_time , j ;
2006-10-31 01:06:45 +03:00
2007-02-20 23:00:53 +03:00
/* For autosuspend, fail fast if anything is in use or autosuspend
* is disabled . Also fail if any interfaces require remote wakeup
* but it isn ' t available .
*/
2006-10-31 01:06:45 +03:00
udev - > do_remote_wakeup = device_may_wakeup ( & udev - > dev ) ;
if ( udev - > pm_usage_cnt > 0 )
return - EBUSY ;
2007-03-20 21:59:39 +03:00
if ( udev - > autosuspend_delay < 0 | | udev - > autosuspend_disabled )
2007-02-20 23:00:53 +03:00
return - EPERM ;
2007-03-27 21:33:59 +04:00
suspend_time = udev - > last_busy + udev - > autosuspend_delay ;
2006-10-31 01:06:45 +03:00
if ( udev - > actconfig ) {
for ( i = 0 ; i < udev - > actconfig - > desc . bNumInterfaces ; i + + ) {
intf = udev - > actconfig - > interface [ i ] ;
if ( ! is_active ( intf ) )
continue ;
if ( intf - > pm_usage_cnt > 0 )
return - EBUSY ;
if ( intf - > needs_remote_wakeup & &
! udev - > do_remote_wakeup ) {
dev_dbg ( & udev - > dev , " remote wakeup needed "
" for autosuspend \n " ) ;
return - EOPNOTSUPP ;
}
2007-05-30 23:38:16 +04:00
/* Don't allow autosuspend if the device will need
* a reset - resume and any of its interface drivers
* doesn ' t include support .
*/
if ( udev - > quirks & USB_QUIRK_RESET_RESUME ) {
struct usb_driver * driver ;
driver = to_usb_driver ( intf - > dev . driver ) ;
if ( ! driver - > reset_resume )
return - EOPNOTSUPP ;
}
2006-10-31 01:06:45 +03:00
}
}
2007-03-27 21:33:59 +04:00
/* If everything is okay but the device hasn't been idle for long
2007-10-12 00:47:36 +04:00
* enough , queue a delayed autosuspend request . If the device
* _has_ been idle for long enough and the reschedule flag is set ,
* likewise queue a delayed ( 1 second ) autosuspend request .
2007-03-27 21:33:59 +04:00
*/
2007-10-12 00:47:36 +04:00
j = jiffies ;
if ( time_before ( j , suspend_time ) )
reschedule = 1 ;
else
suspend_time = j + HZ ;
if ( reschedule ) {
2007-04-11 20:06:16 +04:00
if ( ! timer_pending ( & udev - > autosuspend . timer ) ) {
2007-03-27 21:33:59 +04:00
queue_delayed_work ( ksuspend_usb_wq , & udev - > autosuspend ,
2007-10-12 00:47:36 +04:00
round_jiffies_relative ( suspend_time - j ) ) ;
}
2007-03-27 21:33:59 +04:00
return - EAGAIN ;
}
2006-10-31 01:06:45 +03:00
return 0 ;
}
2006-11-20 19:38:46 +03:00
# else
2007-10-12 00:47:36 +04:00
static inline int autosuspend_check ( struct usb_device * udev , int reschedule )
2007-04-06 00:03:49 +04:00
{
return 0 ;
}
2006-11-20 19:38:46 +03:00
2007-02-20 23:00:53 +03:00
# endif /* CONFIG_USB_SUSPEND */
2006-11-20 19:38:46 +03:00
2006-08-30 23:47:02 +04:00
/**
* usb_suspend_both - suspend a USB device and its interfaces
* @ udev : the usb_device to suspend
* @ msg : Power Management message describing this state transition
*
* This is the central routine for suspending USB devices . It calls the
* suspend methods for all the interface drivers in @ udev and then calls
* the suspend method for @ udev itself . If an error occurs at any stage ,
* all the interfaces which were suspended are resumed so that they remain
* in the same state as the device .
*
* If an autosuspend is in progress ( @ udev - > auto_pm is set ) , the routine
* checks first to make sure that neither the device itself or any of its
* active interfaces is in use ( pm_usage_cnt is greater than 0 ) . If they
* are , the autosuspend fails .
*
* If the suspend succeeds , the routine recursively queues an autosuspend
* request for @ udev ' s parent device , thereby propagating the change up
* the device tree . If all of the parent ' s children are now suspended ,
* the parent will autosuspend in turn .
*
* The suspend method calls are subject to mutual exclusion under control
* of @ udev ' s pm_mutex . Many of these calls are also under the protection
* of @ udev ' s device lock ( including all requests originating outside the
* USB subsystem ) , but autosuspend requests generated by a child device or
* interface driver may not be . Usbcore will insure that the method calls
* do not arrive during bind , unbind , or reset operations . However , drivers
* must be prepared to handle suspend calls arriving at unpredictable times .
* The only way to block such calls is to do an autoresume ( preventing
* autosuspends ) while holding @ udev ' s device lock ( preventing outside
* suspends ) .
*
* The caller must hold @ udev - > pm_mutex .
*
* This routine can run only in process context .
*/
2007-03-09 23:41:13 +03:00
static int usb_suspend_both ( struct usb_device * udev , pm_message_t msg )
2006-07-02 06:11:02 +04:00
{
int status = 0 ;
int i = 0 ;
struct usb_interface * intf ;
2006-08-30 23:47:02 +04:00
struct usb_device * parent = udev - > parent ;
2007-03-27 21:33:59 +04:00
if ( udev - > state = = USB_STATE_NOTATTACHED | |
udev - > state = = USB_STATE_SUSPENDED )
goto done ;
2006-07-02 06:11:02 +04:00
2006-08-30 23:47:02 +04:00
udev - > do_remote_wakeup = device_may_wakeup ( & udev - > dev ) ;
if ( udev - > auto_pm ) {
2007-10-12 00:47:36 +04:00
status = autosuspend_check ( udev , 0 ) ;
2006-10-31 01:06:45 +03:00
if ( status < 0 )
2007-03-27 21:33:59 +04:00
goto done ;
2006-08-30 23:47:02 +04:00
}
/* Suspend all the interfaces and then udev itself */
2006-07-02 06:11:02 +04:00
if ( udev - > actconfig ) {
for ( ; i < udev - > actconfig - > desc . bNumInterfaces ; i + + ) {
intf = udev - > actconfig - > interface [ i ] ;
2006-11-14 21:06:17 +03:00
status = usb_suspend_interface ( intf , msg ) ;
2006-07-02 06:11:02 +04:00
if ( status ! = 0 )
break ;
}
}
2007-09-10 19:31:43 +04:00
if ( status = = 0 )
2006-11-14 21:06:17 +03:00
status = usb_suspend_device ( udev , msg ) ;
2006-07-02 06:11:02 +04:00
/* If the suspend failed, resume interfaces that did get suspended */
if ( status ! = 0 ) {
while ( - - i > = 0 ) {
intf = udev - > actconfig - > interface [ i ] ;
2007-05-04 19:52:20 +04:00
usb_resume_interface ( intf , 0 ) ;
2006-07-02 06:11:02 +04:00
}
2006-08-30 23:47:02 +04:00
2007-04-06 00:03:49 +04:00
/* Try another autosuspend when the interfaces aren't busy */
if ( udev - > auto_pm )
2007-10-12 00:47:36 +04:00
autosuspend_check ( udev , status = = - EBUSY ) ;
2007-04-06 00:03:49 +04:00
2007-09-10 19:34:26 +04:00
/* If the suspend succeeded then prevent any more URB submissions,
* flush any outstanding URBs , and propagate the suspend up the tree .
*/
2007-04-06 00:03:49 +04:00
} else {
cancel_delayed_work ( & udev - > autosuspend ) ;
2007-09-10 19:34:26 +04:00
udev - > can_submit = 0 ;
for ( i = 0 ; i < 16 ; + + i ) {
usb_hcd_flush_endpoint ( udev , udev - > ep_out [ i ] ) ;
usb_hcd_flush_endpoint ( udev , udev - > ep_in [ i ] ) ;
}
2007-09-20 20:37:50 +04:00
/* If this is just a FREEZE or a PRETHAW, udev might
* not really be suspended . Only true suspends get
* propagated up the device tree .
*/
if ( parent & & udev - > state = = USB_STATE_SUSPENDED )
2007-04-06 00:03:49 +04:00
usb_autosuspend_device ( parent ) ;
}
2006-08-30 23:47:02 +04:00
2007-03-27 21:33:59 +04:00
done :
2007-05-22 19:50:17 +04:00
dev_vdbg ( & udev - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2006-07-02 06:11:02 +04:00
return status ;
}
2006-08-30 23:47:02 +04:00
/**
* usb_resume_both - resume a USB device and its interfaces
* @ udev : the usb_device to resume
*
* This is the central routine for resuming USB devices . It calls the
* the resume method for @ udev and then calls the resume methods for all
* the interface drivers in @ udev .
*
* Before starting the resume , the routine calls itself recursively for
* the parent device of @ udev , thereby propagating the change up the device
* tree and assuring that @ udev will be able to resume . If the parent is
* unable to resume successfully , the routine fails .
*
* The resume method calls are subject to mutual exclusion under control
* of @ udev ' s pm_mutex . Many of these calls are also under the protection
* of @ udev ' s device lock ( including all requests originating outside the
* USB subsystem ) , but autoresume requests generated by a child device or
* interface driver may not be . Usbcore will insure that the method calls
* do not arrive during bind , unbind , or reset operations . However , drivers
* must be prepared to handle resume calls arriving at unpredictable times .
* The only way to block such calls is to do an autoresume ( preventing
* other autoresumes ) while holding @ udev ' s device lock ( preventing outside
* resumes ) .
*
* The caller must hold @ udev - > pm_mutex .
*
* This routine can run only in process context .
*/
2007-03-09 23:41:13 +03:00
static int usb_resume_both ( struct usb_device * udev )
2006-07-02 06:11:02 +04:00
{
2006-08-30 23:47:02 +04:00
int status = 0 ;
2006-07-02 06:11:02 +04:00
int i ;
struct usb_interface * intf ;
2006-08-30 23:47:02 +04:00
struct usb_device * parent = udev - > parent ;
cancel_delayed_work ( & udev - > autosuspend ) ;
2007-03-27 21:33:59 +04:00
if ( udev - > state = = USB_STATE_NOTATTACHED ) {
status = - ENODEV ;
goto done ;
}
2007-09-10 19:34:26 +04:00
udev - > can_submit = 1 ;
2006-07-02 06:11:02 +04:00
2006-08-30 23:47:02 +04:00
/* Propagate the resume up the tree, if necessary */
if ( udev - > state = = USB_STATE_SUSPENDED ) {
2007-03-27 21:33:59 +04:00
if ( udev - > auto_pm & & udev - > autoresume_disabled ) {
status = - EPERM ;
goto done ;
}
2006-08-30 23:47:02 +04:00
if ( parent ) {
2006-11-20 19:38:46 +03:00
status = usb_autoresume_device ( parent ) ;
2006-11-23 00:55:54 +03:00
if ( status = = 0 ) {
status = usb_resume_device ( udev ) ;
2007-05-30 23:38:16 +04:00
if ( status | | udev - > state = =
USB_STATE_NOTATTACHED ) {
2006-11-20 19:38:46 +03:00
usb_autosuspend_device ( parent ) ;
2006-11-23 00:55:54 +03:00
/* It's possible usb_resume_device()
* failed after the port was
* unsuspended , causing udev to be
* logically disconnected . We don ' t
* want usb_disconnect ( ) to autosuspend
* the parent again , so tell it that
* udev disconnected while still
* suspended . */
if ( udev - > state = =
USB_STATE_NOTATTACHED )
udev - > discon_suspended = 1 ;
}
}
2006-08-30 23:47:02 +04:00
} else {
/* We can't progagate beyond the USB subsystem,
* so if a root hub ' s controller is suspended
* then we ' re stuck . */
2007-06-22 00:25:17 +04:00
status = usb_resume_device ( udev ) ;
2006-11-23 00:55:54 +03:00
}
2006-09-19 18:08:43 +04:00
} else {
2007-05-04 19:52:20 +04:00
/* Needed for setting udev->dev.power.power_state.event,
* for possible debugging message , and for reset_resume . */
2006-11-14 21:06:17 +03:00
status = usb_resume_device ( udev ) ;
2006-07-02 06:13:04 +04:00
}
2006-07-02 06:11:02 +04:00
if ( status = = 0 & & udev - > actconfig ) {
for ( i = 0 ; i < udev - > actconfig - > desc . bNumInterfaces ; i + + ) {
intf = udev - > actconfig - > interface [ i ] ;
2007-05-04 19:52:20 +04:00
usb_resume_interface ( intf , udev - > reset_resume ) ;
2006-07-02 06:11:02 +04:00
}
}
2006-08-30 23:47:02 +04:00
2007-03-27 21:33:59 +04:00
done :
2007-05-22 19:50:17 +04:00
dev_vdbg ( & udev - > dev , " %s: status %d \n " , __FUNCTION__ , status ) ;
2007-05-04 19:52:20 +04:00
udev - > reset_resume = 0 ;
2006-08-30 23:47:02 +04:00
return status ;
}
# ifdef CONFIG_USB_SUSPEND
2006-11-20 19:38:46 +03:00
/* Internal routine to adjust a device's usage counter and change
* its autosuspend state .
*/
static int usb_autopm_do_device ( struct usb_device * udev , int inc_usage_cnt )
{
int status = 0 ;
usb_pm_lock ( udev ) ;
2007-03-27 21:33:59 +04:00
udev - > auto_pm = 1 ;
2006-11-20 19:38:46 +03:00
udev - > pm_usage_cnt + = inc_usage_cnt ;
WARN_ON ( udev - > pm_usage_cnt < 0 ) ;
2007-08-20 20:18:39 +04:00
if ( inc_usage_cnt )
udev - > last_busy = jiffies ;
2006-11-20 19:38:46 +03:00
if ( inc_usage_cnt > = 0 & & udev - > pm_usage_cnt > 0 ) {
2007-03-27 21:33:59 +04:00
if ( udev - > state = = USB_STATE_SUSPENDED )
status = usb_resume_both ( udev ) ;
2006-11-20 19:38:46 +03:00
if ( status ! = 0 )
udev - > pm_usage_cnt - = inc_usage_cnt ;
2007-03-27 21:33:59 +04:00
else if ( inc_usage_cnt )
udev - > last_busy = jiffies ;
} else if ( inc_usage_cnt < = 0 & & udev - > pm_usage_cnt < = 0 ) {
status = usb_suspend_both ( udev , PMSG_SUSPEND ) ;
}
2006-11-20 19:38:46 +03:00
usb_pm_unlock ( udev ) ;
return status ;
}
2007-03-27 21:33:59 +04:00
/* usb_autosuspend_work - callback routine to autosuspend a USB device */
void usb_autosuspend_work ( struct work_struct * work )
{
struct usb_device * udev =
container_of ( work , struct usb_device , autosuspend . work ) ;
usb_autopm_do_device ( udev , 0 ) ;
}
2006-08-30 23:47:02 +04:00
/**
* usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
2006-09-26 04:00:56 +04:00
* @ udev : the usb_device to autosuspend
2006-08-30 23:47:02 +04:00
*
* This routine should be called when a core subsystem is finished using
* @ udev and wants to allow it to autosuspend . Examples would be when
* @ udev ' s device file in usbfs is closed or after a configuration change .
*
2006-11-20 19:38:46 +03:00
* @ udev ' s usage counter is decremented . If it or any of the usage counters
* for an active interface is greater than 0 , no autosuspend request will be
* queued . ( If an interface driver does not support autosuspend then its
* usage counter is permanently positive . ) Furthermore , if an interface
* driver requires remote - wakeup capability during autosuspend but remote
* wakeup is disabled , the autosuspend will fail .
2006-08-30 23:47:02 +04:00
*
* Often the caller will hold @ udev ' s device lock , but this is not
* necessary .
*
* This routine can run only in process context .
*/
2006-11-20 19:38:46 +03:00
void usb_autosuspend_device ( struct usb_device * udev )
2006-08-30 23:47:02 +04:00
{
2006-11-20 19:38:46 +03:00
int status ;
status = usb_autopm_do_device ( udev , - 1 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & udev - > dev , " %s: cnt %d \n " ,
__FUNCTION__ , udev - > pm_usage_cnt ) ;
2007-02-20 23:03:32 +03:00
}
/**
* usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces
* @ udev : the usb_device to autosuspend
*
* This routine should be called when a core subsystem thinks @ udev may
* be ready to autosuspend .
*
* @ udev ' s usage counter left unchanged . If it or any of the usage counters
* for an active interface is greater than 0 , or autosuspend is not allowed
* for any other reason , no autosuspend request will be queued .
*
* This routine can run only in process context .
*/
void usb_try_autosuspend_device ( struct usb_device * udev )
{
usb_autopm_do_device ( udev , 0 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & udev - > dev , " %s: cnt %d \n " ,
__FUNCTION__ , udev - > pm_usage_cnt ) ;
2006-08-30 23:47:02 +04:00
}
/**
* usb_autoresume_device - immediately autoresume a USB device and its interfaces
2006-09-26 04:00:56 +04:00
* @ udev : the usb_device to autoresume
2006-08-30 23:47:02 +04:00
*
* This routine should be called when a core subsystem wants to use @ udev
2006-11-20 19:38:46 +03:00
* and needs to guarantee that it is not suspended . No autosuspend will
* occur until usb_autosuspend_device is called . ( Note that this will not
* prevent suspend events originating in the PM core . ) Examples would be
* when @ udev ' s device file in usbfs is opened or when a remote - wakeup
* request is received .
2006-08-30 23:47:02 +04:00
*
2006-11-20 19:38:46 +03:00
* @ udev ' s usage counter is incremented to prevent subsequent autosuspends .
* However if the autoresume fails then the usage counter is re - decremented .
2006-08-30 23:47:02 +04:00
*
* Often the caller will hold @ udev ' s device lock , but this is not
* necessary ( and attempting it might cause deadlock ) .
*
* This routine can run only in process context .
*/
2006-11-20 19:38:46 +03:00
int usb_autoresume_device ( struct usb_device * udev )
2006-08-30 23:47:02 +04:00
{
int status ;
2006-11-20 19:38:46 +03:00
status = usb_autopm_do_device ( udev , 1 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & udev - > dev , " %s: status %d cnt %d \n " ,
__FUNCTION__ , status , udev - > pm_usage_cnt ) ;
2006-08-30 23:47:02 +04:00
return status ;
}
2006-10-31 01:06:45 +03:00
/* Internal routine to adjust an interface's usage counter and change
* its device ' s autosuspend state .
*/
static int usb_autopm_do_interface ( struct usb_interface * intf ,
int inc_usage_cnt )
{
struct usb_device * udev = interface_to_usbdev ( intf ) ;
int status = 0 ;
usb_pm_lock ( udev ) ;
if ( intf - > condition = = USB_INTERFACE_UNBOUND )
status = - ENODEV ;
else {
2007-03-27 21:33:59 +04:00
udev - > auto_pm = 1 ;
2006-10-31 01:06:45 +03:00
intf - > pm_usage_cnt + = inc_usage_cnt ;
2007-08-20 20:18:39 +04:00
udev - > last_busy = jiffies ;
2006-10-31 01:06:45 +03:00
if ( inc_usage_cnt > = 0 & & intf - > pm_usage_cnt > 0 ) {
2007-03-27 21:33:59 +04:00
if ( udev - > state = = USB_STATE_SUSPENDED )
status = usb_resume_both ( udev ) ;
2006-10-31 01:06:45 +03:00
if ( status ! = 0 )
intf - > pm_usage_cnt - = inc_usage_cnt ;
2007-08-20 20:18:39 +04:00
else
2007-03-27 21:33:59 +04:00
udev - > last_busy = jiffies ;
} else if ( inc_usage_cnt < = 0 & & intf - > pm_usage_cnt < = 0 ) {
status = usb_suspend_both ( udev , PMSG_SUSPEND ) ;
}
2006-10-31 01:06:45 +03:00
}
usb_pm_unlock ( udev ) ;
return status ;
}
2006-08-30 23:47:02 +04:00
/**
* usb_autopm_put_interface - decrement a USB interface ' s PM - usage counter
2006-09-26 04:00:56 +04:00
* @ intf : the usb_interface whose counter should be decremented
2006-08-30 23:47:02 +04:00
*
* This routine should be called by an interface driver when it is
* finished using @ intf and wants to allow it to autosuspend . A typical
* example would be a character - device driver when its device file is
* closed .
*
* The routine decrements @ intf ' s usage counter . When the counter reaches
* 0 , a delayed autosuspend request for @ intf ' s device is queued . When
* the delay expires , if @ intf - > pm_usage_cnt is still < = 0 along with all
* the other usage counters for the sibling interfaces and @ intf ' s
* usb_device , the device and all its interfaces will be autosuspended .
*
* Note that @ intf - > pm_usage_cnt is owned by the interface driver . The
* core will not change its value other than the increment and decrement
* in usb_autopm_get_interface and usb_autopm_put_interface . The driver
* may use this simple counter - oriented discipline or may set the value
* any way it likes .
*
* If the driver has set @ intf - > needs_remote_wakeup then autosuspend will
* take place only if the device ' s remote - wakeup facility is enabled .
*
* Suspend method calls queued by this routine can arrive at any time
* while @ intf is resumed and its usage counter is equal to 0. They are
* not protected by the usb_device ' s lock but only by its pm_mutex .
* Drivers must provide their own synchronization .
*
* This routine can run only in process context .
*/
void usb_autopm_put_interface ( struct usb_interface * intf )
{
2006-10-31 01:06:45 +03:00
int status ;
2006-08-30 23:47:02 +04:00
2006-10-31 01:06:45 +03:00
status = usb_autopm_do_interface ( intf , - 1 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & intf - > dev , " %s: status %d cnt %d \n " ,
__FUNCTION__ , status , intf - > pm_usage_cnt ) ;
2006-08-30 23:47:02 +04:00
}
EXPORT_SYMBOL_GPL ( usb_autopm_put_interface ) ;
/**
* usb_autopm_get_interface - increment a USB interface ' s PM - usage counter
2006-09-26 04:00:56 +04:00
* @ intf : the usb_interface whose counter should be incremented
2006-08-30 23:47:02 +04:00
*
* This routine should be called by an interface driver when it wants to
* use @ intf and needs to guarantee that it is not suspended . In addition ,
* the routine prevents @ intf from being autosuspended subsequently . ( Note
* that this will not prevent suspend events originating in the PM core . )
* This prevention will persist until usb_autopm_put_interface ( ) is called
* or @ intf is unbound . A typical example would be a character - device
* driver when its device file is opened .
*
2007-03-27 21:33:59 +04:00
*
* The routine increments @ intf ' s usage counter . ( However if the
* autoresume fails then the counter is re - decremented . ) So long as the
* counter is greater than 0 , autosuspend will not be allowed for @ intf
* or its usb_device . When the driver is finished using @ intf it should
* call usb_autopm_put_interface ( ) to decrement the usage counter and
* queue a delayed autosuspend request ( if the counter is < = 0 ) .
*
2006-08-30 23:47:02 +04:00
*
* Note that @ intf - > pm_usage_cnt is owned by the interface driver . The
* core will not change its value other than the increment and decrement
* in usb_autopm_get_interface and usb_autopm_put_interface . The driver
* may use this simple counter - oriented discipline or may set the value
* any way it likes .
*
* Resume method calls generated by this routine can arrive at any time
* while @ intf is suspended . They are not protected by the usb_device ' s
* lock but only by its pm_mutex . Drivers must provide their own
* synchronization .
*
* This routine can run only in process context .
*/
int usb_autopm_get_interface ( struct usb_interface * intf )
{
2006-10-31 01:06:45 +03:00
int status ;
2006-08-30 23:47:02 +04:00
2006-10-31 01:06:45 +03:00
status = usb_autopm_do_interface ( intf , 1 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & intf - > dev , " %s: status %d cnt %d \n " ,
__FUNCTION__ , status , intf - > pm_usage_cnt ) ;
2006-07-02 06:11:02 +04:00
return status ;
}
2006-08-30 23:47:02 +04:00
EXPORT_SYMBOL_GPL ( usb_autopm_get_interface ) ;
2006-10-31 01:07:51 +03:00
/**
* usb_autopm_set_interface - set a USB interface ' s autosuspend state
* @ intf : the usb_interface whose state should be set
*
* This routine sets the autosuspend state of @ intf ' s device according
* to @ intf ' s usage counter , which the caller must have set previously .
* If the counter is < = 0 , the device is autosuspended ( if it isn ' t
* already suspended and if nothing else prevents the autosuspend ) . If
* the counter is > 0 , the device is autoresumed ( if it isn ' t already
* awake ) .
*/
int usb_autopm_set_interface ( struct usb_interface * intf )
{
int status ;
status = usb_autopm_do_interface ( intf , 0 ) ;
2007-05-22 19:50:17 +04:00
dev_vdbg ( & intf - > dev , " %s: status %d cnt %d \n " ,
__FUNCTION__ , status , intf - > pm_usage_cnt ) ;
2006-10-31 01:07:51 +03:00
return status ;
}
EXPORT_SYMBOL_GPL ( usb_autopm_set_interface ) ;
2007-03-09 23:41:13 +03:00
# else
void usb_autosuspend_work ( struct work_struct * work )
{ }
2006-08-30 23:47:02 +04:00
# endif /* CONFIG_USB_SUSPEND */
2006-07-02 06:11:02 +04:00
2007-03-13 23:37:30 +03:00
/**
* usb_external_suspend_device - external suspend of a USB device and its interfaces
* @ udev : the usb_device to suspend
* @ msg : Power Management message describing this state transition
*
* This routine handles external suspend requests : ones not generated
* internally by a USB driver ( autosuspend ) but rather coming from the user
* ( via sysfs ) or the PM core ( system sleep ) . The suspend will be carried
* out regardless of @ udev ' s usage counter or those of its interfaces ,
* and regardless of whether or not remote wakeup is enabled . Of course ,
* interface drivers still have the option of failing the suspend ( if
* there are unsuspended children , for example ) .
*
* The caller must hold @ udev ' s device lock .
*/
int usb_external_suspend_device ( struct usb_device * udev , pm_message_t msg )
2006-07-02 06:10:15 +04:00
{
int status ;
2007-03-13 23:37:30 +03:00
usb_pm_lock ( udev ) ;
udev - > auto_pm = 0 ;
status = usb_suspend_both ( udev , msg ) ;
usb_pm_unlock ( udev ) ;
2006-07-02 06:10:15 +04:00
return status ;
}
2007-03-13 23:37:30 +03:00
/**
* usb_external_resume_device - external resume of a USB device and its interfaces
* @ udev : the usb_device to resume
*
* This routine handles external resume requests : ones not generated
* internally by a USB driver ( autoresume ) but rather coming from the user
* ( via sysfs ) , the PM core ( system resume ) , or the device itself ( remote
* wakeup ) . @ udev ' s usage counter is unaffected .
*
* The caller must hold @ udev ' s device lock .
*/
int usb_external_resume_device ( struct usb_device * udev )
2006-07-02 06:10:15 +04:00
{
int status ;
2007-03-13 23:37:30 +03:00
usb_pm_lock ( udev ) ;
udev - > auto_pm = 0 ;
status = usb_resume_both ( udev ) ;
2007-04-06 00:03:49 +04:00
udev - > last_busy = jiffies ;
2007-03-13 23:37:30 +03:00
usb_pm_unlock ( udev ) ;
2006-07-02 06:11:02 +04:00
2007-03-13 23:37:30 +03:00
/* Now that the device is awake, we can start trying to autosuspend
* it again . */
if ( status = = 0 )
usb_try_autosuspend_device ( udev ) ;
2006-07-02 06:10:15 +04:00
return status ;
}
2007-03-13 23:37:30 +03:00
static int usb_suspend ( struct device * dev , pm_message_t message )
{
2007-10-11 00:30:12 +04:00
struct usb_device * udev ;
2007-03-13 23:37:30 +03:00
if ( ! is_usb_device ( dev ) ) /* Ignore PM for interfaces */
return 0 ;
2007-10-11 00:30:12 +04:00
udev = to_usb_device ( dev ) ;
/* If udev is already suspended, we can skip this suspend and
* we should also skip the upcoming system resume . */
if ( udev - > state = = USB_STATE_SUSPENDED ) {
udev - > skip_sys_resume = 1 ;
return 0 ;
}
udev - > skip_sys_resume = 0 ;
return usb_external_suspend_device ( udev , message ) ;
2007-03-13 23:37:30 +03:00
}
static int usb_resume ( struct device * dev )
{
2007-03-20 21:59:39 +03:00
struct usb_device * udev ;
2007-03-13 23:37:30 +03:00
if ( ! is_usb_device ( dev ) ) /* Ignore PM for interfaces */
return 0 ;
2007-03-20 21:59:39 +03:00
udev = to_usb_device ( dev ) ;
2007-05-04 19:52:20 +04:00
2007-10-11 00:30:12 +04:00
/* If udev->skip_sys_resume is set then udev was already suspended
* when the system suspend started , so we don ' t want to resume
* udev during this system wakeup . However a reset - resume counts
* as a wakeup event , so allow a reset - resume to occur if remote
* wakeup is enabled . */
if ( udev - > skip_sys_resume ) {
2007-05-04 19:52:20 +04:00
if ( ! ( udev - > reset_resume & & udev - > do_remote_wakeup ) )
2007-10-11 00:30:12 +04:00
return - EHOSTUNREACH ;
2007-05-04 19:52:20 +04:00
}
2007-03-20 21:59:39 +03:00
return usb_external_resume_device ( udev ) ;
2007-03-13 23:37:30 +03:00
}
# else
# define usb_suspend NULL
# define usb_resume NULL
2006-07-02 06:08:06 +04:00
# endif /* CONFIG_PM */
struct bus_type usb_bus_type = {
. name = " usb " ,
. match = usb_device_match ,
. uevent = usb_uevent ,
2006-07-02 06:09:35 +04:00
. suspend = usb_suspend ,
. resume = usb_resume ,
2006-07-02 06:08:06 +04:00
} ;