//-------------------------------------------------------------- USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost, uint16_t length) { USBH_Status status; uint16_t index = 0; if((status = USBH_GetDescriptor(pdev, phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_CONFIGURATION, pdev->host.Rx_Buffer, length)) == USBH_OK) { /*save Cfg descriptor for class parsing usage */ for( ; index < length ; index ++) { USBH_CfgDesc[index] = pdev->host.Rx_Buffer[index]; } /* Commands successfully sent and Response Received */ USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc, phost->device_prop.Itf_Desc, phost->device_prop.Ep_Desc, pdev->host.Rx_Buffer, length); } return status; }
/** * @brief USBH_Get_CfgDesc * Issues Configuration Descriptor to the device. Once the response * received, it parses the configuartion descriptor and updates the * status. * @param phost: Host Handle * @param length: Length of the descriptor * @retval USBH Status */ USBH_StatusTypeDef USBH_Get_CfgDesc(USBH_HandleTypeDef *phost, uint16_t length) { USBH_StatusTypeDef status; uint8_t *pData; #if (USBH_KEEP_CFG_DESCRIPTOR == 1) pData = phost->device.CfgDesc_Raw; #else pData = phost->device.Data; #endif if((status = USBH_GetDescriptor(phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_CONFIGURATION, pData, length)) == USBH_OK) { /* Commands successfully sent and Response Received */ USBH_ParseCfgDesc (&phost->device.CfgDesc, pData, length); } return status; }
/** * @brief USBH_Get_CfgDesc * Issues Configuration Descriptor to the device. Once the response * received, it parses the configuration descriptor and updates the * status. * @param pdev: Selected device * @param cfg_desc: Configuration Descriptor address * @param itf_desc: Interface Descriptor address * @param ep_desc: Endpoint Descriptor address * @param length: Length of the descriptor * @retval Status */ USBH_Status USBH_Get_CfgDesc(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost, uint16_t length) { USBH_Status status, result; if((status = USBH_GetDescriptor(pdev, phost, USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD, USB_DESC_CONFIGURATION, Cfg_Rx_Buffer, length)) == USBH_OK) { /* Commands successfully sent and Response Received */ result = USBH_ParseCfgDesc (&phost->device_prop.Cfg_Desc, phost->device_prop.Itf_Desc, phost->device_prop.Ep_Desc, Cfg_Rx_Buffer, length); if (result != USBH_OK) status= result; } return status; }
uint8_t USBPTD_SetupStage(USB_OTG_CORE_HANDLE* pcore, USB_SETUP_REQ* req) { // store for later use from another function memcpy(USBPT_LastSetupPacket, pcore->dev.setup_packet, 24); // print for monitoring USBPT_printf("\b\r\n USBPT:SETUP:"); for (uint8_t i = 0; i < 8; i++) { USBPT_printf(" 0x%02X", USBPT_LastSetupPacket[i]); } USBPT_printf("\r\n"); // prepare to be sent to the device memcpy(USBPT_Dev->Control.setup.d8, USBPT_LastSetupPacket, 8); // set address must be handled explicitly if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_SET_ADDRESS) { // let the internal code handle it for the device interface USBD_StdDevReq(pcore, req); // pass it to the downstream device USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100); USBD_CtlSendStatus(pcore); // modifiy our host channel to match USBPT_Dev->device_prop.address = (uint8_t)(req->wValue) & 0x7F; USBH_Modify_Channel (&USB_OTG_Core_host, USBPT_Dev->Control.hc_num_in, USBPT_Dev->device_prop.address, 0, 0, 0); USBH_Modify_Channel (&USB_OTG_Core_host, USBPT_Dev->Control.hc_num_out, USBPT_Dev->device_prop.address, 0, 0, 0); // modify all other channels to match for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i]; uint8_t hc = pl->hc; if (hc != 0 && hc != HC_ERROR) // if listener is actually allocated { USBH_EpDesc_TypeDef* epDesc = pl->epDesc; uint8_t epType = 0; if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) { epType = EP_TYPE_CTRL; } USBH_Modify_Channel( &USB_OTG_Core_host, USBPTH_Listeners[i].hc, USBPT_Dev->device_prop.address, USBPT_Dev->device_prop.speed, epType, USBPTH_Listeners[i].epDesc->wMaxPacketSize); } } // note: out direction channels are dynamically allocated only when needed // so we don't need to modify those channel addresses return USBD_OK; } // no data means we can just directly relay the data if (req->wLength == 0) { USBH_CtlReq_Blocking(&USB_OTG_Core_host, USBPT_Dev, 0, 0, 100); USBD_CtlSendStatus(pcore); return USBD_OK; } // there is extra data later USBPT_CtrlDataLen = req->wLength; if (USBPT_CtrlData != 0) free(USBPT_CtrlData); USBPT_CtrlData = malloc(USBPT_CtrlDataLen); USBH_Status status; // wait until previous req is finished delay_1ms_cnt = 100; while (delay_1ms_cnt > 0 && USBPT_Dev->Control.state != CTRL_COMPLETE && USBPT_Dev->Control.state != CTRL_IDLE && USBPT_Dev->Control.state != CTRL_ERROR && USBPT_Dev->Control.state != CTRL_STALLED); { status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev); } // finalize previous ctrl req if (USBPT_Dev->RequestState == CMD_WAIT) { USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, 0 , 0 ); } // prepare new setup USBH_SubmitSetupRequest(USBPT_Dev, USBPT_CtrlData, USBPT_CtrlDataLen); USBPT_Dev->RequestState = CMD_WAIT; USBH_CtlSendSetup (&USB_OTG_Core_host, USBPT_Dev->Control.setup.d8, USBPT_Dev->Control.hc_num_out); USBPT_Dev->Control.state = CTRL_SETUP_WAIT; USBPT_Dev->Control.timer = HCD_GetCurrentFrame(pcore); USBPT_Dev->Control.timeout = 50; if ((req->bmRequest & 0x80) == 0) { // H2D // we need to obtain the data from EP0_RxReady first USBD_CtlPrepareRx (pcore, USBPT_CtrlData, USBPT_CtrlDataLen); return USBD_OK; } else { // D2H // wait for request to finish delay_1ms_cnt = 100; do { status = USBH_CtlReq(&USB_OTG_Core_host, USBPT_Dev, USBPT_CtrlData , USBPT_CtrlDataLen ); if (status == USBH_OK || status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } else { status = USBH_HandleControl(&USB_OTG_Core_host, USBPT_Dev); if (status == USBH_FAIL || status == USBH_STALL || status == USBH_NOT_SUPPORTED) { break; } } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { // timeout dbg_printf(DBGMODE_ERR, "USBPT Setup Timed Out \r\n"); USBD_CtlSendStatus(pcore); // we reply with nothing to simulate a timeout return USBH_OK; } else if (status == USBH_OK) { // all good, send back the data USBD_CtlSendData (pcore, USBPT_CtrlData, USBPT_CtrlDataLen); // handle config descriptors specially, we need to know what channels to open based on endpoints if ((req->bmRequest & 0x7F) == (USB_REQ_RECIPIENT_DEVICE | USB_REQ_TYPE_STANDARD) && req->bRequest == USB_REQ_GET_DESCRIPTOR && req->wValue == USB_DESC_CONFIGURATION && req->wLength > USB_CONFIGURATION_DESC_SIZE) { // this is a full length configuration descriptor // we need this info to open as many D2H endpoints to channels USBH_ParseCfgDesc(&USBPT_Dev->device_prop.Cfg_Desc, USBPT_Dev->device_prop.Itf_Desc, USBPT_Dev->device_prop.Ep_Desc, USBPT_CtrlData, USBPT_CtrlDataLen); USBPTH_OutEPCnt = 0; USBPT_GeneralInDataLen = 0; for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++) { for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++) { USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j]; for (uint8_t k = 0; k < USBPTH_MAX_LISTENERS; k++) { if ((epDesc->bEndpointAddress & USB_EP_DIR_MSK) == USB_D2H && USBPTH_Listeners[k].used == 0) { USBPTH_Listeners[k].epDesc = epDesc; uint8_t epType = 0; if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_CTRL) { epType = EP_TYPE_CTRL; } USBH_Open_Channel( &USB_OTG_Core_host, &(USBPTH_Listeners[k].hc), epDesc->bEndpointAddress, USBPT_Dev->device_prop.address, USBPT_Dev->device_prop.speed, epType, USBPTH_Listeners[k].epDesc->wMaxPacketSize); if (USBPTH_Listeners[k].hc >= 0) { USBPTH_Listeners[k].used = 1; DCD_EP_Open(&USB_OTG_Core_dev, epDesc->bEndpointAddress, epDesc->wMaxPacketSize, epType); if (epDesc->wMaxPacketSize > USBPT_GeneralInDataMax) { USBPT_GeneralInDataMax = epDesc->wMaxPacketSize; } } } } if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) { USBPTH_OutEPCnt++; } } } if (USBPT_GeneralInData != 0) free(USBPT_GeneralInData); // release memory if previously allocated USBPT_GeneralInData = malloc(USBPT_GeneralInDataMax); // only allocate the memory we need if (USBPTH_OutEP != 0) free(USBPTH_OutEP); // release memory if previously allocated USBPTH_OutEP = malloc(sizeof(USBH_EpDesc_TypeDef*) * USBPTH_OutEPCnt); // only allocate the memory we need uint8_t ec = 0; for (uint8_t i = 0; i < USBPT_Dev->device_prop.Cfg_Desc.bNumInterfaces && i < USBH_MAX_NUM_INTERFACES; i++) { for (uint8_t j = 0; j < USBPT_Dev->device_prop.Itf_Desc[i].bNumEndpoints && j < USBH_MAX_NUM_ENDPOINTS; j++) { USBH_EpDesc_TypeDef* epDesc = &USBPT_Dev->device_prop.Ep_Desc[i][j]; if ((epDesc->bEndpointAddress & 0x80) == USB_H2D) { // only save the H2D direction endpoints USBPTH_OutEP[ec] = epDesc; ec++; } } } } return USBH_OK; } else { if (status == USBH_STALL || status == USBH_NOT_SUPPORTED) { dbg_printf(DBGMODE_ERR, "USBPT Setup Stalled \r\n"); USBD_CtlError(pcore , req); return USBH_OK; } } return USBD_OK; } dbg_printf(DBGMODE_ERR, "USBPT Setup Unhandled Error \r\n"); USBD_CtlError(pcore , req); return USBD_OK; }