@ -15,17 +15,22 @@
# include <linux/usb/quirks.h>
# include "usb.h"
/* List of quirky USB devices. Please keep this list ordered by:
/* Lists of quirky USB devices, split in device quirks and interface quirks.
* Device quirks are applied at the very beginning of the enumeration process ,
* right after reading the device descriptor . They can thus only match on device
* information .
*
* Interface quirks are applied after reading all the configuration descriptors .
* They can match on both device and interface information .
*
* Note that the DELAY_INIT and HONOR_BNUMINTERFACES quirks do not make sense as
* interface quirks , as they only influence the enumeration process which is run
* before processing the interface quirks .
*
* Please keep the lists ordered by :
* 1 ) Vendor ID
* 2 ) Product ID
* 3 ) Class ID
*
* as we want specific devices to be overridden first , and only after that , any
* class specific quirks .
*
* Right now the logic aborts if it finds a valid device in the table , we might
* want to change that in the future if it turns out that a whole class of
* devices is broken . . .
*/
static const struct usb_device_id usb_quirk_list [ ] = {
/* CBM - Flash disk */
@ -156,16 +161,53 @@ static const struct usb_device_id usb_quirk_list[] = {
{ } /* terminating entry must be last */
} ;
static const struct usb_device_id * find_id ( struct usb_device * udev )
static const struct usb_device_id usb_interface_quirk_list [ ] = {
{ } /* terminating entry must be last */
} ;
static bool usb_match_any_interface ( struct usb_device * udev ,
const struct usb_device_id * id )
{
unsigned int i ;
for ( i = 0 ; i < udev - > descriptor . bNumConfigurations ; + + i ) {
struct usb_host_config * cfg = & udev - > config [ i ] ;
unsigned int j ;
for ( j = 0 ; j < cfg - > desc . bNumInterfaces ; + + j ) {
struct usb_interface_cache * cache ;
struct usb_host_interface * intf ;
cache = cfg - > intf_cache [ j ] ;
if ( cache - > num_altsetting = = 0 )
continue ;
intf = & cache - > altsetting [ 0 ] ;
if ( usb_match_one_id_intf ( udev , intf , id ) )
return true ;
}
}
return false ;
}
static u32 __usb_detect_quirks ( struct usb_device * udev ,
const struct usb_device_id * id )
{
const struct usb_device_id * id = usb_quirk_list ;
u32 quirks = 0 ;
for ( ; id - > idVendor | | id - > bDeviceClass | | id - > bInterfaceClass | |
id - > driver_info ; id + + ) {
if ( usb_match_device ( udev , id ) )
return id ;
for ( ; id - > match_flags ; id + + ) {
if ( ! usb_match_device ( udev , id ) )
continue ;
if ( ( id - > match_flags & USB_DEVICE_ID_MATCH_INT_INFO ) & &
! usb_match_any_interface ( udev , id ) )
continue ;
quirks | = ( u32 ) ( id - > driver_info ) ;
}
return NULL ;
return quirks ;
}
/*
@ -173,14 +215,10 @@ static const struct usb_device_id *find_id(struct usb_device *udev)
*/
void usb_detect_quirks ( struct usb_device * udev )
{
const struct usb_device_id * id = usb_quirk_list ;
id = find_id ( udev ) ;
if ( id )
udev - > quirks = ( u32 ) ( id - > driver_info ) ;
udev - > quirks = __usb_detect_quirks ( udev , usb_quirk_list ) ;
if ( udev - > quirks )
dev_dbg ( & udev - > dev , " USB quirks for this device: %x \n " ,
udev - > quirks ) ;
udev - > quirks ) ;
/* For the present, all devices default to USB-PERSIST enabled */
#if 0 /* was: #ifdef CONFIG_PM */
@ -197,3 +235,16 @@ void usb_detect_quirks(struct usb_device *udev)
udev - > persist_enabled = 1 ;
# endif /* CONFIG_PM */
}
void usb_detect_interface_quirks ( struct usb_device * udev )
{
u32 quirks ;
quirks = __usb_detect_quirks ( udev , usb_interface_quirk_list ) ;
if ( quirks = = 0 )
return ;
dev_dbg ( & udev - > dev , " USB interface quirks for this device: %x \n " ,
quirks ) ;
udev - > quirks | = quirks ;
}