2005-04-17 02:20:36 +04:00
/*
2006-10-04 01:01:26 +04:00
* drivers / usb / core / usb . c
2005-04-17 02:20:36 +04:00
*
* ( 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
* generic USB things that the real drivers can use . .
*
* Think of this as a " USB library " rather than anything else .
* It should be considered a slave , with no callbacks . Callbacks
* are evil .
*/
# include <linux/module.h>
2007-02-20 23:00:53 +03:00
# include <linux/moduleparam.h>
2005-04-17 02:20:36 +04:00
# include <linux/string.h>
# include <linux/bitops.h>
# include <linux/slab.h>
# include <linux/interrupt.h> /* for in_interrupt() */
# include <linux/kmod.h>
# include <linux/init.h>
# include <linux/spinlock.h>
# include <linux/errno.h>
# include <linux/usb.h>
2006-01-11 17:55:29 +03:00
# include <linux/mutex.h>
2006-09-19 18:14:07 +04:00
# include <linux/workqueue.h>
2005-04-17 02:20:36 +04:00
# include <asm/io.h>
2007-10-30 12:35:04 +03:00
# include <linux/scatterlist.h>
2005-04-17 02:20:36 +04:00
# include <linux/mm.h>
# include <linux/dma-mapping.h>
# include "hcd.h"
# include "usb.h"
const char * usbcore_name = " usbcore " ;
static int nousb ; /* Disable USB when built into kernel image */
2007-03-13 23:37:30 +03:00
/* Workqueue for autosuspend and for remote wakeup of root hubs */
struct workqueue_struct * ksuspend_usb_wq ;
2006-09-19 18:14:07 +04:00
2007-02-20 23:00:53 +03:00
# ifdef CONFIG_USB_SUSPEND
static int usb_autosuspend_delay = 2 ; /* Default delay value,
* in seconds */
2007-03-13 23:39:15 +03:00
module_param_named ( autosuspend , usb_autosuspend_delay , int , 0644 ) ;
2007-02-20 23:00:53 +03:00
MODULE_PARM_DESC ( autosuspend , " default autosuspend delay " ) ;
# else
# define usb_autosuspend_delay 0
# endif
2005-04-17 02:20:36 +04:00
/**
* usb_ifnum_to_if - get the interface object with a given interface number
* @ dev : the device whose current configuration is considered
* @ ifnum : the desired interface
*
* This walks the device descriptor for the currently active configuration
* and returns a pointer to the interface with that particular interface
* number , or null .
*
* Note that configuration descriptors are not required to assign interface
* numbers sequentially , so that it would be incorrect to assume that
* the first interface in that descriptor corresponds to interface zero .
* This routine helps device drivers avoid such mistakes .
* However , you should make sure that you do the right thing with any
* alternate settings available for this interfaces .
*
* Don ' t call this function unless you are bound to one of the interfaces
* on this device or you have locked the device !
*/
2006-08-27 06:48:11 +04:00
struct usb_interface * usb_ifnum_to_if ( const struct usb_device * dev ,
unsigned ifnum )
2005-04-17 02:20:36 +04:00
{
struct usb_host_config * config = dev - > actconfig ;
int i ;
if ( ! config )
return NULL ;
for ( i = 0 ; i < config - > desc . bNumInterfaces ; i + + )
if ( config - > interface [ i ] - > altsetting [ 0 ]
. desc . bInterfaceNumber = = ifnum )
return config - > interface [ i ] ;
return NULL ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_ifnum_to_if ) ;
2005-04-17 02:20:36 +04:00
/**
2008-03-01 09:03:07 +03:00
* usb_altnum_to_altsetting - get the altsetting structure with a given alternate setting number .
2005-04-17 02:20:36 +04:00
* @ intf : the interface containing the altsetting in question
* @ altnum : the desired alternate setting number
*
* This searches the altsetting array of the specified interface for
* an entry with the correct bAlternateSetting value and returns a pointer
* to that entry , or null .
*
* Note that altsettings need not be stored sequentially by number , so
* it would be incorrect to assume that the first altsetting entry in
* the array corresponds to altsetting zero . This routine helps device
* drivers avoid such mistakes .
*
* Don ' t call this function unless you are bound to the intf interface
* or you have locked the device !
*/
2008-01-31 02:21:33 +03:00
struct usb_host_interface * usb_altnum_to_altsetting (
const struct usb_interface * intf ,
unsigned int altnum )
2005-04-17 02:20:36 +04:00
{
int i ;
for ( i = 0 ; i < intf - > num_altsetting ; i + + ) {
if ( intf - > altsetting [ i ] . desc . bAlternateSetting = = altnum )
return & intf - > altsetting [ i ] ;
}
return NULL ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_altnum_to_altsetting ) ;
2005-04-17 02:20:36 +04:00
2005-12-22 04:24:54 +03:00
struct find_interface_arg {
int minor ;
struct usb_interface * interface ;
} ;
2005-04-17 02:20:36 +04:00
2008-01-31 02:21:33 +03:00
static int __find_interface ( struct device * dev , void * data )
2005-03-21 22:09:40 +03:00
{
2005-12-22 04:24:54 +03:00
struct find_interface_arg * arg = data ;
struct usb_interface * intf ;
2005-03-21 22:09:40 +03:00
/* can't look at usb devices, only interfaces */
2006-07-02 06:08:49 +04:00
if ( is_usb_device ( dev ) )
2005-03-21 22:09:40 +03:00
return 0 ;
intf = to_usb_interface ( dev ) ;
2005-12-22 04:24:54 +03:00
if ( intf - > minor ! = - 1 & & intf - > minor = = arg - > minor ) {
arg - > interface = intf ;
2005-03-21 22:09:40 +03:00
return 1 ;
}
return 0 ;
}
2005-04-17 02:20:36 +04:00
/**
* usb_find_interface - find usb_interface pointer for driver and device
* @ drv : the driver whose current configuration is considered
* @ minor : the minor number of the desired device
*
2008-01-31 02:21:33 +03:00
* This walks the driver device list and returns a pointer to the interface
2005-04-17 02:20:36 +04:00
* with the matching minor . Note , this only works for devices that share the
* USB major number .
*/
struct usb_interface * usb_find_interface ( struct usb_driver * drv , int minor )
{
2005-12-22 04:24:54 +03:00
struct find_interface_arg argb ;
2006-08-28 22:43:25 +04:00
int retval ;
2005-04-17 02:20:36 +04:00
2005-12-22 04:24:54 +03:00
argb . minor = minor ;
argb . interface = NULL ;
2006-08-28 22:43:25 +04:00
/* eat the error, it will be in argb.interface */
retval = driver_for_each_device ( & drv - > drvwrap . driver , NULL , & argb ,
__find_interface ) ;
2005-12-22 04:24:54 +03:00
return argb . interface ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_find_interface ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_release_dev - free a usb device structure when all users of it are finished .
* @ dev : device that ' s been disconnected
*
* Will be called only by the device core when all users of this usb device are
* done .
*/
static void usb_release_dev ( struct device * dev )
{
struct usb_device * udev ;
udev = to_usb_device ( dev ) ;
usb_destroy_configuration ( udev ) ;
2006-08-30 19:32:52 +04:00
usb_put_hcd ( bus_to_hcd ( udev - > bus ) ) ;
2005-04-17 02:20:36 +04:00
kfree ( udev - > product ) ;
kfree ( udev - > manufacturer ) ;
kfree ( udev - > serial ) ;
kfree ( udev ) ;
}
2007-11-06 23:01:52 +03:00
# ifdef CONFIG_HOTPLUG
static int usb_dev_uevent ( struct device * dev , struct kobj_uevent_env * env )
{
struct usb_device * usb_dev ;
usb_dev = to_usb_device ( dev ) ;
if ( add_uevent_var ( env , " BUSNUM=%03d " , usb_dev - > bus - > busnum ) )
return - ENOMEM ;
if ( add_uevent_var ( env , " DEVNUM=%03d " , usb_dev - > devnum ) )
return - ENOMEM ;
return 0 ;
}
# else
static int usb_dev_uevent ( struct device * dev , struct kobj_uevent_env * env )
{
return - ENODEV ;
}
# endif /* CONFIG_HOTPLUG */
2007-03-13 17:59:31 +03:00
struct device_type usb_device_type = {
. name = " usb_device " ,
. release = usb_release_dev ,
2007-11-06 23:01:52 +03:00
. uevent = usb_dev_uevent ,
2007-03-13 17:59:31 +03:00
} ;
2006-08-30 23:47:02 +04:00
# ifdef CONFIG_PM
2006-09-19 18:14:07 +04:00
static int ksuspend_usb_init ( void )
{
2007-05-22 17:38:39 +04:00
/* This workqueue is supposed to be both freezable and
* singlethreaded . Its job doesn ' t justify running on more
* than one CPU .
*/
2008-02-25 02:35:04 +03:00
ksuspend_usb_wq = create_freezeable_workqueue ( " ksuspend_usbd " ) ;
2006-09-19 18:14:07 +04:00
if ( ! ksuspend_usb_wq )
return - ENOMEM ;
return 0 ;
}
static void ksuspend_usb_cleanup ( void )
{
destroy_workqueue ( ksuspend_usb_wq ) ;
}
2006-11-13 23:02:04 +03:00
# else
# define ksuspend_usb_init() 0
# define ksuspend_usb_cleanup() do {} while (0)
# endif /* CONFIG_PM */
2006-08-30 23:47:02 +04:00
2007-08-01 07:34:00 +04:00
/* Returns 1 if @usb_bus is WUSB, 0 otherwise */
static unsigned usb_bus_is_wusb ( struct usb_bus * bus )
{
struct usb_hcd * hcd = container_of ( bus , struct usb_hcd , self ) ;
return hcd - > wireless ;
}
2005-04-17 02:20:36 +04:00
/**
* usb_alloc_dev - usb device constructor ( usbcore - internal )
* @ parent : hub to which device is connected ; null to allocate a root hub
* @ bus : bus used to access the device
* @ port1 : one - based index of port ; ignored for root hubs
2007-01-23 23:55:28 +03:00
* Context : ! in_interrupt ( )
2005-04-17 02:20:36 +04:00
*
* Only hub drivers ( including virtual root hub drivers for host
* controllers ) should ever call this .
*
* This call may not be used in a non - sleeping context .
*/
2008-01-31 02:21:33 +03:00
struct usb_device * usb_alloc_dev ( struct usb_device * parent ,
struct usb_bus * bus , unsigned port1 )
2005-04-17 02:20:36 +04:00
{
struct usb_device * dev ;
2007-08-01 07:34:00 +04:00
struct usb_hcd * usb_hcd = container_of ( bus , struct usb_hcd , self ) ;
unsigned root_hub = 0 ;
2005-04-17 02:20:36 +04:00
2005-10-24 23:38:24 +04:00
dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
2005-04-17 02:20:36 +04:00
if ( ! dev )
return NULL ;
2006-08-30 19:32:52 +04:00
if ( ! usb_get_hcd ( bus_to_hcd ( bus ) ) ) {
2005-04-17 02:20:36 +04:00
kfree ( dev ) ;
return NULL ;
}
device_initialize ( & dev - > dev ) ;
dev - > dev . bus = & usb_bus_type ;
2007-03-13 17:59:31 +03:00
dev - > dev . type = & usb_device_type ;
2005-04-17 02:20:36 +04:00
dev - > dev . dma_mask = bus - > controller - > dma_mask ;
2007-07-09 23:03:09 +04:00
set_dev_node ( & dev - > dev , dev_to_node ( bus - > controller ) ) ;
2005-04-17 02:20:36 +04:00
dev - > state = USB_STATE_ATTACHED ;
2007-10-04 01:56:03 +04:00
atomic_set ( & dev - > urbnum , 0 ) ;
2005-04-17 02:20:36 +04:00
INIT_LIST_HEAD ( & dev - > ep0 . urb_list ) ;
dev - > ep0 . desc . bLength = USB_DT_ENDPOINT_SIZE ;
dev - > ep0 . desc . bDescriptorType = USB_DT_ENDPOINT ;
/* ep0 maxpacket comes later, from device descriptor */
2007-07-31 01:05:22 +04:00
usb_enable_endpoint ( dev , & dev - > ep0 ) ;
2007-09-10 19:34:26 +04:00
dev - > can_submit = 1 ;
2005-04-17 02:20:36 +04:00
/* Save readable and stable topology id, distinguishing devices
* by location for diagnostics , tools , driver model , etc . The
* string is a path along hub ports , from the root . Each device ' s
* dev - > devpath will be stable until USB is re - cabled , and hubs
* are often labeled with these port numbers . The bus_id isn ' t
* as stable : bus - > busnum changes easily from modprobe order ,
* cardbus or pci hotplugging , and so on .
*/
2007-01-23 23:55:28 +03:00
if ( unlikely ( ! parent ) ) {
dev - > devpath [ 0 ] = ' 0 ' ;
2005-04-17 02:20:36 +04:00
dev - > dev . parent = bus - > controller ;
2007-01-23 23:55:28 +03:00
sprintf ( & dev - > dev . bus_id [ 0 ] , " usb%d " , bus - > busnum ) ;
2007-08-01 07:34:00 +04:00
root_hub = 1 ;
2005-04-17 02:20:36 +04:00
} else {
/* match any labeling on the hubs; it's one-based */
2007-01-23 23:55:28 +03:00
if ( parent - > devpath [ 0 ] = = ' 0 ' )
snprintf ( dev - > devpath , sizeof dev - > devpath ,
2005-04-17 02:20:36 +04:00
" %d " , port1 ) ;
else
2007-01-23 23:55:28 +03:00
snprintf ( dev - > devpath , sizeof dev - > devpath ,
2005-04-17 02:20:36 +04:00
" %s.%d " , parent - > devpath , port1 ) ;
dev - > dev . parent = & parent - > dev ;
2007-01-23 23:55:28 +03:00
sprintf ( & dev - > dev . bus_id [ 0 ] , " %d-%s " ,
2005-04-17 02:20:36 +04:00
bus - > busnum , dev - > devpath ) ;
/* hub driver sets up TT records */
}
2005-11-23 20:09:52 +03:00
dev - > portnum = port1 ;
2005-04-17 02:20:36 +04:00
dev - > bus = bus ;
dev - > parent = parent ;
INIT_LIST_HEAD ( & dev - > filelist ) ;
2006-08-30 23:47:02 +04:00
# ifdef CONFIG_PM
mutex_init ( & dev - > pm_mutex ) ;
2006-11-22 17:57:56 +03:00
INIT_DELAYED_WORK ( & dev - > autosuspend , usb_autosuspend_work ) ;
2007-02-20 23:00:53 +03:00
dev - > autosuspend_delay = usb_autosuspend_delay * HZ ;
2007-12-22 03:54:15 +03:00
dev - > connect_time = jiffies ;
dev - > active_duration = - jiffies ;
2006-08-30 23:47:02 +04:00
# endif
2007-08-01 07:34:00 +04:00
if ( root_hub ) /* Root hub always ok [and always wired] */
dev - > authorized = 1 ;
else {
dev - > authorized = usb_hcd - > authorized_default ;
dev - > wusb = usb_bus_is_wusb ( bus ) ? 1 : 0 ;
}
2005-04-17 02:20:36 +04:00
return dev ;
}
/**
* usb_get_dev - increments the reference count of the usb device structure
* @ dev : the device being referenced
*
* Each live reference to a device should be refcounted .
*
* Drivers for USB interfaces should normally record such references in
* their probe ( ) methods , when they bind to an interface , and release
* them by calling usb_put_dev ( ) , in their disconnect ( ) methods .
*
* A pointer to the device with the incremented reference counter is returned .
*/
struct usb_device * usb_get_dev ( struct usb_device * dev )
{
if ( dev )
get_device ( & dev - > dev ) ;
return dev ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_get_dev ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_put_dev - release a use of the usb device structure
* @ dev : device that ' s been disconnected
*
* Must be called when a user of a device is finished with it . When the last
* user of the device calls this function , the memory of the device is freed .
*/
void usb_put_dev ( struct usb_device * dev )
{
if ( dev )
put_device ( & dev - > dev ) ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_put_dev ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_get_intf - increments the reference count of the usb interface structure
* @ intf : the interface being referenced
*
* Each live reference to a interface must be refcounted .
*
* Drivers for USB interfaces should normally record such references in
* their probe ( ) methods , when they bind to an interface , and release
* them by calling usb_put_intf ( ) , in their disconnect ( ) methods .
*
* A pointer to the interface with the incremented reference counter is
* returned .
*/
struct usb_interface * usb_get_intf ( struct usb_interface * intf )
{
if ( intf )
get_device ( & intf - > dev ) ;
return intf ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_get_intf ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_put_intf - release a use of the usb interface structure
* @ intf : interface that ' s been decremented
*
* Must be called when a user of an interface is finished with it . When the
* last user of the interface calls this function , the memory of the interface
* is freed .
*/
void usb_put_intf ( struct usb_interface * intf )
{
if ( intf )
put_device ( & intf - > dev ) ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_put_intf ) ;
2005-04-17 02:20:36 +04:00
/* USB device locking
*
2005-11-18 01:10:32 +03:00
* USB devices and interfaces are locked using the semaphore in their
* embedded struct device . The hub driver guarantees that whenever a
* device is connected or disconnected , drivers are called with the
* USB device locked as well as their particular interface .
2005-04-17 02:20:36 +04:00
*
* Complications arise when several devices are to be locked at the same
* time . Only hub - aware drivers that are part of usbcore ever have to
2005-11-18 01:10:32 +03:00
* do this ; nobody else needs to worry about it . The rule for locking
* is simple :
2005-04-17 02:20:36 +04:00
*
* When locking both a device and its parent , always lock the
* the parent first .
*/
/**
2008-03-01 09:03:07 +03:00
* usb_lock_device_for_reset - cautiously acquire the lock for a usb device structure
2005-04-17 02:20:36 +04:00
* @ udev : device that ' s being locked
* @ iface : interface bound to the driver making the request ( optional )
*
* Attempts to acquire the device lock , but fails if the device is
* NOTATTACHED or SUSPENDED , or if iface is specified and the interface
* is neither BINDING nor BOUND . Rather than sleeping to wait for the
* lock , the routine polls repeatedly . This is to prevent deadlock with
* disconnect ; in some drivers ( such as usb - storage ) the disconnect ( )
2005-08-11 18:15:39 +04:00
* or suspend ( ) method will block waiting for a device reset to complete .
2005-04-17 02:20:36 +04:00
*
* Returns a negative error code for failure , otherwise 1 or 0 to indicate
* that the device will or will not have to be unlocked . ( 0 can be
* returned when an interface is given and is BINDING , because in that
* case the driver already owns the device lock . )
*/
int usb_lock_device_for_reset ( struct usb_device * udev ,
2006-08-27 06:48:11 +04:00
const struct usb_interface * iface )
2005-04-17 02:20:36 +04:00
{
2005-08-11 18:15:39 +04:00
unsigned long jiffies_expire = jiffies + HZ ;
2005-04-17 02:20:36 +04:00
if ( udev - > state = = USB_STATE_NOTATTACHED )
return - ENODEV ;
if ( udev - > state = = USB_STATE_SUSPENDED )
return - EHOSTUNREACH ;
if ( iface ) {
switch ( iface - > condition ) {
2008-01-31 02:21:33 +03:00
case USB_INTERFACE_BINDING :
2005-04-17 02:20:36 +04:00
return 0 ;
2008-01-31 02:21:33 +03:00
case USB_INTERFACE_BOUND :
2005-04-17 02:20:36 +04:00
break ;
2008-01-31 02:21:33 +03:00
default :
2005-04-17 02:20:36 +04:00
return - EINTR ;
}
}
2005-11-18 01:10:32 +03:00
while ( usb_trylock_device ( udev ) ! = 0 ) {
2005-08-11 18:15:39 +04:00
/* If we can't acquire the lock after waiting one second,
* we ' re probably deadlocked */
if ( time_after ( jiffies , jiffies_expire ) )
return - EBUSY ;
2005-04-17 02:20:36 +04:00
msleep ( 15 ) ;
if ( udev - > state = = USB_STATE_NOTATTACHED )
return - ENODEV ;
if ( udev - > state = = USB_STATE_SUSPENDED )
return - EHOSTUNREACH ;
if ( iface & & iface - > condition ! = USB_INTERFACE_BOUND )
return - EINTR ;
}
return 1 ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_lock_device_for_reset ) ;
2005-04-17 02:20:36 +04:00
static struct usb_device * match_device ( struct usb_device * dev ,
u16 vendor_id , u16 product_id )
{
struct usb_device * ret_dev = NULL ;
int child ;
dev_dbg ( & dev - > dev , " check for vendor %04x, product %04x ... \n " ,
le16_to_cpu ( dev - > descriptor . idVendor ) ,
le16_to_cpu ( dev - > descriptor . idProduct ) ) ;
/* see if this device matches */
if ( ( vendor_id = = le16_to_cpu ( dev - > descriptor . idVendor ) ) & &
( product_id = = le16_to_cpu ( dev - > descriptor . idProduct ) ) ) {
2007-01-23 23:55:28 +03:00
dev_dbg ( & dev - > dev , " matched this device! \n " ) ;
2005-04-17 02:20:36 +04:00
ret_dev = usb_get_dev ( dev ) ;
goto exit ;
}
/* look through all of the children of this device */
for ( child = 0 ; child < dev - > maxchild ; + + child ) {
if ( dev - > children [ child ] ) {
2005-11-18 01:10:32 +03:00
usb_lock_device ( dev - > children [ child ] ) ;
2005-04-17 02:20:36 +04:00
ret_dev = match_device ( dev - > children [ child ] ,
vendor_id , product_id ) ;
2005-11-18 01:10:32 +03:00
usb_unlock_device ( dev - > children [ child ] ) ;
2005-04-17 02:20:36 +04:00
if ( ret_dev )
goto exit ;
}
}
exit :
return ret_dev ;
}
/**
* usb_find_device - find a specific usb device in the system
* @ vendor_id : the vendor id of the device to find
* @ product_id : the product id of the device to find
*
* Returns a pointer to a struct usb_device if such a specified usb
* device is present in the system currently . The usage count of the
* device will be incremented if a device is found . Make sure to call
* usb_put_dev ( ) when the caller is finished with the device .
*
* If a device with the specified vendor and product id is not found ,
* NULL is returned .
*/
struct usb_device * usb_find_device ( u16 vendor_id , u16 product_id )
{
struct list_head * buslist ;
struct usb_bus * bus ;
struct usb_device * dev = NULL ;
2008-01-31 02:21:33 +03:00
2006-01-11 17:55:29 +03:00
mutex_lock ( & usb_bus_list_lock ) ;
2005-04-17 02:20:36 +04:00
for ( buslist = usb_bus_list . next ;
2008-01-31 02:21:33 +03:00
buslist ! = & usb_bus_list ;
2005-04-17 02:20:36 +04:00
buslist = buslist - > next ) {
bus = container_of ( buslist , struct usb_bus , bus_list ) ;
if ( ! bus - > root_hub )
continue ;
usb_lock_device ( bus - > root_hub ) ;
dev = match_device ( bus - > root_hub , vendor_id , product_id ) ;
usb_unlock_device ( bus - > root_hub ) ;
if ( dev )
goto exit ;
}
exit :
2006-01-11 17:55:29 +03:00
mutex_unlock ( & usb_bus_list_lock ) ;
2005-04-17 02:20:36 +04:00
return dev ;
}
/**
* usb_get_current_frame_number - return current bus frame number
* @ dev : the device whose bus is being queried
*
* Returns the current frame number for the USB host controller
* used with the given USB device . This can be used when scheduling
* isochronous requests .
*
* Note that different kinds of host controller have different
* " scheduling horizons " . While one type might support scheduling only
* 32 frames into the future , others could support scheduling up to
* 1024 frames into the future .
*/
int usb_get_current_frame_number ( struct usb_device * dev )
{
2007-01-23 23:55:28 +03:00
return usb_hcd_get_frame_number ( dev ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_get_current_frame_number ) ;
2005-04-17 02:20:36 +04:00
/*-------------------------------------------------------------------*/
/*
* __usb_get_extra_descriptor ( ) finds a descriptor of specific type in the
* extra field of the interface and endpoint descriptor structs .
*/
int __usb_get_extra_descriptor ( char * buffer , unsigned size ,
2008-01-31 02:21:33 +03:00
unsigned char type , void * * ptr )
2005-04-17 02:20:36 +04:00
{
struct usb_descriptor_header * header ;
while ( size > = sizeof ( struct usb_descriptor_header ) ) {
header = ( struct usb_descriptor_header * ) buffer ;
if ( header - > bLength < 2 ) {
printk ( KERN_ERR
" %s: bogus descriptor, type %d length %d \n " ,
usbcore_name ,
2008-01-31 02:21:33 +03:00
header - > bDescriptorType ,
2005-04-17 02:20:36 +04:00
header - > bLength ) ;
return - 1 ;
}
if ( header - > bDescriptorType = = type ) {
* ptr = header ;
return 0 ;
}
buffer + = header - > bLength ;
size - = header - > bLength ;
}
return - 1 ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( __usb_get_extra_descriptor ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_buffer_alloc - allocate dma - consistent buffer for URB_NO_xxx_DMA_MAP
* @ dev : device the buffer will be used with
* @ size : requested buffer size
* @ mem_flags : affect whether allocation may block
* @ dma : used to return DMA address of buffer
*
* Return value is either null ( indicating no buffer could be allocated ) , or
* the cpu - space pointer to a buffer that may be used to perform DMA to the
* specified device . Such cpu - space buffers are returned along with the DMA
* address ( through the pointer provided ) .
*
* These buffers are used with URB_NO_xxx_DMA_MAP set in urb - > transfer_flags
2007-07-02 10:33:12 +04:00
* to avoid behaviors like using " DMA bounce buffers " , or thrashing IOMMU
* hardware during URB completion / resubmit . The implementation varies between
2005-04-17 02:20:36 +04:00
* platforms , depending on details of how DMA will work to this device .
2007-07-02 10:33:12 +04:00
* Using these buffers also eliminates cacheline sharing problems on
* architectures where CPU caches are not DMA - coherent . On systems without
* bus - snooping caches , these buffers are uncached .
2005-04-17 02:20:36 +04:00
*
* When the buffer is no longer used , free it with usb_buffer_free ( ) .
*/
2008-01-31 02:21:33 +03:00
void * usb_buffer_alloc ( struct usb_device * dev , size_t size , gfp_t mem_flags ,
dma_addr_t * dma )
2005-04-17 02:20:36 +04:00
{
2006-08-30 19:27:36 +04:00
if ( ! dev | | ! dev - > bus )
2005-04-17 02:20:36 +04:00
return NULL ;
2007-01-23 23:55:28 +03:00
return hcd_buffer_alloc ( dev - > bus , size , mem_flags , dma ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_alloc ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_buffer_free - free memory allocated with usb_buffer_alloc ( )
* @ dev : device the buffer was used with
* @ size : requested buffer size
* @ addr : CPU address of buffer
* @ dma : DMA address of buffer
*
* This reclaims an I / O buffer , letting it be reused . The memory must have
* been allocated using usb_buffer_alloc ( ) , and the parameters must match
2007-07-02 10:33:12 +04:00
* those provided in that allocation request .
2005-04-17 02:20:36 +04:00
*/
2008-01-31 02:21:33 +03:00
void usb_buffer_free ( struct usb_device * dev , size_t size , void * addr ,
dma_addr_t dma )
2005-04-17 02:20:36 +04:00
{
2006-08-30 19:27:36 +04:00
if ( ! dev | | ! dev - > bus )
2006-08-02 06:33:34 +04:00
return ;
if ( ! addr )
return ;
2007-01-23 23:55:28 +03:00
hcd_buffer_free ( dev - > bus , size , addr , dma ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_free ) ;
2005-04-17 02:20:36 +04:00
/**
* usb_buffer_map - create DMA mapping ( s ) for an urb
* @ urb : urb whose transfer_buffer / setup_packet will be mapped
*
* Return value is either null ( indicating no buffer could be mapped ) , or
* the parameter . URB_NO_TRANSFER_DMA_MAP and URB_NO_SETUP_DMA_MAP are
* added to urb - > transfer_flags if the operation succeeds . If the device
* is connected to this system through a non - DMA controller , this operation
* always succeeds .
*
* This call would normally be used for an urb which is reused , perhaps
* as the target of a large periodic transfer , with usb_buffer_dmasync ( )
* calls to synchronize memory and dma state .
*
* Reverse the effect of this call with usb_buffer_unmap ( ) .
*/
#if 0
2007-01-23 23:55:28 +03:00
struct urb * usb_buffer_map ( struct urb * urb )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! urb
| | ! urb - > dev
| | ! ( bus = urb - > dev - > bus )
| | ! ( controller = bus - > controller ) )
return NULL ;
if ( controller - > dma_mask ) {
2007-01-23 23:55:28 +03:00
urb - > transfer_dma = dma_map_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > transfer_buffer , urb - > transfer_buffer_length ,
2007-01-23 23:55:28 +03:00
usb_pipein ( urb - > pipe )
2005-04-17 02:20:36 +04:00
? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2007-01-23 23:55:28 +03:00
if ( usb_pipecontrol ( urb - > pipe ) )
urb - > setup_dma = dma_map_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > setup_packet ,
2007-01-23 23:55:28 +03:00
sizeof ( struct usb_ctrlrequest ) ,
2005-04-17 02:20:36 +04:00
DMA_TO_DEVICE ) ;
2008-01-31 02:21:33 +03:00
/* FIXME generic api broken like pci, can't report errors */
/* if (urb->transfer_dma == DMA_ADDR_INVALID) return 0; */
2005-04-17 02:20:36 +04:00
} else
urb - > transfer_dma = ~ 0 ;
urb - > transfer_flags | = ( URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP ) ;
return urb ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_map ) ;
2005-04-17 02:20:36 +04:00
# endif /* 0 */
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
* XXX the buffer from device to cpu or vice verse , and thusly use the
* XXX appropriate _for_ { cpu , device } ( ) method . - DaveM
*/
#if 0
/**
* usb_buffer_dmasync - synchronize DMA and CPU view of buffer ( s )
* @ urb : urb whose transfer_buffer / setup_packet will be synchronized
*/
2007-01-23 23:55:28 +03:00
void usb_buffer_dmasync ( struct urb * urb )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! urb
| | ! ( urb - > transfer_flags & URB_NO_TRANSFER_DMA_MAP )
| | ! urb - > dev
| | ! ( bus = urb - > dev - > bus )
| | ! ( controller = bus - > controller ) )
return ;
if ( controller - > dma_mask ) {
2007-01-23 23:55:28 +03:00
dma_sync_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > transfer_dma , urb - > transfer_buffer_length ,
2007-01-23 23:55:28 +03:00
usb_pipein ( urb - > pipe )
2005-04-17 02:20:36 +04:00
? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2007-01-23 23:55:28 +03:00
if ( usb_pipecontrol ( urb - > pipe ) )
dma_sync_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > setup_dma ,
2007-01-23 23:55:28 +03:00
sizeof ( struct usb_ctrlrequest ) ,
2005-04-17 02:20:36 +04:00
DMA_TO_DEVICE ) ;
}
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_dmasync ) ;
2005-04-17 02:20:36 +04:00
# endif
/**
* usb_buffer_unmap - free DMA mapping ( s ) for an urb
* @ urb : urb whose transfer_buffer will be unmapped
*
* Reverses the effect of usb_buffer_map ( ) .
*/
#if 0
2007-01-23 23:55:28 +03:00
void usb_buffer_unmap ( struct urb * urb )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! urb
| | ! ( urb - > transfer_flags & URB_NO_TRANSFER_DMA_MAP )
| | ! urb - > dev
| | ! ( bus = urb - > dev - > bus )
| | ! ( controller = bus - > controller ) )
return ;
if ( controller - > dma_mask ) {
2007-01-23 23:55:28 +03:00
dma_unmap_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > transfer_dma , urb - > transfer_buffer_length ,
2007-01-23 23:55:28 +03:00
usb_pipein ( urb - > pipe )
2005-04-17 02:20:36 +04:00
? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2007-01-23 23:55:28 +03:00
if ( usb_pipecontrol ( urb - > pipe ) )
dma_unmap_single ( controller ,
2005-04-17 02:20:36 +04:00
urb - > setup_dma ,
2007-01-23 23:55:28 +03:00
sizeof ( struct usb_ctrlrequest ) ,
2005-04-17 02:20:36 +04:00
DMA_TO_DEVICE ) ;
}
urb - > transfer_flags & = ~ ( URB_NO_TRANSFER_DMA_MAP
| URB_NO_SETUP_DMA_MAP ) ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_unmap ) ;
2005-04-17 02:20:36 +04:00
# endif /* 0 */
/**
* usb_buffer_map_sg - create scatterlist DMA mapping ( s ) for an endpoint
* @ dev : device to which the scatterlist will be mapped
2007-07-31 01:07:21 +04:00
* @ is_in : mapping transfer direction
2005-04-17 02:20:36 +04:00
* @ sg : the scatterlist to map
* @ nents : the number of entries in the scatterlist
*
* Return value is either < 0 ( indicating no buffers could be mapped ) , or
* the number of DMA mapping array entries in the scatterlist .
*
* The caller is responsible for placing the resulting DMA addresses from
* the scatterlist into URB transfer buffer pointers , and for setting the
* URB_NO_TRANSFER_DMA_MAP transfer flag in each of those URBs .
*
* Top I / O rates come from queuing URBs , instead of waiting for each one
* to complete before starting the next I / O . This is particularly easy
* to do with scatterlists . Just allocate and submit one URB for each DMA
* mapping entry returned , stopping on the first error or when all succeed .
* Better yet , use the usb_sg_ * ( ) calls , which do that ( and more ) for you .
*
* This call would normally be used when translating scatterlist requests ,
* rather than usb_buffer_map ( ) , since on some hardware ( with IOMMUs ) it
* may be able to coalesce mappings for improved I / O efficiency .
*
* Reverse the effect of this call with usb_buffer_unmap_sg ( ) .
*/
2007-07-31 01:07:21 +04:00
int usb_buffer_map_sg ( const struct usb_device * dev , int is_in ,
2006-08-27 06:48:11 +04:00
struct scatterlist * sg , int nents )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! dev
| | ! ( bus = dev - > bus )
| | ! ( controller = bus - > controller )
| | ! controller - > dma_mask )
return - 1 ;
2008-01-31 02:21:33 +03:00
/* FIXME generic api broken like pci, can't report errors */
2007-01-23 23:55:28 +03:00
return dma_map_sg ( controller , sg , nents ,
2007-07-31 01:07:21 +04:00
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_map_sg ) ;
2005-04-17 02:20:36 +04:00
/* XXX DISABLED, no users currently. If you wish to re-enable this
* XXX please determine whether the sync is to transfer ownership of
* XXX the buffer from device to cpu or vice verse , and thusly use the
* XXX appropriate _for_ { cpu , device } ( ) method . - DaveM
*/
#if 0
/**
* usb_buffer_dmasync_sg - synchronize DMA and CPU view of scatterlist buffer ( s )
* @ dev : device to which the scatterlist will be mapped
2007-07-31 01:07:21 +04:00
* @ is_in : mapping transfer direction
2005-04-17 02:20:36 +04:00
* @ sg : the scatterlist to synchronize
* @ n_hw_ents : the positive return value from usb_buffer_map_sg
*
* Use this when you are re - using a scatterlist ' s data buffers for
* another USB request .
*/
2007-07-31 01:07:21 +04:00
void usb_buffer_dmasync_sg ( const struct usb_device * dev , int is_in ,
2006-08-27 06:48:11 +04:00
struct scatterlist * sg , int n_hw_ents )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! dev
| | ! ( bus = dev - > bus )
| | ! ( controller = bus - > controller )
| | ! controller - > dma_mask )
return ;
2007-01-23 23:55:28 +03:00
dma_sync_sg ( controller , sg , n_hw_ents ,
2007-07-31 01:07:21 +04:00
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_dmasync_sg ) ;
2005-04-17 02:20:36 +04:00
# endif
/**
* usb_buffer_unmap_sg - free DMA mapping ( s ) for a scatterlist
* @ dev : device to which the scatterlist will be mapped
2007-07-31 01:07:21 +04:00
* @ is_in : mapping transfer direction
2005-04-17 02:20:36 +04:00
* @ sg : the scatterlist to unmap
* @ n_hw_ents : the positive return value from usb_buffer_map_sg
*
* Reverses the effect of usb_buffer_map_sg ( ) .
*/
2007-07-31 01:07:21 +04:00
void usb_buffer_unmap_sg ( const struct usb_device * dev , int is_in ,
2006-08-27 06:48:11 +04:00
struct scatterlist * sg , int n_hw_ents )
2005-04-17 02:20:36 +04:00
{
struct usb_bus * bus ;
struct device * controller ;
if ( ! dev
| | ! ( bus = dev - > bus )
| | ! ( controller = bus - > controller )
| | ! controller - > dma_mask )
return ;
2007-01-23 23:55:28 +03:00
dma_unmap_sg ( controller , sg , n_hw_ents ,
2007-07-31 01:07:21 +04:00
is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE ) ;
2005-04-17 02:20:36 +04:00
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_buffer_unmap_sg ) ;
2005-04-17 02:20:36 +04:00
/* format to disable USB on kernel command line is: nousb */
2005-12-21 01:15:04 +03:00
__module_param_call ( " " , nousb , param_set_bool , param_get_bool , & nousb , 0444 ) ;
2005-04-17 02:20:36 +04:00
/*
* for external read access to < nousb >
*/
int usb_disabled ( void )
{
return nousb ;
}
2008-01-25 20:12:21 +03:00
EXPORT_SYMBOL_GPL ( usb_disabled ) ;
2005-04-17 02:20:36 +04:00
/*
* Init
*/
static int __init usb_init ( void )
{
int retval ;
if ( nousb ) {
2007-01-23 23:55:28 +03:00
pr_info ( " %s: USB support disabled \n " , usbcore_name ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-09-19 18:14:07 +04:00
retval = ksuspend_usb_init ( ) ;
if ( retval )
goto out ;
2005-04-17 02:20:36 +04:00
retval = bus_register ( & usb_bus_type ) ;
2008-01-31 02:21:33 +03:00
if ( retval )
2006-09-19 18:14:07 +04:00
goto bus_register_failed ;
2005-04-17 02:20:36 +04:00
retval = usb_host_init ( ) ;
if ( retval )
goto host_init_failed ;
retval = usb_major_init ( ) ;
if ( retval )
goto major_init_failed ;
2005-07-31 03:05:53 +04:00
retval = usb_register ( & usbfs_driver ) ;
if ( retval )
goto driver_register_failed ;
2007-03-13 17:59:31 +03:00
retval = usb_devio_init ( ) ;
2005-07-31 03:05:53 +04:00
if ( retval )
2007-03-13 17:59:31 +03:00
goto usb_devio_init_failed ;
2005-04-17 02:20:36 +04:00
retval = usbfs_init ( ) ;
if ( retval )
goto fs_init_failed ;
retval = usb_hub_init ( ) ;
if ( retval )
goto hub_init_failed ;
2006-07-02 06:08:49 +04:00
retval = usb_register_device_driver ( & usb_generic_driver , THIS_MODULE ) ;
2005-04-17 02:20:36 +04:00
if ( ! retval )
goto out ;
usb_hub_cleanup ( ) ;
hub_init_failed :
usbfs_cleanup ( ) ;
fs_init_failed :
2007-03-13 17:59:31 +03:00
usb_devio_cleanup ( ) ;
usb_devio_init_failed :
2005-07-31 03:05:53 +04:00
usb_deregister ( & usbfs_driver ) ;
driver_register_failed :
usb_major_cleanup ( ) ;
2005-04-17 02:20:36 +04:00
major_init_failed :
usb_host_cleanup ( ) ;
host_init_failed :
bus_unregister ( & usb_bus_type ) ;
2006-09-19 18:14:07 +04:00
bus_register_failed :
ksuspend_usb_cleanup ( ) ;
2005-04-17 02:20:36 +04:00
out :
return retval ;
}
/*
* Cleanup
*/
static void __exit usb_exit ( void )
{
/* This will matter if shutdown/reboot does exitcalls. */
if ( nousb )
return ;
2006-07-02 06:08:49 +04:00
usb_deregister_device_driver ( & usb_generic_driver ) ;
2005-04-17 02:20:36 +04:00
usb_major_cleanup ( ) ;
usbfs_cleanup ( ) ;
2005-07-31 03:05:53 +04:00
usb_deregister ( & usbfs_driver ) ;
2007-03-13 17:59:31 +03:00
usb_devio_cleanup ( ) ;
2005-04-17 02:20:36 +04:00
usb_hub_cleanup ( ) ;
usb_host_cleanup ( ) ;
bus_unregister ( & usb_bus_type ) ;
2006-09-19 18:14:07 +04:00
ksuspend_usb_cleanup ( ) ;
2005-04-17 02:20:36 +04:00
}
subsys_initcall ( usb_init ) ;
module_exit ( usb_exit ) ;
MODULE_LICENSE ( " GPL " ) ;