//***************************************************************************** // // 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); }
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; }