int usb_choose_configuration(struct usb_device *udev)
{ int i; int num_configs; int insufficient_power = 0; struct usb_host_config *c, *best; struct usb_device_driver *udriver;
if (udriver->choose_configuration) {
i = udriver->choose_configuration(udev); if (i >= 0) return i;
}
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations; for (i = 0; i < num_configs; (i++, c++)) { struct usb_interface_descriptor *desc = NULL;
/* It's possible that a config has no interfaces! */ if (c->desc.bNumInterfaces > 0)
desc = &c->intf_cache[0]->altsetting->desc;
/* *HP'sUSBbus-poweredkeyboardhasonlyoneconfiguration *anditclaimstobeself-powered;otherdevicesmayhave *similarerrorsintheirdescriptors.Ifthenexttest *wereallowedtoexecute,suchconfigurationswouldalways *berejectedandthedeviceswouldnotworkasexpected. *Inthemeantime,weruntheriskofselectingaconfig *thatrequiresexternalpoweratatimewhenthatpower *isn'tavailable.Itseemstobethelesseroftwoevils. * *Bugzilla#6448reportsadevicethatappearstocrash *whenitreceivesaGET_DEVICE_STATUSrequest!Wedon't *haveanyotherwaytotellwhetheradeviceisself-powered, *butsincewedon'tusethatinformationanywherebuthere, *thecallhasbeenremoved. * *MaybetheGET_DEVICE_STATUScallandthetestbelowcan *bereinstatedwhendevicefirmwaresbecomemorereliable. *Don'tholdyourbreath.
*/ #if0 /* Rule out self-powered configs for a bus-powered device */ if (bus_powered && (c->desc.bmAttributes &
USB_CONFIG_ATT_SELFPOWER)) continue; #endif
/* Rule out configs that draw too much bus current */ if (usb_get_max_power(udev, c) > udev->bus_mA) {
insufficient_power++; continue;
}
/* *Selectfirstconfigurationasdefaultforaudiosothat *devicesthatdon'tcomplywithUAC3protocolaresupported. *But,stilliteratethroughotherconfigurationsand *selectUAC3compliantconfigifpresent.
*/ if (desc && is_audio(desc)) { /* Always prefer the first found UAC3 config */ if (is_uac3_config(desc)) {
best = c; break;
}
/* If there is no UAC3 config, prefer the first config */ elseif (i == 0)
best = c;
/* Unconditional continue, because the rest of the code *intheloopisirrelevantforaudiodevices,and *becauseitcanreassignbest,whichforaudiodevices *wedon'twant.
*/ continue;
}
/* When the first config's first interface is one of Microsoft's *petnonstandardEthernet-over-USBprotocols,ignoreitunless *thiskernelhasenabledthenecessaryhostsidedriver. *But:Don'tignoreitifit'stheonlyconfig.
*/ if (i == 0 && num_configs > 1 && desc &&
(is_rndis(desc) || is_activesync(desc))) { #if !defined(CONFIG_USB_NET_RNDIS_HOST) && !defined(CONFIG_USB_NET_RNDIS_HOST_MODULE) continue; #else
best = c; #endif
}
/* From the remaining configs, choose the first one whose *firstinterfaceisforanon-vendor-specificclass. *Reason:Linuxismorelikelytohaveaclassdriver
* than a vendor-specific driver. */ elseif (udev->descriptor.bDeviceClass !=
USB_CLASS_VENDOR_SPEC &&
(desc && desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)) {
best = c; break;
}
/* If all the remaining configs are vendor-specific,
* choose the first one. */ elseif (!best)
best = c;
}
if (insufficient_power > 0)
dev_info(&udev->dev, "rejected %d configuration%s " "due to insufficient available bus power\n",
insufficient_power, str_plural(insufficient_power));
if (best) {
i = best->desc.bConfigurationValue;
dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n",
i, num_configs, str_plural(num_configs));
} else {
i = -1;
dev_warn(&udev->dev, "no configuration chosen from %d choice%s\n",
num_configs, str_plural(num_configs));
} return i;
}
EXPORT_SYMBOL_GPL(usb_choose_configuration);
if (!is_usb_device_driver(drv)) return0;
udrv = to_usb_device_driver(drv); if (udrv == &usb_generic_driver) return0; return usb_driver_applicable(udev, udrv);
}
staticbool usb_generic_driver_match(struct usb_device *udev)
{ if (udev->use_generic_driver) returntrue;
/* *Ifanyotherdriverwantsthedevice,leavethedevicetothisother *driver.
*/ if (bus_for_each_drv(&usb_bus_type, NULL, udev, __check_for_non_generic_match)) returnfalse;
returntrue;
}
int usb_generic_driver_probe(struct usb_device *udev)
{ int err, c;
/* Choose and set the configuration. This registers the interfaces *withthedrivercoreandletsinterfacedriversbindtothem.
*/ if (udev->authorized == 0)
dev_err(&udev->dev, "Device is not authorized for usage\n"); else {
c = usb_choose_configuration(udev); if (c >= 0) {
err = usb_set_configuration(udev, c); if (err && err != -ENODEV) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err); /* This need not be fatal. The user can try to
* set other configurations. */
}
}
} /* USB device state == configured ... usable */
usb_notify_add_device(udev);
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */ if (udev->actconfig)
usb_set_configuration(udev, -1);
}
#ifdef CONFIG_PM
int usb_generic_driver_suspend(struct usb_device *udev, pm_message_t msg)
{ int rc;
/* Normal USB devices suspend through their upstream port. *Roothubsdon'thaveupstreamportstosuspend, *sowehavetoshutdowntheirdownstreamHC-to-USB *interfacesmanuallybydoingabus(or"global")suspend.
*/ if (!udev->parent)
rc = hcd_bus_suspend(udev, msg);
if (rc == 0)
usbfs_notify_suspend(udev); return rc;
}
int usb_generic_driver_resume(struct usb_device *udev, pm_message_t msg)
{ int rc;
/* Normal USB devices resume/reset through their upstream port. *Roothubsdon'thaveupstreamportstoresumeorreset, *sowehavetostartuptheirdownstreamHC-to-USB *interfacesmanuallybydoingabus(or"global")resume.
*/ if (!udev->parent)
rc = hcd_bus_resume(udev, msg); else
rc = usb_port_resume(udev, msg);
if (rc == 0)
usbfs_notify_resume(udev); return rc;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.