UsbDevice2.cpp

UsbErr UsbDevice::hub_init()
{
    UsbErr rc;
    uint8_t buf[9];
    rc = controlReceive(
          USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE, // 0xa0 
          GET_DESCRIPTOR, 
          (USB_DESCRIPTOR_TYPE_HUB << 8), 0, buf, sizeof(buf));
    DBG_ASSERT(rc == USBERR_OK);
    DBG_ASSERT(buf[0] == 9);
    DBG_ASSERT(buf[1] == 0x29);
    DBG_BYTES("HUB DESCRIPTOR", buf, sizeof(buf));

    m_hub_ports = buf[2];
    VERBOSE("NbrPorts: %d\n", m_hub_ports);
    int PwrOn2PwrGood = buf[5];
    VERBOSE("PwrOn2PwrGood: %d %d ms\n", PwrOn2PwrGood, PwrOn2PwrGood*2);
    VERBOSE("HubContrCurrent: %d\n", buf[6]);

    rc = setConfiguration(1);    
    DBG_ASSERT(rc == USBERR_OK);
    
    uint8_t status[4];
    rc = controlReceive(
          USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_DEVICE, // 0xa0 
          GET_STATUS, 
          0, 0, status, sizeof(status));
    DBG_ASSERT(rc == USBERR_OK);
    DBG_BYTES("HUB STATUS", status, sizeof(status));

    for(int i = 1; i <= m_hub_ports; i++) {
        rc = SetPortFeature(PORT_POWER, i);
        DBG("PORT_POWER port=%d rc=%d\n", i, rc);
        DBG_ASSERT(rc == USBERR_OK);
        if (rc != USBERR_OK) {
            return rc;
        }
    }
    wait_ms(PwrOn2PwrGood*2);
    
    m_enumerated = true;
    return USBERR_OK;
}

UsbErr UsbDevice::hub_poll()
{
    DBG("m_hub=%d m_port=%d\n", m_hub, m_port);
    UsbErr rc;
    // check status
    for(int port = 1; port <= m_hub_ports; port++) {
        uint8_t status[4];
        rc = GetPortStatus(port, status, sizeof(status));
        DBG_ASSERT(rc == USBERR_OK);
        DBG("port=%d\n", port);
        DBG_BYTES("STATUS", status, sizeof(status));
        if (status[2] & 0x01) { // Connect Status Change, has changed
            DBG_ASSERT(status[0] & 0x01);
            ClearPortFeature(C_PORT_CONNECTION, port);
            SetPortReset(port);

            // wait reset
            DBG_ASSERT((status[2] & 0x10) == 0x00);
            bool reset = false;
            for(int i = 0; i < 100; i++) {
                rc = GetPortStatus(port, status, sizeof(status));
                DBG_ASSERT(rc == USBERR_OK);
                DBG_BYTES("RESET", status, sizeof(status));
                if (status[2] & 0x10) { // Reset change , Reset complete
                    reset = true;
                    break;
                }
                wait_ms(5);
            }
            DBG_ASSERT(reset);
            if (!reset) {
                break;
            }
            DBG_ASSERT(m_pMgr);
            wait_ms(200);
            m_pMgr->onUsbDeviceConnected(m_port, port);
            break;
        }
    }
    rc = USBERR_OK;
    return rc;
}