static int generic_suspend(struct usb_device *udev, pm_message_t msg) { int rc; MYDBG("udev : %x", (unsigned int)udev); /* Normal USB devices suspend through their upstream port. * Root hubs don't have upstream ports to suspend, * so we have to shut down their downstream HC-to-USB * interfaces manually by doing a bus (or "global") suspend. */ if (!udev->parent) { MYDBG(""); rc = hcd_bus_suspend(udev, msg); } /* Non-root devices don't need to do anything for FREEZE or PRETHAW */ else if (msg.event == PM_EVENT_FREEZE || msg.event == PM_EVENT_PRETHAW) { MYDBG(""); rc = 0; } else { MYDBG(""); rc = usb_port_suspend(udev, msg); } return rc; }
QString try_load_start_of_file(const QString &url, const off_t maxreadsize, const qint64 wholetimeout_msec, const qint64 sleep_usec) { MYDBG("try_load_start_of_file: %s, read first %lu bytes, fail after %lu msec", qPrintable(url), (unsigned long)maxreadsize, (unsigned long)wholetimeout_msec); QStringList errors; AsyncReadFile ASF(url, false, maxreadsize); QElapsedTimer timer; timer.start(); bool made_progress; while(ASF.iter(&errors, NULL, &made_progress)) { const qint64 timepassed_msec = timer.elapsed(); if(timepassed_msec > wholetimeout_msec) { errors.append(QStringLiteral("took too long")); const QString ret = errors.join(QStringLiteral("; ")); MYDBG("try_load_start_of_file: FAILURE %s", qPrintable(ret)); return ret; } if(!made_progress) { const qint64 time_still_allowed_msec = wholetimeout_msec - timepassed_msec; const qint64 timetosleep_usec = qMin(sleep_usec, 1000 * time_still_allowed_msec); ::usleep(timetosleep_usec); } QCoreApplication::processEvents(); } const QString ret = errors.join(QStringLiteral("; ")); if(ret.isEmpty()) { MYDBG("try_load_start_of_file: success"); } else { MYDBG("try_load_start_of_file: FAILURE %s", qPrintable(ret)); } return ret; }
void async_slurp_file(const QString &url, QStringList &errors, QByteArray &contents, const qint64 wholetimeout_msec, const qint64 sleep_usec) { MYDBG("async_slurp_file: %s, fail after %lu msec", qPrintable(url), (unsigned long)wholetimeout_msec); AsyncReadFile ASF(url, true, -1); QElapsedTimer timer; timer.start(); bool made_progress; while(ASF.iter(&errors, &contents, &made_progress)) { const qint64 timepassed_msec = timer.elapsed(); if(timepassed_msec > wholetimeout_msec) { errors.append(QStringLiteral("took too long")); MYDBG("async_slurp_file: FAILURE %s", qPrintable(errors.join(QLatin1String("; ")))); return; } if(!made_progress) { const qint64 time_still_allowed_msec = wholetimeout_msec - timepassed_msec; const qint64 timetosleep_usec = qMin(sleep_usec, 1000 * time_still_allowed_msec); ::usleep(timetosleep_usec); } QCoreApplication::processEvents(); } if(errors.isEmpty()) { MYDBG("async_slurp_file: success"); } else { MYDBG("async_slurp_file: FAILURE %s", qPrintable(errors.join(QLatin1String("; ")))); } }
static int generic_resume(struct usb_device *udev, pm_message_t msg) { int rc; MYDBG("udev : %x", (unsigned int)udev); /* Normal USB devices resume/reset through their upstream port. * Root hubs don't have upstream ports to resume or reset, * so we have to start up their downstream HC-to-USB * interfaces manually by doing a bus (or "global") resume. */ if (!udev->parent) { MYDBG("udev : %x", (unsigned int)udev); rc = hcd_bus_resume(udev, msg); } else { MYDBG("udev : %x", (unsigned int)udev); rc = usb_port_resume(udev, msg); } return rc; }
static void musbfsh_port_suspend(struct musbfsh *musbfsh, bool do_suspend) { u8 power; u8 intrusbe; u8 intrusb; void __iomem *mbase = musbfsh->mregs; int retries = 0; /* MYDBG("cpuid:%d\n", smp_processor_id()); */ /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and * MUSBFSH_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect * SE0 changing to connect (J) or wakeup (K) states. */ if (do_suspend) { #ifdef CONFIG_MTK_DT_USB_SUPPORT if (musbfsh_skip_port_suspend) { MYDBG("\n"); musbfsh->port1_status |= USB_PORT_STAT_SUSPEND; return; } #endif /* clean MUSBFSH_INTR_SOF in MUSBFSH_INTRUSBE */ intrusbe = musbfsh_readb(mbase, MUSBFSH_INTRUSBE); intrusbe &= ~MUSBFSH_INTR_SOF; musbfsh_writeb(mbase, MUSBFSH_INTRUSBE, intrusbe); mb(); /* flush POWER and PHY setting immediately */ /* clean MUSBFSH_INTR_SOF in MUSBFSH_INTRUSB */ intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB); intrusb |= MUSBFSH_INTR_SOF; musbfsh_writeb(mbase, MUSBFSH_INTRUSB, intrusb); mb(); /* flush POWER and PHY setting immediately */ retries = 10000; intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB); while (!(intrusb & MUSBFSH_INTR_SOF)) { intrusb = musbfsh_readb(mbase, MUSBFSH_INTRUSB); if (retries-- < 1) { MYDBG("\n"); break; } } /* delay 10 us */ udelay(10); /* set MUSBFSH_POWER_SUSPENDM in MUSBFSH_POWER_SUSPENDM */ power = musbfsh_readb(mbase, MUSBFSH_POWER); #ifdef CONFIG_MTK_DT_USB_SUPPORT #if defined(CONFIG_PM_RUNTIME) && defined(USB11_REMOTE_IRQ_NON_AUTO_MASK) disable_remote_wake_up(); #endif #endif #ifdef MTK_USB_RUNTIME_SUPPORT /* * mask remote wake up IRQ between port suspend and bus suspend. * hub.c will call set_port_feature first then * usb_set_device_state, so if EINT comes between them, * resume flow may see device state without USB_STATE_SUSPENDED * and do nothing. * So we postpone remote wake up IRQ until the suspend flow * is all done (when bus_suspend is called). Since suspend flow * may be interrupted (root hub is suspended, but not host * controller), so we also unmaks EINT when resume is done. */ mt_eint_mask(CUST_EINT_MT6280_USB_WAKEUP_NUM); #endif retries = 10000; #ifdef CONFIG_MTK_ICUSB_SUPPORT if (skip_port_pm_attr.value) { MYDBG("skip hw operation for port suspend\n"); } else { power &= ~MUSBFSH_POWER_RESUME; power |= MUSBFSH_POWER_SUSPENDM; musbfsh_writeb(mbase, MUSBFSH_POWER, power); /* Needed for OPT A tests */ power = musbfsh_readb(mbase, MUSBFSH_POWER); while (power & MUSBFSH_POWER_SUSPENDM) { power = musbfsh_readb(mbase, MUSBFSH_POWER); if (retries-- < 1) break; } } #else power &= ~MUSBFSH_POWER_RESUME; power |= MUSBFSH_POWER_SUSPENDM; musbfsh_writeb(mbase, MUSBFSH_POWER, power); /* Needed for OPT A tests */ power = musbfsh_readb(mbase, MUSBFSH_POWER); while (power & MUSBFSH_POWER_SUSPENDM) { power = musbfsh_readb(mbase, MUSBFSH_POWER); if (retries-- < 1) { MYDBG("\n"); break; } } #endif mb(); /* flush POWER and PHY setting immediately */ WARNING("Root port suspended, power 0x%02x\n", power); #ifdef CONFIG_MTK_DT_USB_SUPPORT #if defined(CONFIG_PM_RUNTIME) disable_usb11_clk(); #endif #endif musbfsh->port1_status |= USB_PORT_STAT_SUSPEND; } else { #ifdef CONFIG_MTK_DT_USB_SUPPORT if (musbfsh_skip_port_resume) { MYDBG("\n"); request_wakeup_md_timeout(0, 0); musbfsh->port1_status |= MUSBFSH_PORT_STAT_RESUME; musbfsh->rh_timer = jiffies + msecs_to_jiffies(20); return; } #if defined(CONFIG_PM_RUNTIME) enable_usb11_clk(); #endif #endif power = musbfsh_readb(mbase, MUSBFSH_POWER); if (!(power & MUSBFSH_POWER_SUSPENDM)) { WARNING("Root port resuming abort, power 0x%02x\n", power); if (power & MUSBFSH_POWER_RESUME) goto finish; else return; } #ifdef CONFIG_MTK_DT_USB_SUPPORT request_wakeup_md_timeout(0, 0); #endif #ifdef MTK_USB_RUNTIME_SUPPORT /* ERR("EINT to wake up MD for resume\n"); */ /* request_wakeup_md_timeout(0, 0); //wx, wakeup MD first */ #endif #ifdef CONFIG_MTK_ICUSB_SUPPORT if (skip_port_pm_attr.value) { MYDBG("skip hw operation for port resume\n"); } else { power &= ~MUSBFSH_POWER_SUSPENDM; power |= MUSBFSH_POWER_RESUME; musbfsh_writeb(mbase, MUSBFSH_POWER, power); } #else power &= ~MUSBFSH_POWER_SUSPENDM; power |= MUSBFSH_POWER_RESUME; musbfsh_writeb(mbase, MUSBFSH_POWER, power); #endif mb(); /* flush POWER and PHY setting immediately */ WARNING("Root port resuming, power 0x%02x\n", power); finish: /* later, GetPortStatus will stop RESUME signaling */ musbfsh->port1_status |= MUSBFSH_PORT_STAT_RESUME; musbfsh->rh_timer = jiffies + msecs_to_jiffies(20); } }
int musbfsh_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct musbfsh *musbfsh = hcd_to_musbfsh(hcd); u32 temp; int retval = 0; unsigned long flags; INFO("%s++, typeReq=0x%x, wValue=0x%x, wIndex=0x%x\r\n", __func__, typeReq, wValue, wIndex); spin_lock_irqsave(&musbfsh->lock, flags); if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) { spin_unlock_irqrestore(&musbfsh->lock, flags); return -ESHUTDOWN; } /* hub features: always zero, setting is a NOP * port features: reported, sometimes updated when host is active * no indicators */ switch (typeReq) { case ClearHubFeature: case SetHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: break; default: goto error; } break; case ClearPortFeature: /* wIndex indicate the port number, here it is should be 1 */ if ((wIndex & 0xff) != 1) goto error; switch (wValue) { case USB_PORT_FEAT_ENABLE: break; case USB_PORT_FEAT_SUSPEND: /* here is clearing the suspend */ musbfsh_port_suspend(musbfsh, false); break; case USB_PORT_FEAT_POWER: #ifndef MTK_ALPS_BOX_SUPPORT /* only power off the vbus */ musbfsh_set_vbus(musbfsh, 0); #else /* only power off the vbus */ musbfsh_platform_set_vbus(musbfsh, 0); #endif break; case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_SUSPEND: break; default: goto error; } INFO("clear feature %d\n", wValue); musbfsh->port1_status &= ~(1 << wValue); break; case GetHubDescriptor: { struct usb_hub_descriptor *desc = (void *)buf; desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; /* 0x0001: per-port power switching */ /* 0x0010: no overcurrent reporting */ desc->wHubCharacteristics = cpu_to_le16(0x0001 | 0x0010); /* msec/2 */ desc->bPwrOn2PwrGood = 5; desc->bHubContrCurrent = 0; /* workaround bogus struct definition */ desc->u.hs.DeviceRemovable[0] = 0x02; /* port 1 */ desc->u.hs.DeviceRemovable[1] = 0xff; } break; case GetHubStatus: temp = 0; *(__le32 *)buf = cpu_to_le32(temp); break; case GetPortStatus: if (wIndex != 1) goto error; /* finish RESET signaling? */ /* if FALSE: stop the reset because the timeout of reset. */ if ((musbfsh->port1_status & USB_PORT_STAT_RESET) && time_after_eq(jiffies, musbfsh->rh_timer)) musbfsh_port_reset(musbfsh, false); /* finish RESUME signaling? */ if ((musbfsh->port1_status & MUSBFSH_PORT_STAT_RESUME) && time_after_eq(jiffies, musbfsh->rh_timer)) { u8 pwr; #ifdef CONFIG_MTK_DT_USB_SUPPORT if (!musbfsh_skip_port_resume) { pwr = musbfsh_readb(musbfsh->mregs, MUSBFSH_POWER); pwr &= ~MUSBFSH_POWER_RESUME; WARNING("Root port resume stopped\n"); WARNING("power 0x%02x\n", pwr); musbfsh_writeb(musbfsh->mregs, MUSBFSH_POWER, pwr); #if defined(CONFIG_PM_RUNTIME) && defined(USB11_REMOTE_IRQ_NON_AUTO_MASK) enable_remote_wake_up(); #endif } else { MYDBG("\n"); } #else pwr = musbfsh_readb(musbfsh->mregs, MUSBFSH_POWER); pwr &= ~MUSBFSH_POWER_RESUME; WARNING("Root port resume stopped, power 0x%02x\n", pwr); musbfsh_writeb(musbfsh->mregs, MUSBFSH_POWER, pwr); #endif #ifdef MTK_USB_RUNTIME_SUPPORT /* mt_eint_unmask(CUST_EINT_MT6280_USB_WAKEUP_NUM); */ #endif /* * ISSUE: DaVinci (RTL 1.300) disconnects after * resume of high speed peripherals (but not full * speed ones). */ musbfsh->is_active = 1; musbfsh->port1_status &= ~(USB_PORT_STAT_SUSPEND | MUSBFSH_PORT_STAT_RESUME); musbfsh->port1_status |= USB_PORT_STAT_C_SUSPEND << 16; usb_hcd_poll_rh_status(musbfsh_to_hcd(musbfsh)); } put_unaligned(cpu_to_le32(musbfsh->port1_status & ~MUSBFSH_PORT_STAT_RESUME), (__le32 *)buf); /* port change status is more interesting */ WARNING("port status %08x,devctl=0x%x\n", musbfsh->port1_status, musbfsh_readb(musbfsh->mregs, MUSBFSH_DEVCTL)); break; case SetPortFeature: if ((wIndex & 0xff) != 1) goto error; switch (wValue) { case USB_PORT_FEAT_POWER: /* NOTE: this controller has a strange state machine * that involves "requesting sessions" according to * magic side effects from incompletely-described * rules about startup... * * This call is what really starts the host mode; be * very careful about side effects if you reorder any * initialization logic, e.g. for OTG, or change any * logic relating to VBUS power-up. */ INFO("musbfsh_start is called in hub control\r\n"); #ifdef CONFIG_MTK_ICUSB_SUPPORT if (skip_mac_init_attr.value) MYDBG(""); else musbfsh_start(musbfsh); #else musbfsh_start(musbfsh); #endif break; case USB_PORT_FEAT_RESET: /* enable the reset, but not finish */ musbfsh_port_reset(musbfsh, true); break; case USB_PORT_FEAT_SUSPEND: musbfsh_port_suspend(musbfsh, true); break; case USB_PORT_FEAT_TEST: #if 0 if (unlikely(is_host_active(musbfsh))) goto error; wIndex >>= 8; switch (wIndex) { case 1: pr_debug("TEST_J\n"); temp = MUSBFSH_TEST_J; break; case 2: pr_debug("TEST_K\n"); temp = MUSBFSH_TEST_K; break; case 3: pr_debug("TEST_SE0_NAK\n"); temp = MUSBFSH_TEST_SE0_NAK; break; case 4: pr_debug("TEST_PACKET\n"); temp = MUSBFSH_TEST_PACKET; musbfsh_load_testpacket(musbfsh); break; case 5: pr_debug("TEST_FORCE_ENABLE\n"); temp = MUSBFSH_TEST_FORCE_HOST | MUSBFSH_TEST_FORCE_FS; musbfsh_writeb(musbfsh->mregs, MUSBFSH_DEVCTL, MUSBFSH_DEVCTL_SESSION); break; case 6: pr_debug("TEST_FIFO_ACCESS\n"); temp = MUSBFSH_TEST_FIFO_ACCESS; break; default: goto error; } musbfsh_writeb(musbfsh->mregs, MUSBFSH_TESTMODE, temp); #endif break; default: goto error; } INFO("set feature %d\n", wValue); musbfsh->port1_status |= 1 << wValue; break; default: error: /* "protocol stall" on error */ retval = -EPIPE; } spin_unlock_irqrestore(&musbfsh->lock, flags); return retval; }
static void musbfsh_port_reset(struct musbfsh *musbfsh, bool do_reset) { u8 power; void __iomem *mbase = musbfsh->mregs; /* NOTE: caller guarantees it will turn off the reset when * the appropriate amount of time has passed */ power = musbfsh_readb(mbase, MUSBFSH_POWER); WARNING("reset=%d power=0x%x\n", do_reset, power); if (do_reset) { if (power & MUSBFSH_POWER_SUSPENDM) { WARNING("reset a suspended device\n"); #ifdef CONFIG_MTK_DT_USB_SUPPORT request_wakeup_md_timeout(0, 0); #endif #ifdef MTK_USB_RUNTIME_SUPPORT /* ERR("EINT to wake up MD for reset\n"); */ /* wx, we may have to reset a suspended MD */ /* request_wakeup_md_timeout(0, 0); */ #endif musbfsh_writeb(mbase, MUSBFSH_POWER, power | MUSBFSH_POWER_RESUME); mdelay(20); musbfsh_writeb(mbase, MUSBFSH_POWER, power & ~MUSBFSH_POWER_RESUME); } /* * If RESUME is set, we must make sure it stays minimum 20 ms. * Then we must clear RESUME and wait a bit to let musb start * generating SOFs. If we don't do this, OPT HS A 6.8 tests * fail with "Error! Did not receive an SOF before suspend * detected". */ if (power & MUSBFSH_POWER_RESUME) { WARNING("reset a resuming device\n"); while (time_before(jiffies, musbfsh->rh_timer)) mdelay(1); /* stop the resume signal */ musbfsh_writeb(mbase, MUSBFSH_POWER, power & ~MUSBFSH_POWER_RESUME); mdelay(1); } musbfsh->ignore_disconnect = true; power &= 0xf0; musbfsh_writeb(mbase, MUSBFSH_POWER, power | MUSBFSH_POWER_RESET); mb(); /* flush POWER and PHY setting immediately */ musbfsh->port1_status |= USB_PORT_STAT_RESET; musbfsh->port1_status &= ~USB_PORT_STAT_ENABLE; musbfsh->rh_timer = jiffies + msecs_to_jiffies(50); } else { INFO("Root port reset stopped\n"); #ifdef CONFIG_MTK_ICUSB_SUPPORT if (resistor_control_attr.value) { /* improve signal quality, from Dingjun */ #if 0 /* FS_DISC_DISABLE */ u32 TM1; TM1 = musbfsh_readl(mbase, 0x604); musbfsh_writel(mbase, 0x604, TM1 | 0x4); MYDBG("set FS_DISC_DISABLE\n"); #endif /* original flow from SS5 */ USB11PHY_SET8(U1PHTCR2, force_usb11_dm_rpd | force_usb11_dp_rpd); /* * disconnect host port's pull down resistors * on D+ and D- */ USB11PHY_CLR8(U1PHTCR2, RG_USB11_DM_RPD | RG_USB11_DP_RPD); /* * Tell MAC there still is a device attached, * ohterwise we will get disconnect interrupt */ USB11PHY_SET8(U1PHTCR2, force_usb11_dp_rpu | RG_USB11_DP_RPU); /* force */ USB11PHY_SET8(0x6a, 0x20 | 0x10); /* RG */ /* * disconnect host port's pull down resistors * on D+ and D- */ USB11PHY_CLR8(0x68, 0x80 | 0x40); /* * Tell MAC there still is a device attached, * ohterwise we will get disconnect interrupt. */ /* USB11PHY_SET8(U1PHTCR2, * force_usb11_dp_rpu | * RG_USB11_DP_RPU); */ MYDBG("USB1.1 PHY special config for IC-USB\n"); } else { MYDBG(""); } #endif musbfsh_writeb(mbase, MUSBFSH_POWER, power & ~MUSBFSH_POWER_RESET); #ifdef CONFIG_MTK_ICUSB_SUPPORT if (resistor_control_attr.value) USB11PHY_CLR8(0x6a, 0x20 | 0x10); else MYDBG(""); #endif mb(); /* flush POWER and PHY setting immediately */ musbfsh->ignore_disconnect = false; power = musbfsh_readb(mbase, MUSBFSH_POWER); if (power & MUSBFSH_POWER_HSMODE) { INFO("high-speed device connected\n"); musbfsh->port1_status |= USB_PORT_STAT_HIGH_SPEED; } #if 0 /* IC_USB from SS5 */ #ifdef IC_USB USB11PHY_SET8(U1PHTCR2, force_usb11_dm_rpd | force_usb11_dp_rpd); /* disconnect host port's pull down resistors on D+ and D- */ USB11PHY_CLR8(U1PHTCR2, RG_USB11_DM_RPD | RG_USB11_DP_RPD); /* * tell MAC there still is a device attached, * ohterwise we will get disconnect interrupt */ USB11PHY_SET8(U1PHTCR2, force_usb11_dp_rpu | RG_USB11_DP_RPU); WARNING("USB1.1 PHY special config for IC-USB 0x%X=%x\n", U1PHTCR2, USB11PHY_READ8(U1PHTCR2)); #endif #endif musbfsh->port1_status &= ~USB_PORT_STAT_RESET; musbfsh->port1_status |= USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET << 16) | (USB_PORT_STAT_C_ENABLE << 16); /* call back func to notify the hub thread the state of hub! */ usb_hcd_poll_rh_status(musbfsh_to_hcd(musbfsh)); musbfsh->vbuserr_retry = VBUSERR_RETRY_COUNT; } }
int usb_choose_configuration(struct usb_device *udev) { int i; int num_configs; int insufficient_power = 0; struct usb_host_config *c, *best; if (usb_device_is_owned(udev)) return 0; best = NULL; c = udev->config; num_configs = udev->descriptor.bNumConfigurations; for (i = 0; i < num_configs; (i++, c++)) { struct usb_interface_descriptor *desc = NULL; /* It's possible that a config has no interfaces! */ if (c->desc.bNumInterfaces > 0) desc = &c->intf_cache[0]->altsetting->desc; /* * HP's USB bus-powered keyboard has only one configuration * and it claims to be self-powered; other devices may have * similar errors in their descriptors. If the next test * were allowed to execute, such configurations would always * be rejected and the devices would not work as expected. * In the meantime, we run the risk of selecting a config * that requires external power at a time when that power * isn't available. It seems to be the lesser of two evils. * * Bugzilla #6448 reports a device that appears to crash * when it receives a GET_DEVICE_STATUS request! We don't * have any other way to tell whether a device is self-powered, * but since we don't use that information anywhere but here, * the call has been removed. * * Maybe the GET_DEVICE_STATUS call and the test below can * be reinstated when device firmwares become more reliable. * Don't hold your breath. */ #if 0 /* Rule out self-powered configs for a bus-powered device */ if (bus_powered && (c->desc.bmAttributes & USB_CONFIG_ATT_SELFPOWER)) continue; #endif /* * The next test may not be as effective as it should be. * Some hubs have errors in their descriptor, claiming * to be self-powered when they are really bus-powered. * We will overestimate the amount of current such hubs * make available for each port. * * This is a fairly benign sort of failure. It won't * cause us to reject configurations that we should have * accepted. */ /* Rule out configs that draw too much bus current */ if (usb_get_max_power(udev, c) > udev->bus_mA) { insufficient_power++; MYDBG("insufficient available bus power to %d intf, the intf class is 0x%x \n", desc->bInterfaceNumber , desc->bInterfaceClass); continue; } /* When the first config's first interface is one of Microsoft's * pet nonstandard Ethernet-over-USB protocols, ignore it unless * this kernel has enabled the necessary host side driver. * But: Don't ignore it if it's the only config. */ 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 * first interface is for a non-vendor-specific class. * Reason: Linux is more likely to have a class driver * than a vendor-specific driver. */ else if (udev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC && (desc && desc->bInterfaceClass != USB_CLASS_VENDOR_SPEC)) { best = c; break; } /* If all the remaining configs are vendor-specific, * choose the first one. */ else if (!best) best = c; } if (insufficient_power > 0) dev_info(&udev->dev, "rejected %d configuration%s " "due to insufficient available bus power\n", insufficient_power, plural(insufficient_power)); if (best) { i = best->desc.bConfigurationValue; dev_dbg(&udev->dev, "configuration #%d chosen from %d choice%s\n", i, num_configs, plural(num_configs)); } else { i = -1; dev_warn(&udev->dev, "no configuration chosen from %d choice%s\n", num_configs, plural(num_configs)); #ifdef CONFIG_USBIF_COMPLIANCE if ((insufficient_power>0) && (insufficient_power==num_configs)){ MYDBG("insufficient available bus power to all intf\n"); usbif_u3h_send_event("DEV_OVER_CURRENT"); } #endif } return i; }
static int usb_dev_resume(struct device *dev) { MYDBG(""); return usb_resume(dev, PMSG_RESUME); }
static int usb_dev_suspend(struct device *dev) { MYDBG(""); return usb_suspend(dev, PMSG_SUSPEND); }