Esempio n. 1
0
//*****************************************************************************
//
// Open an instance of the hub driver.  This is called when the USB host
// has enumerated a new hub device.
//
//*****************************************************************************
static void *
HubDriverOpen(tUSBHostDevice *psDevice)
{
    tEndpointDescriptor *psEndpointDescriptor;
    tInterfaceDescriptor *psInterface;
    tUsbHubDescriptor sHubDesc;
    bool bRetcode;
    uint32_t ui32Loop;

    //
    // If we are already talking to a hub, fail the call.  We only support
    // a single hub.
    //
    if(g_sRootHub.ui32Flags & USBLIB_HUB_ACTIVE)
    {
        return(0);
    }

    //
    // Get pointers to the device descriptors we need to look at.
    //
    psInterface = USBDescGetInterface(psDevice->psConfigDescriptor, 0, 0);
    psEndpointDescriptor = USBDescGetInterfaceEndpoint(psInterface, 0,
                                      psDevice->ui32ConfigDescriptorSize);

    //
    // If there are no endpoints, something is wrong since a hub must have
    // a single INT endpoint for signaling.
    //
    if(psEndpointDescriptor == 0)
    {
        return 0;
    }

    //
    // Make sure we really are talking to a hub.
    //
    if((psInterface->bInterfaceClass != USB_CLASS_HUB) ||
       (psInterface->bInterfaceSubClass != 0))
    {
        //
        // Something is wrong - this isn't a hub or, if it is, we don't
        // understand the protocol it is using.
        //
        return(0);
    }

    //
    // Remember that this is a high speed hub with either single or multiple
    // transaction translators.
    //
    if(psInterface->bInterfaceProtocol == USB_HUB_PROTOCOL_SINGLE)
    {
        g_sRootHub.ui32Flags |= USBLIB_HUB_HS;
    }
    else if(psInterface->bInterfaceProtocol == USB_HUB_PROTOCOL_MULTI)
    {
        g_sRootHub.ui32Flags |= USBLIB_HUB_HS | USBLIB_HUB_MULTI_TT;
    }

    //
    // Remember the device information for later.
    //
    g_sRootHub.psDevice = psDevice;

    //
    // A hub must support an interrupt endpoint so check this.
    //
    if((psEndpointDescriptor->bmAttributes & USB_EP_ATTR_TYPE_M) ==
       USB_EP_ATTR_INT)
    {
        //
        // The endpoint is the correct type. Is it an IN endpoint?
        //
        if(psEndpointDescriptor->bEndpointAddress & USB_EP_DESC_IN)
        {
            //
            // Yes - all is well with the hub endpoint so allocate a pipe to
            // handle traffic from the hub.
            //
            g_sRootHub.ui32IntInPipe = USBHCDPipeAlloc(0, USBHCD_PIPE_INTR_IN,
                                                       psDevice,
                                                       HubIntINCallback);
            USBHCDPipeConfig(g_sRootHub.ui32IntInPipe,
                             psEndpointDescriptor->wMaxPacketSize,
                             psEndpointDescriptor->bInterval,
                             psEndpointDescriptor->bEndpointAddress &
                             USB_EP_DESC_NUM_M);
        }
    }

    //
    // Did we allocate the endpoint successfully?
    //
    if(!g_sRootHub.ui32IntInPipe)
    {
        //
        // No - return an error.
        //
        return 0;
    }

    //
    // Assuming we have a callback, call it to tell the owner that a hub is
    // now connected.
    //
    if(g_sRootHub.pfnCallback != 0)
    {
        g_sRootHub.pfnCallback((void *)g_sRootHub.ui32CBData,
                               USB_EVENT_CONNECTED, (uint32_t)&g_sRootHub, 0);
    }

    //
    // Get the hub descriptor and store information we'll need for later.
    //
    bRetcode = GetHubDescriptor(&sHubDesc);
    if(bRetcode)
    {

        //
        // We read the descriptor successfully so extract the parts we need.
        //
        g_sRootHub.ui8NumPorts = sHubDesc.bNbrPorts;
        g_sRootHub.ui16HubCharacteristics = sHubDesc.wHubCharacteristics;
        g_sRootHub.ui8NumPortsInUse =
            (sHubDesc.bNbrPorts > MAX_USB_DEVICES) ? MAX_USB_DEVICES :
                                                     sHubDesc.bNbrPorts;

        //
        // The size of the status change report that the hub sends is dependent
        // upon the number of ports that the hub supports.  Calculate this by
        // adding 1 to the number of ports (bit 0 of the report is the hub
        // status, higher bits are one per port) then dividing by 8 (bits per
        // byte) and rounding up.
        //
        g_sRootHub.ui8ReportSize = ((sHubDesc.bNbrPorts + 1) + 7) / 8;

        //
        // Enable power to all ports on the hub.
        //
        for(ui32Loop = 1; ui32Loop <= sHubDesc.bNbrPorts; ui32Loop++)
        {
            //
            // Turn on power to this port.
            //
            HubSetPortFeature(&g_sRootHub, ui32Loop,
                              HUB_FEATURE_PORT_POWER);
        }

        //
        // Clear out our port state structures.
        //
        for(ui32Loop = 0; ui32Loop < MAX_USB_DEVICES; ui32Loop++)
        {
            g_sRootHub.psPorts[ui32Loop].bChanged = false;
            g_sRootHub.psPorts[ui32Loop].iState = ePortIdle;
        }
    }
    else
    {
        //
        // Oops - we can't read the hub descriptor!  Tidy up and return
        // an error.
        //
        USBHCDPipeFree(g_sRootHub.ui32IntInPipe);
        g_sRootHub.pfnCallback = 0;
        g_sRootHub.ui32Flags &= ~USBLIB_HUB_ACTIVE;
        return(0);
    }

    //
    // If we get here, all is well so remember that the hub is connected and
    // active.
    //
    g_sRootHub.ui32Flags |= USBLIB_HUB_ACTIVE;

    //
    // Return our instance data pointer to the caller to use as a handle.
    //
    return((void *)&g_sRootHub);
}
Esempio n. 2
0
uint8_t USBHub::Init(uint8_t parent, uint8_t port, bool lowspeed) {
        uint8_t buf[32];
        USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
        HubDescriptor* hd = reinterpret_cast<HubDescriptor*>(buf);
        USB_CONFIGURATION_DESCRIPTOR * ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(buf);
        uint8_t rcode;
        UsbDevice *p = NULL;
        EpInfo *oldep_ptr = NULL;
        uint8_t len = 0;
        uint16_t cd_len = 0;

        //USBTRACE("\r\nHub Init Start ");
        //D_PrintHex<uint8_t > (bInitState, 0x80);

        AddressPool &addrPool = pUsb->GetAddressPool();

        //switch (bInitState) {
        //        case 0:
        if(bAddress)
                return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;

        // Get pointer to pseudo device with address 0 assigned
        p = addrPool.GetUsbDevicePtr(0);

        if(!p)
                return USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL;

        if(!p->epinfo)
                return USB_ERROR_EPINFO_IS_NULL;

        // Save old pointer to EP_RECORD of address 0
        oldep_ptr = p->epinfo;

        // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
        p->epinfo = epInfo;

        p->lowspeed = lowspeed;

        // Get device descriptor
        rcode = pUsb->getDevDescr(0, 0, 8, (uint8_t*)buf);

        p->lowspeed = false;

        if(!rcode)
                len = (buf[0] > 32) ? 32 : buf[0];

        if(rcode) {
                // Restore p->epinfo
                p->epinfo = oldep_ptr;
                return rcode;
        }

        // Extract device class from device descriptor
        // If device class is not a hub return
        if(udd->bDeviceClass != 0x09)
                return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;

        // Allocate new address according to device class
        bAddress = addrPool.AllocAddress(parent, (udd->bDeviceClass == 0x09) ? true : false, port);

        if(!bAddress)
                return USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL;

        // Extract Max Packet Size from the device descriptor
        epInfo[0].maxPktSize = udd->bMaxPacketSize0;

        // Assign new address to the device
        rcode = pUsb->setAddr(0, 0, bAddress);

        if(rcode) {
                // Restore p->epinfo
                p->epinfo = oldep_ptr;
                addrPool.FreeAddress(bAddress);
                bAddress = 0;
                return rcode;
        }

        //USBTRACE2("\r\nHub address: ", bAddress );

        // Restore p->epinfo
        p->epinfo = oldep_ptr;

        if(len)
                rcode = pUsb->getDevDescr(bAddress, 0, len, (uint8_t*)buf);

        if(rcode)
                goto FailGetDevDescr;

        // Assign epInfo to epinfo pointer
        rcode = pUsb->setEpInfoEntry(bAddress, 2, epInfo);

        if(rcode)
                goto FailSetDevTblEntry;

        //                bInitState = 1;

        //        case 1:
        // Get hub descriptor
        rcode = GetHubDescriptor(0, 8, buf);

        if(rcode)
                goto FailGetHubDescr;

        // Save number of ports for future use
        bNbrPorts = hd->bNbrPorts;

        //                bInitState = 2;

        //        case 2:
        // Read configuration Descriptor in Order To Obtain Proper Configuration Value
        rcode = pUsb->getConfDescr(bAddress, 0, 8, 0, buf);

        if(!rcode) {
                cd_len = ucd->wTotalLength;
                rcode = pUsb->getConfDescr(bAddress, 0, cd_len, 0, buf);
        }
        if(rcode)
                goto FailGetConfDescr;

        // The following code is of no practical use in real life applications.
        // It only intended for the usb protocol sniffer to properly parse hub-class requests.
        {
                uint8_t buf2[24];

                rcode = pUsb->getConfDescr(bAddress, 0, buf[0], 0, buf2);

                if(rcode)
                        goto FailGetConfDescr;
        }

        // Set Configuration Value
        rcode = pUsb->setConf(bAddress, 0, buf[5]);

        if(rcode)
                goto FailSetConfDescr;

        //                bInitState = 3;

        //        case 3:
        // Power on all ports
        for(uint8_t j = 1; j <= bNbrPorts; j++)
                SetPortFeature(HUB_FEATURE_PORT_POWER, j, 0); //HubPortPowerOn(j);

        pUsb->SetHubPreMask();
        bPollEnable = true;
        //                bInitState = 0;
        //}
        //bInitState = 0;
        //USBTRACE("...OK\r\n");
        return 0;

        // Oleg, No debugging?? -- xxxajk
FailGetDevDescr:
        goto Fail;

FailSetDevTblEntry:
        goto Fail;

FailGetHubDescr:
        goto Fail;

FailGetConfDescr:
        goto Fail;

FailSetConfDescr:
        goto Fail;

Fail:
        USBTRACE("...FAIL\r\n");
        return rcode;
}