static void CDC_ProcessReception(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef*) phost->pActiveClass->pData; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; uint16_t length; switch(CDC_Handle->data_rx_state) { case CDC_RECEIVE_DATA: USBH_BulkReceiveData (phost, CDC_Handle->pRxData, CDC_Handle->DataItf.InEpSize, CDC_Handle->DataItf.InPipe); CDC_Handle->data_rx_state = CDC_RECEIVE_DATA_WAIT; break; case CDC_RECEIVE_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.InPipe); /*Check the status done for reception*/ if(URB_Status == USBH_URB_DONE ) { length = USBH_LL_GetLastXferSize(phost, CDC_Handle->DataItf.InPipe); if(((CDC_Handle->RxDataLength - length) > 0) && (length > CDC_Handle->DataItf.InEpSize)) { CDC_Handle->RxDataLength -= length ; CDC_Handle->pRxData += length; CDC_Handle->data_rx_state = CDC_RECEIVE_DATA; } else { CDC_Handle->data_rx_state = CDC_IDLE; USBH_CDC_ReceiveCallback(phost); } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif } break; default: break; } }
/** * @brief This function responsible for reception of data from the device * @param pdev: Selected device * @retval None */ static void CDC_ProcessReception(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) { if(RX_Enabled == 1) { URB_STATE URB_StatusRx = HCD_GetURB_State(pdev , CDC_Machine.CDC_DataItf.hc_num_in); switch(CDC_RxParam.CDCState) { case CDC_IDLE: /*check the received length lesser then the remaining space available in the buffer */ if(CDC_RxParam.DataLength < (CDC_RxParam.BufferLen - CDC_Machine.CDC_DataItf.length)) { /*Receive the data */ USBH_BulkReceiveData(pdev, CDC_RxParam.pFillBuff, CDC_Machine.CDC_DataItf.length, CDC_Machine.CDC_DataItf.hc_num_in); /*change the cdc state to USBH_CDC_GET_DATA*/ CDC_RxParam.CDCState = CDC_GET_DATA; } break; case CDC_GET_DATA: /*Check the last state of the device is URB_DONE */ if(URB_StatusRx == URB_DONE) { /* Move the pointer as well as datalength */ CDC_RxParam.DataLength += pdev->host.hc[CDC_Machine.CDC_DataItf.hc_num_in].xfer_count ; CDC_RxParam.pFillBuff += pdev->host.hc[CDC_Machine.CDC_DataItf.hc_num_in].xfer_count ; /* Process the recived data */ CDC_ReceiveData(&CDC_RxParam); /*change the state od the CDC state*/ CDC_RxParam.CDCState = CDC_IDLE; } break; } } }
static USBH_StatusTypeDef USBH_AOA_InHandle(USBH_HandleTypeDef *phost) { USBH_URBStateTypeDef URB_Status; uint32_t size; AOA_HandleTypeDef* aoa = phost->pActiveClass->pData; switch (aoa->inState) { case AOA_RECV_DATA: USBH_BulkReceiveData(phost, aoa->inbuff, USBH_AOA_DATA_SIZE, aoa->hc_num_in); aoa->inState = AOA_RECV_DATA_WAIT; break; case AOA_RECV_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, aoa->hc_num_in); if (URB_Status == USBH_URB_DONE) { size = USBH_LL_GetLastXferSize(phost, aoa->hc_num_in); if (size > 0) { if (DebugConfig.print_aoa_recvdata) { if (printable(aoa->inbuff, size)) { aoa->inbuff[size] = '\0'; USBH_UsrLog("AOA: in %u bytes, \"%s\"", (unsigned int)size, aoa->inbuff); } else { USBH_UsrLog("AOA: in %u bytes, %s", (unsigned int)size, bytes2bin(aoa->inbuff, size)); } } if (aoa->recvCallback) { aoa->recvCallback(phost, aoa->inbuff, size); } aoa->inState = AOA_RECV_DATA; } } break; } return USBH_OK; }
/** * @brief USBH_MSC_BOT_Process * The function handle the BOT protocol. * @param phost: Host handle * @param lun: Logical Unit Number * @retval USBH Status */ USBH_StatusTypeDef USBH_MSC_BOT_Process (USBH_HandleTypeDef *phost, uint8_t lun) { USBH_StatusTypeDef status = USBH_BUSY; USBH_StatusTypeDef error = USBH_BUSY; BOT_CSWStatusTypeDef CSW_Status = BOT_CSW_CMD_FAILED; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; MSC_HandleTypeDef *MSC_Handle = (MSC_HandleTypeDef *) phost->pActiveClass->pData; uint8_t toggle = 0; switch (MSC_Handle->hbot.state) { case BOT_SEND_CBW: MSC_Handle->hbot.cbw.field.LUN = lun; MSC_Handle->hbot.state = BOT_SEND_CBW_WAIT; USBH_BulkSendData (phost, MSC_Handle->hbot.cbw.data, BOT_CBW_LENGTH, MSC_Handle->OutPipe, 1); break; case BOT_SEND_CBW_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); if(URB_Status == USBH_URB_DONE) { if ( MSC_Handle->hbot.cbw.field.DataTransferLength != 0 ) { /* If there is Data Transfer Stage */ if (((MSC_Handle->hbot.cbw.field.Flags) & USB_REQ_DIR_MASK) == USB_D2H) { /* Data Direction is IN */ MSC_Handle->hbot.state = BOT_DATA_IN; } else { /* Data Direction is OUT */ MSC_Handle->hbot.state = BOT_DATA_OUT; } } else {/* If there is NO Data Transfer Stage */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Re-send CBW */ MSC_Handle->hbot.state = BOT_SEND_CBW; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_DATA_IN: /* Send first packet */ USBH_BulkReceiveData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->InEpSize , MSC_Handle->InPipe); MSC_Handle->hbot.state = BOT_DATA_IN_WAIT; break; case BOT_DATA_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); if(URB_Status == USBH_URB_DONE) { /* Adjust Data pointer and data length */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->InEpSize) { MSC_Handle->hbot.pbuf += MSC_Handle->InEpSize; MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->InEpSize; } else { MSC_Handle->hbot.cbw.field.DataTransferLength = 0; } /* More Data To be Received */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) { /* Send next packet */ USBH_BulkReceiveData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->InEpSize , MSC_Handle->InPipe); } else { /* If value was 0, and successful transfer, then change the state */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(URB_Status == USBH_URB_STALL) { /* This is Data IN Stage STALL Condition */ MSC_Handle->hbot.state = BOT_ERROR_IN; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.2 Host expects to receive data from the device 3. On a STALL condition receiving data, then: The host shall accept the data received. The host shall clear the Bulk-In pipe. 4. The host shall attempt to receive a CSW.*/ #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_DATA_OUT: USBH_BulkSendData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->OutEpSize , MSC_Handle->OutPipe, 1); MSC_Handle->hbot.state = BOT_DATA_OUT_WAIT; break; case BOT_DATA_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->OutPipe); if(URB_Status == USBH_URB_DONE) { /* Adjust Data pointer and data length */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > MSC_Handle->OutEpSize) { MSC_Handle->hbot.pbuf += MSC_Handle->OutEpSize; MSC_Handle->hbot.cbw.field.DataTransferLength -= MSC_Handle->OutEpSize; } else { MSC_Handle->hbot.cbw.field.DataTransferLength = 0; } /* More Data To be Sent */ if(MSC_Handle->hbot.cbw.field.DataTransferLength > 0) { USBH_BulkSendData (phost, MSC_Handle->hbot.pbuf, MSC_Handle->OutEpSize , MSC_Handle->OutPipe, 1); } else { /* If value was 0, and successful transfer, then change the state */ MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_NOTREADY) { /* Resend same data */ MSC_Handle->hbot.state = BOT_DATA_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_OUT; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.3 Ho - Host expects to send data to the device 3. On a STALL condition sending data, then: " The host shall clear the Bulk-Out pipe. 4. The host shall attempt to receive a CSW. */ #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_RECEIVE_CSW: USBH_BulkReceiveData (phost, MSC_Handle->hbot.csw.data, BOT_CSW_LENGTH , MSC_Handle->InPipe); MSC_Handle->hbot.state = BOT_RECEIVE_CSW_WAIT; break; case BOT_RECEIVE_CSW_WAIT: URB_Status = USBH_LL_GetURBState(phost, MSC_Handle->InPipe); /* Decode CSW */ if(URB_Status == USBH_URB_DONE) { MSC_Handle->hbot.state = BOT_SEND_CBW; MSC_Handle->hbot.cmd_state = BOT_CMD_SEND; CSW_Status = USBH_MSC_DecodeCSW(phost); if(CSW_Status == BOT_CSW_CMD_PASSED) { status = USBH_OK; } else { status = USBH_FAIL; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { MSC_Handle->hbot.state = BOT_ERROR_IN; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } break; case BOT_ERROR_IN: error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_IN); if (error == USBH_OK) { MSC_Handle->hbot.state = BOT_RECEIVE_CSW; } else if (error == USBH_UNRECOVERED_ERROR) { /* This means that there is a STALL Error limit, Do Reset Recovery */ MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; } break; case BOT_ERROR_OUT: error = USBH_MSC_BOT_Abort(phost, lun, BOT_DIR_OUT); if ( error == USBH_OK) { toggle = USBH_LL_GetToggle(phost, MSC_Handle->OutPipe); USBH_LL_SetToggle(phost, MSC_Handle->OutPipe, 1- toggle); USBH_LL_SetToggle(phost, MSC_Handle->InPipe, 0); MSC_Handle->hbot.state = BOT_ERROR_IN; } else if (error == USBH_UNRECOVERED_ERROR) { MSC_Handle->hbot.state = BOT_UNRECOVERED_ERROR; } break; case BOT_UNRECOVERED_ERROR: status = USBH_MSC_BOT_REQ_Reset(phost); if ( status == USBH_OK) { MSC_Handle->hbot.state = BOT_SEND_CBW; } break; default: break; } return status; }
/** * @brief USBH_MSC_HandleBOTXfer * This function manages the different states of BOT transfer and * updates the status to upper layer. * @param None * @retval None * */ void USBH_MSC_HandleBOTXfer(USB_OTG_CORE_HANDLE *pdev, USBH_HOST *phost) { uint8_t xferDirection, index; static uint32_t remainingDataLength; static uint8_t *datapointer, *datapointer_prev; static uint8_t error_direction; USBH_Status status; URB_STATE URB_Status = URB_IDLE; if (HCD_IsDeviceConnected(pdev)) { switch (USBH_MSC_BOTXferParam.BOTState) { case USBH_MSC_SEND_CBW: /* send CBW */ USBH_BulkSendData(pdev, &USBH_MSC_CBWData.CBWArray[0], USBH_MSC_BOT_CBW_PACKET_LENGTH, MSC_Machine.hc_num_out); USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SEND_CBW; USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SENT_CBW; break; case USBH_MSC_SENT_CBW: URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_out); if (URB_Status == URB_DONE) { BOTStallErrorCount = 0; USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_SENT_CBW; /* If the CBW Pkt is sent successful, then change the state */ xferDirection = (USBH_MSC_CBWData.field.CBWFlags & USB_REQ_DIR_MASK); if (USBH_MSC_CBWData.field.CBWTransferLength != 0) { remainingDataLength = USBH_MSC_CBWData.field.CBWTransferLength; datapointer = USBH_MSC_BOTXferParam.pRxTxBuff; datapointer_prev = datapointer; /* If there is Data Transfer Stage */ if (xferDirection == USB_D2H) { /* Data Direction is IN */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAIN_STATE; } else { /* Data Direction is OUT */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_DATAOUT_STATE; } } else {/* If there is NO Data Transfer Stage */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; } } else if (URB_Status == URB_NOTREADY) { USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; } else if (URB_Status == URB_STALL) { error_direction = USBH_MSC_DIR_OUT; USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; } break; case USBH_MSC_BOT_DATAIN_STATE: URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_in); /* BOT DATA IN stage */ if ((URB_Status == URB_DONE) || (USBH_MSC_BOTXferParam.BOTStateBkp != USBH_MSC_BOT_DATAIN_STATE)) { BOTStallErrorCount = 0; USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAIN_STATE; if (remainingDataLength > MSC_Machine.MSBulkInEpSize) { USBH_BulkReceiveData(pdev, datapointer, MSC_Machine.MSBulkInEpSize, MSC_Machine.hc_num_in); remainingDataLength -= MSC_Machine.MSBulkInEpSize; datapointer = datapointer + MSC_Machine.MSBulkInEpSize; } else if (remainingDataLength == 0) { /* If value was 0, and successful transfer, then change the state */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; } else { USBH_BulkReceiveData(pdev, datapointer, remainingDataLength, MSC_Machine.hc_num_in); remainingDataLength = 0; /* Reset this value and keep in same state */ } } else if (URB_Status == URB_STALL) { /* This is Data Stage STALL Condition */ error_direction = USBH_MSC_DIR_IN; USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.2 Host expects to receive data from the device 3. On a STALL condition receiving data, then: The host shall accept the data received. The host shall clear the Bulk-In pipe. 4. The host shall attempt to receive a CSW. USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original state after the ClearFeature Command is issued. */ USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; } break; case USBH_MSC_BOT_DATAOUT_STATE: /* BOT DATA OUT stage */ URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_out); if (URB_Status == URB_DONE) { BOTStallErrorCount = 0; USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_BOT_DATAOUT_STATE; if (remainingDataLength > MSC_Machine.MSBulkOutEpSize) { USBH_BulkSendData(pdev, datapointer, MSC_Machine.MSBulkOutEpSize, MSC_Machine.hc_num_out); datapointer_prev = datapointer; datapointer = datapointer + MSC_Machine.MSBulkOutEpSize; remainingDataLength = remainingDataLength - MSC_Machine.MSBulkOutEpSize; } else if (remainingDataLength == 0) { /* If value was 0, and successful transfer, then change the state */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_RECEIVE_CSW_STATE; } else { USBH_BulkSendData(pdev, datapointer, remainingDataLength, MSC_Machine.hc_num_out); remainingDataLength = 0; /* Reset this value and keep in same state */ } } else if (URB_Status == URB_NOTREADY) { if (datapointer != datapointer_prev) { USBH_BulkSendData(pdev, (datapointer - MSC_Machine.MSBulkOutEpSize), MSC_Machine.MSBulkOutEpSize, MSC_Machine.hc_num_out); } else { USBH_BulkSendData(pdev, datapointer, MSC_Machine.MSBulkOutEpSize, MSC_Machine.hc_num_out); } } else if (URB_Status == URB_STALL) { error_direction = USBH_MSC_DIR_OUT; USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; /* Refer to USB Mass-Storage Class : BOT (www.usb.org) 6.7.3 Ho - Host expects to send data to the device 3. On a STALL condition sending data, then: " The host shall clear the Bulk-Out pipe. 4. The host shall attempt to receive a CSW. The Above statement will do the clear the Bulk-Out pipe. The Below statement will help in Getting the CSW. USBH_MSC_BOTXferParam.BOTStateBkp is used to switch to the Original state after the ClearFeature Command is issued. */ USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; } break; case USBH_MSC_RECEIVE_CSW_STATE: /* BOT CSW stage */ /* NOTE: We cannot reset the BOTStallErrorCount here as it may come from the clearFeature from previous command */ USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray; USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH; for (index = USBH_MSC_CSW_LENGTH; index != 0; index--) { USBH_MSC_CSWData.CSWArray[index] = 0; } USBH_MSC_CSWData.CSWArray[0] = 0; USBH_BulkReceiveData(pdev, USBH_MSC_BOTXferParam.pRxTxBuff, USBH_MSC_CSW_MAX_LENGTH, MSC_Machine.hc_num_in); USBH_MSC_BOTXferParam.BOTState = USBH_MSC_DECODE_CSW; break; case USBH_MSC_DECODE_CSW: URB_Status = HCD_GetURB_State(pdev, MSC_Machine.hc_num_in); /* Decode CSW */ if (URB_Status == URB_DONE) { BOTStallErrorCount = 0; USBH_MSC_BOTXferParam.BOTStateBkp = USBH_MSC_RECEIVE_CSW_STATE; USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOTXferParam.MSCStateCurrent; USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_DecodeCSW(pdev, phost); } else if (URB_Status == URB_STALL) { error_direction = USBH_MSC_DIR_IN; USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_IN; } break; case USBH_MSC_BOT_ERROR_IN: status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_IN); if (status == USBH_OK) { /* Check if the error was due in Both the directions */ if (error_direction == USBH_MSC_BOTH_DIR) {/* If Both directions are Needed, Switch to OUT Direction */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOT_ERROR_OUT; } else { /* Switch Back to the Original State, In many cases this will be USBH_MSC_RECEIVE_CSW_STATE state */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; } } else if (status == USBH_UNRECOVERED_ERROR) { /* This means that there is a STALL Error limit, Do Reset Recovery */ USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; } break; case USBH_MSC_BOT_ERROR_OUT: status = USBH_MSC_BOT_Abort(pdev, phost, USBH_MSC_DIR_OUT); if (status == USBH_OK) { /* Switch Back to the Original State */ USBH_MSC_BOTXferParam.BOTState = USBH_MSC_BOTXferParam.BOTStateBkp; } else if (status == USBH_UNRECOVERED_ERROR) { /* This means that there is a STALL Error limit, Do Reset Recovery */ USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_PHASE_ERROR; } break; default: break; } } }
/** * This function will do bulk transfer in lowlevel, it will send request to the host controller * * @param pipe the bulk transfer pipe. * @param buffer the data buffer to save requested data * @param nbytes the size of buffer * * @return the error code, RT_EOK on successfully. */ static int susb_bulk_xfer(upipe_t pipe, void* buffer, int nbytes, int timeout) { rt_uint8_t channel; int left = nbytes; rt_uint8_t *ptr; URB_STATE state; RT_ASSERT(pipe != RT_NULL); RT_ASSERT(buffer != RT_NULL); if(!(root_hub.port_status[0] & PORT_CCS) || (root_hub.port_status[0] & PORT_CCSC)) return -1; ptr = (rt_uint8_t*)buffer; channel = (rt_uint32_t)pipe->user_data & 0xFF; rt_sem_take(&sem_lock, RT_WAITING_FOREVER); if(pipe->ep.bEndpointAddress & USB_DIR_IN) { while(left > pipe->ep.wMaxPacketSize) { USBH_BulkReceiveData(&USB_OTG_Core, ptr, pipe->ep.wMaxPacketSize, channel); while(1) { state = HCD_GetURB_State(&USB_OTG_Core , channel); if(state == URB_DONE) break; else if(state == URB_NOTREADY) rt_kprintf("not ready\n"); else if(state == URB_STALL) rt_kprintf("stall\n"); //else if(state == URB_IDLE) rt_kprintf("idle\n"); } ptr += pipe->ep.wMaxPacketSize; left -= pipe->ep.wMaxPacketSize; } USBH_BulkReceiveData(&USB_OTG_Core, ptr, left, channel); while(1) { state = HCD_GetURB_State(&USB_OTG_Core , channel); if(state == URB_DONE) break; else if(state == URB_NOTREADY) rt_kprintf("not ready\n"); else if(state == URB_STALL) rt_kprintf("stall\n"); //else if(state == URB_IDLE) rt_kprintf("idle\n"); } } else { send_data: while(left > pipe->ep.wMaxPacketSize) { USBH_BulkSendData(&USB_OTG_Core, ptr, pipe->ep.wMaxPacketSize, channel); while(1) { state = HCD_GetURB_State(&USB_OTG_Core, channel); if(state == URB_DONE) break; if(state == URB_NOTREADY) goto send_data; } ptr += pipe->ep.wMaxPacketSize; left -= pipe->ep.wMaxPacketSize; } USBH_BulkSendData(&USB_OTG_Core, ptr, left, channel); while(1) { state = HCD_GetURB_State(&USB_OTG_Core , channel); if(state == URB_DONE) break; if(state == URB_NOTREADY) goto send_data; } } rt_sem_release(&sem_lock); return nbytes; }
void USBPT_Work() { if (USBPT_Has_Dev == 0) { if (HCD_IsDeviceConnected(&USB_OTG_Core_host) != 0) { USBPT_printf("USBPT Device Connecting \r\n"); if (USBH_Open_Channel( &USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in), 0x80, USBPT_Dev->device_prop.address, // still 0 at this point USBPT_Dev->device_prop.speed, EP_TYPE_CTRL, USBPT_Dev->Control.ep0size) == HC_OK && USBH_Open_Channel( &USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out), 0x00, USBPT_Dev->device_prop.address, // still 0 at this point USBPT_Dev->device_prop.speed, EP_TYPE_CTRL, USBPT_Dev->Control.ep0size) == HC_OK ) { DCD_DevConnect(&USB_OTG_Core_dev); USBPT_Has_Dev = 1; } else { dbg_printf(DBGMODE_ERR, "USBPT Unable to allocate control EP HC \r\n"); } } else { return; } } else { if (HCD_IsDeviceConnected(&USB_OTG_Core_host) == 0) { USBPT_printf("USBPT Device Disconnecting \r\n"); USBD_DeInit(&USB_OTG_Core_dev); DCD_DevDisconnect(&USB_OTG_Core_dev); USBPT_Has_Dev = 0; for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBH_Free_Channel(&USB_OTG_Core_host, &(USBPTH_Listeners[i].hc)); } USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_out)); USBH_Free_Channel(&USB_OTG_Core_host, &(USBPT_Dev->Control.hc_num_in)); } } for (uint8_t i = 0; i < USBPTH_MAX_LISTENERS; i++) { USBPTH_HC_EP_t* pl = &USBPTH_Listeners[i]; int8_t hc = USBPTH_Listeners[i].hc; if (hc >= 0) // if listener is actually allocated { USBH_EpDesc_TypeDef* epDesc = pl->epDesc; uint8_t epnum = epDesc->bEndpointAddress; uint8_t epType = 0; USBPT_GeneralInDataLen = epDesc->wMaxPacketSize; // try to send read tokens only on even frames if (USB_OTG_IsEvenFrame(&USB_OTG_Core_host) == 0) continue; dbg_trace(); // attempt to start the read, check the read type first if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_INTR) { epType = EP_TYPE_INTR; USBH_InterruptReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_BULK) { epType = EP_TYPE_BULK; USBH_BulkReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } else if ((epDesc->bmAttributes & USB_EP_TYPE_INTR) == USB_EP_TYPE_ISOC) { epType = EP_TYPE_ISOC; USBH_IsocReceiveData(&USB_OTG_Core_host, USBPT_GeneralInData, USBPT_GeneralInDataLen, hc); } // now we wait for a reply, or maybe there isn't one USBH_Status status; char sent = 0; delay_1ms_cnt = 100; do { URB_STATE us = HCD_GetURB_State(&USB_OTG_Core_host, hc); if (us == URB_DONE) { // data was indeed received // print it to the serial port for monitoring USBPT_printf("USBPT:IN:EP0x%02X:", epnum); for (uint16_t c = 0; c < USBPT_GeneralInDataLen; c++) { USBPT_printf(" 0x%02X", USBPT_GeneralInData[c]); } USBPT_printf("\r\n"); // relay the data to the host DCD_EP_Tx(&USB_OTG_Core_dev, epnum, USBPT_GeneralInData, USBPT_GeneralInDataLen); sent = 1; break; } else if (us == URB_ERROR) { dbg_printf(DBGMODE_ERR, "DataIn Error on EP 0x%02X \r\n", epnum); break; } else if (us == URB_STALL) { dbg_printf(DBGMODE_ERR, "DataIn Stalled EP 0x%02X \r\n", epnum); break; } else if (us == URB_NOTREADY) { // NAK, no data break; } } while (delay_1ms_cnt > 0); if (delay_1ms_cnt == 0) { dbg_printf(DBGMODE_ERR, "DataIn Read Timed Out EP 0x%02X \r\n", epnum); } } } }
static int _usb_bulkin_request_handle(USB_OTG_CORE_HANDLE * pdev , USBH_HOST * phost, wifi_usb_adapter_t *adapter) { wifi_usb_bulkin_request_t *rx_req = &adapter->usb_rx_req; static unsigned short timeout = 0; URB_STATE URB_Status = URB_IDLE; unsigned int actual_len = 0; int status = 1; switch (rx_req->state) { case USB_BULK_STATE_IDLE: status = 0; /* indicate the state machine could be blocked */ break; case USB_BULK_STATE_REQUEST: rx_req->packet_buffer = &rx_req->buffer[0]; rx_req->packet_len = pdev->host.hc[adapter->hc_num_in].max_packet; USBH_BulkReceiveData(pdev, rx_req->packet_buffer, rx_req->packet_len, adapter->hc_num_in); rx_req->retry = 3; rx_req->state = USB_BULK_STATE_REQUEST_WAIT; status = 0; /* indicate the state machine could be blocked */ timeout = BULK_DATA_STAGE_TIMEOUT; /* Set the delay timer to enable timeout for data stage completion. */ rx_req->timer = HCD_GetCurrentFrame(pdev); break; case USB_BULK_STATE_REQUEST_WAIT: URB_Status = HCD_GetURB_State(pdev , adapter->hc_num_in); rx_req->status = URB_Status; if (URB_Status == URB_DONE) { rx_req->state = USB_BULK_STATE_IDLE; actual_len = pdev->host.hc[adapter->hc_num_in].xfer_count; rx_req->len += actual_len; rx_req->packet_buffer = (unsigned char *)(rx_req->packet_buffer) + actual_len; if (actual_len < pdev->host.hc[adapter->hc_num_in].max_packet) { _usb_bulkin_complete(adapter); } else { if ((rx_req->len + pdev->host.hc[adapter->hc_num_in].max_packet) <= NOSWIFI_USB_RX_BUFFER_MAX_LEN) { rx_req->packet_len = pdev->host.hc[adapter->hc_num_in].max_packet; USBH_BulkReceiveData(pdev, rx_req->packet_buffer, rx_req->packet_len, adapter->hc_num_in); rx_req->retry = 3; rx_req->state = USB_BULK_STATE_REQUEST_WAIT; status = 0; /* indicate the state machine could be blocked */ timeout = BULK_DATA_STAGE_TIMEOUT; /* Set the delay timer to enable timeout for data stage completion. */ rx_req->timer = HCD_GetCurrentFrame(pdev); } else { rx_req->len = 0; _usb_bulkin_complete(adapter); } } } else if (URB_Status == URB_ERROR) { rx_req->state = USB_BULK_STATE_ERROR; } else if (URB_Status == URB_STALL) { rx_req->state = USB_BULK_STATE_ERROR; } break; case USB_BULK_STATE_ERROR: DBGPRINT(WHED_DEBUG_ERROR, "PANIC(%s - %d): %s - rx urb failed(%d).\n", __FILE__, __LINE__, __FUNCTION__, rx_req->status); if (rx_req->retry) { USB_OTG_BSP_uDelay(600); rx_req->retry--; rx_req->state = USB_BULK_STATE_REQUEST; } else { rx_req->state = USB_BULK_STATE_REQUEST; rx_req->state = USB_BULK_STATE_IDLE; rx_req->len = 0; _usb_bulkin_complete(adapter); } break; default: break; } timeout = timeout; /* avoid compiler's warning */ return status; }