/* enable the USB port by setting the EN bit in the USBMOD register */
void fhci_port_enable(void *lld)
{
	struct fhci_usb *usb = (struct fhci_usb *)lld;
	struct fhci_hcd *fhci = usb->fhci;

	fhci_dbg(fhci, "-> %s\n", __func__);

	fhci_config_transceiver(fhci, usb->port_status);

	if ((usb->port_status != FHCI_PORT_FULL) &&
			(usb->port_status != FHCI_PORT_LOW))
		fhci_start_sof_timer(fhci);

	usb->vroot_hub->port.wPortStatus |= USB_PORT_STAT_ENABLE;
	usb->vroot_hub->port.wPortChange |= USB_PORT_STAT_C_ENABLE;

	fhci_dbg(fhci, "<- %s\n", __func__);
}
Example #2
0
int fhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                     u16 wIndex, char *buf, u16 wLength)
{
    struct fhci_hcd *fhci = hcd_to_fhci(hcd);
    int retval = 0;
    int len = 0;
    struct usb_hub_status *hub_status;
    struct usb_port_status *port_status;
    unsigned long flags;

    spin_lock_irqsave(&fhci->lock, flags);

    fhci_dbg(fhci, "-> %s\n", __func__);

    switch (typeReq) {
    case ClearHubFeature:
        switch (wValue) {
        case C_HUB_LOCAL_POWER:
        case C_HUB_OVER_CURRENT:
            break;
        default:
            goto error;
        }
        break;
    case ClearPortFeature:
        fhci->vroot_hub->feature &= (1 << wValue);

        switch (wValue) {
        case USB_PORT_FEAT_ENABLE:
            fhci->vroot_hub->port.wPortStatus &=
                ~USB_PORT_STAT_ENABLE;
            fhci_port_disable(fhci);
            break;
        case USB_PORT_FEAT_C_ENABLE:
            fhci->vroot_hub->port.wPortChange &=
                ~USB_PORT_STAT_C_ENABLE;
            break;
        case USB_PORT_FEAT_SUSPEND:
            fhci->vroot_hub->port.wPortStatus &=
                ~USB_PORT_STAT_SUSPEND;
            fhci_stop_sof_timer(fhci);
            break;
        case USB_PORT_FEAT_C_SUSPEND:
            fhci->vroot_hub->port.wPortChange &=
                ~USB_PORT_STAT_C_SUSPEND;
            break;
        case USB_PORT_FEAT_POWER:
            fhci->vroot_hub->port.wPortStatus &=
                ~USB_PORT_STAT_POWER;
            fhci_config_transceiver(fhci, FHCI_PORT_POWER_OFF);
            break;
        case USB_PORT_FEAT_C_CONNECTION:
            fhci->vroot_hub->port.wPortChange &=
                ~USB_PORT_STAT_C_CONNECTION;
            break;
        case USB_PORT_FEAT_C_OVER_CURRENT:
            fhci->vroot_hub->port.wPortChange &=
                ~USB_PORT_STAT_C_OVERCURRENT;
            break;
        case USB_PORT_FEAT_C_RESET:
            fhci->vroot_hub->port.wPortChange &=
                ~USB_PORT_STAT_C_RESET;
            break;
        default:
            goto error;
        }
        break;
    case GetHubDescriptor:
        memcpy(buf, root_hub_des, sizeof(root_hub_des));
        buf[3] = 0x11; /* per-port power, no ovrcrnt */
        len = (buf[0] < wLength) ? buf[0] : wLength;
        break;
    case GetHubStatus:
        hub_status = (struct usb_hub_status *)buf;
        hub_status->wHubStatus =
            cpu_to_le16(fhci->vroot_hub->hub.wHubStatus);
        hub_status->wHubChange =
            cpu_to_le16(fhci->vroot_hub->hub.wHubChange);
        len = 4;
        break;
    case GetPortStatus:
        port_status = (struct usb_port_status *)buf;
        port_status->wPortStatus =
            cpu_to_le16(fhci->vroot_hub->port.wPortStatus);
        port_status->wPortChange =
            cpu_to_le16(fhci->vroot_hub->port.wPortChange);
        len = 4;
        break;
    case SetHubFeature:
        switch (wValue) {
        case C_HUB_OVER_CURRENT:
        case C_HUB_LOCAL_POWER:
            break;
        default:
            goto error;
        }
        break;
    case SetPortFeature:
        fhci->vroot_hub->feature |= (1 << wValue);

        switch (wValue) {
        case USB_PORT_FEAT_ENABLE:
            fhci->vroot_hub->port.wPortStatus |=
                USB_PORT_STAT_ENABLE;
            fhci_port_enable(fhci->usb_lld);
            break;
        case USB_PORT_FEAT_SUSPEND:
            fhci->vroot_hub->port.wPortStatus |=
                USB_PORT_STAT_SUSPEND;
            fhci_stop_sof_timer(fhci);
            break;
        case USB_PORT_FEAT_RESET:
            fhci->vroot_hub->port.wPortStatus |=
                USB_PORT_STAT_RESET;
            fhci_port_reset(fhci->usb_lld);
            fhci->vroot_hub->port.wPortStatus |=
                USB_PORT_STAT_ENABLE;
            fhci->vroot_hub->port.wPortStatus &=
                ~USB_PORT_STAT_RESET;
            break;
        case USB_PORT_FEAT_POWER:
            fhci->vroot_hub->port.wPortStatus |=
                USB_PORT_STAT_POWER;
            fhci_config_transceiver(fhci, FHCI_PORT_WAITING);
            break;
        default:
            goto error;
        }
        break;
    default:
error:
        retval = -EPIPE;
    }

    fhci_dbg(fhci, "<- %s\n", __func__);

    spin_unlock_irqrestore(&fhci->lock, flags);

    return retval;
}