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; } }
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 Handle HID Control process * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_MTP_Events (USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_BUSY ; MTP_HandleTypeDef *MTP_Handle = phost->pActiveClass->pData; switch(MTP_Handle->events.state) { case MTP_EVENTS_INIT: if((phost->Timer & 1) == 0) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); MTP_Handle->events.state = MTP_EVENTS_GETDATA ; } break; case MTP_EVENTS_GETDATA: if(USBH_LL_GetURBState(phost , MTP_Handle->NotificationPipe) == USBH_URB_DONE) { MTP_DecodeEvent(phost); } if(( phost->Timer - MTP_Handle->events.timer) >= MTP_Handle->events.poll) { MTP_Handle->events.timer = phost->Timer; USBH_InterruptReceiveData(phost, (uint8_t *)&(MTP_Handle->events.container), MTP_Handle->NotificationEpSize, MTP_Handle->NotificationPipe); } break; default: break; } return status; }
/** * @brief The function is responsible for sending data to the device * @param pdev: Selected device * @retval None */ static void CDC_ProcessTransmission(USBH_HandleTypeDef *phost) { CDC_HandleTypeDef *CDC_Handle = (CDC_HandleTypeDef*) phost->pActiveClass->pData; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; switch(CDC_Handle->data_tx_state) { case CDC_SEND_DATA: if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) { USBH_BulkSendData (phost, CDC_Handle->pTxData, CDC_Handle->DataItf.OutEpSize, CDC_Handle->DataItf.OutPipe, 1); } else { USBH_BulkSendData (phost, CDC_Handle->pTxData, CDC_Handle->TxDataLength, CDC_Handle->DataItf.OutPipe, 1); } CDC_Handle->data_tx_state = CDC_SEND_DATA_WAIT; break; case CDC_SEND_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, CDC_Handle->DataItf.OutPipe); /*Check the status done for transmission*/ if(URB_Status == USBH_URB_DONE ) { if(CDC_Handle->TxDataLength > CDC_Handle->DataItf.OutEpSize) { CDC_Handle->TxDataLength -= CDC_Handle->DataItf.OutEpSize ; CDC_Handle->pTxData += CDC_Handle->DataItf.OutEpSize; } else { CDC_Handle->TxDataLength = 0; } if( CDC_Handle->TxDataLength > 0) { CDC_Handle->data_tx_state = CDC_SEND_DATA; } else { CDC_Handle->data_tx_state = CDC_IDLE; USBH_CDC_TransmitCallback(phost); } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif } else if( URB_Status == USBH_URB_NOTREADY ) { CDC_Handle->data_tx_state = CDC_SEND_DATA; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CLASS_EVENT, 0); #endif } break; default: break; } }
/** * @brief USBH_HID_Process * The function is for managing state machine for HID data transfers * @param phost: Host handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HID_Process(USBH_HandleTypeDef *phost) { USBH_StatusTypeDef status = USBH_OK; HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; switch (HID_Handle->state) { case HID_INIT: HID_Handle->Init(phost); case HID_IDLE: if(USBH_HID_GetReport (phost, 0x01, 0, HID_Handle->pData, HID_Handle->length) == USBH_OK) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->state = HID_SYNC; } break; case HID_SYNC: /* Sync with start of Even Frame */ if(phost->Timer & 1) { HID_Handle->state = HID_GET_DATA; } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif break; case HID_GET_DATA: USBH_InterruptReceiveData(phost, HID_Handle->pData, HID_Handle->length, HID_Handle->InPipe); HID_Handle->state = HID_POLL; HID_Handle->timer = phost->Timer; HID_Handle->DataReady = 0; break; case HID_POLL: if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_DONE) { if(HID_Handle->DataReady == 0) { fifo_write(&HID_Handle->fifo, HID_Handle->pData, HID_Handle->length); HID_Handle->DataReady = 1; USBH_HID_EventCallback(phost); #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_URB_EVENT, 0); #endif } } else if(USBH_LL_GetURBState(phost , HID_Handle->InPipe) == USBH_URB_STALL) /* IN Endpoint Stalled */ { /* Issue Clear Feature on interrupt IN endpoint */ if(USBH_ClrFeature(phost, HID_Handle->ep_addr) == USBH_OK) { /* Change state to issue next IN token */ HID_Handle->state = HID_GET_DATA; } } break; default: break; } return status; }
/** * @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_HandleControl * Handles the USB control transfer state machine * @param phost: Host Handle * @retval USBH Status */ static USBH_StatusTypeDef USBH_HandleControl (USBH_HandleTypeDef *phost) { uint8_t direction; USBH_StatusTypeDef status = USBH_BUSY; USBH_URBStateTypeDef URB_Status = USBH_URB_IDLE; switch (phost->Control.state) { case CTRL_SETUP: /* send a SETUP packet */ USBH_CtlSendSetup (phost, (uint8_t *)phost->Control.setup.d8 , phost->Control.pipe_out); phost->Control.state = CTRL_SETUP_WAIT; break; case CTRL_SETUP_WAIT: URB_Status = USBH_LL_GetURBState(phost, phost->Control.pipe_out); /* case SETUP packet sent successfully */ if(URB_Status == USBH_URB_DONE) { direction = (phost->Control.setup.b.bmRequestType & USB_REQ_DIR_MASK); /* check if there is a data stage */ if (phost->Control.setup.b.wLength.w != 0 ) { if (direction == USB_D2H) { /* Data Direction is IN */ phost->Control.state = CTRL_DATA_IN; } else { /* Data Direction is OUT */ phost->Control.state = CTRL_DATA_OUT; } } /* No DATA stage */ else { /* If there is No Data Transfer Stage */ if (direction == USB_D2H) { /* Data Direction is IN */ phost->Control.state = CTRL_STATUS_OUT; } else { /* Data Direction is OUT */ phost->Control.state = CTRL_STATUS_IN; } } #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if(URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_DATA_IN: /* Issue an IN token */ phost->Control.timer = phost->Timer; USBH_CtlReceiveData(phost, phost->Control.buff, phost->Control.length, phost->Control.pipe_in); phost->Control.state = CTRL_DATA_IN_WAIT; break; case CTRL_DATA_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); /* check is DATA packet transfered successfully */ if (URB_Status == USBH_URB_DONE) { phost->Control.state = CTRL_STATUS_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } /* manage error cases*/ if (URB_Status == USBH_URB_STALL) { /* In stall case, return to previous machine state*/ status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { /* Device error */ phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_DATA_OUT: USBH_CtlSendData (phost, phost->Control.buff, phost->Control.length , phost->Control.pipe_out, 1); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_DATA_OUT_WAIT; break; case CTRL_DATA_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); if (URB_Status == USBH_URB_DONE) { /* If the Setup Pkt is sent successful, then change the state */ phost->Control.state = CTRL_STATUS_IN; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } /* handle error cases */ else if (URB_Status == USBH_URB_STALL) { /* In stall case, return to previous machine state*/ phost->Control.state = CTRL_STALLED; status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_NOTREADY) { /* Nack received from device */ phost->Control.state = CTRL_DATA_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { /* device error */ phost->Control.state = CTRL_ERROR; status = USBH_FAIL; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_STATUS_IN: /* Send 0 bytes out packet */ USBH_CtlReceiveData (phost, 0, 0, phost->Control.pipe_in); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_STATUS_IN_WAIT; break; case CTRL_STATUS_IN_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_in); if ( URB_Status == USBH_URB_DONE) { /* Control transfers completed, Exit the State Machine */ phost->Control.state = CTRL_COMPLETE; status = USBH_OK; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if(URB_Status == USBH_URB_STALL) { /* Control transfers completed, Exit the State Machine */ status = USBH_NOT_SUPPORTED; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_STATUS_OUT: USBH_CtlSendData (phost, 0, 0, phost->Control.pipe_out, 1); phost->Control.timer = phost->Timer; phost->Control.state = CTRL_STATUS_OUT_WAIT; break; case CTRL_STATUS_OUT_WAIT: URB_Status = USBH_LL_GetURBState(phost , phost->Control.pipe_out); if (URB_Status == USBH_URB_DONE) { status = USBH_OK; phost->Control.state = CTRL_COMPLETE; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_NOTREADY) { phost->Control.state = CTRL_STATUS_OUT; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } else if (URB_Status == USBH_URB_ERROR) { phost->Control.state = CTRL_ERROR; #if (USBH_USE_OS == 1) osMessagePut ( phost->os_event, USBH_CONTROL_EVENT, 0); #endif } break; case CTRL_ERROR: /* After a halt condition is encountered or an error is detected by the host, a control endpoint is allowed to recover by accepting the next Setup PID; i.e., recovery actions via some other pipe are not required for control endpoints. For the Default Control Pipe, a device reset will ultimately be required to clear the halt or error condition if the next Setup PID is not accepted. */ if (++ phost->Control.errorcount <= USBH_MAX_ERROR_COUNT) { /* try to recover control */ USBH_LL_Stop(phost); /* Do the transmission again, starting from SETUP Packet */ phost->Control.state = CTRL_SETUP; phost->RequestState = CMD_SEND; } else { phost->Control.errorcount = 0; USBH_ErrLog("Control error"); status = USBH_FAIL; } break; default: break; } return status; }
static USBH_StatusTypeDef USBH_AOA_OutHandle(USBH_HandleTypeDef *phost) { USBH_URBStateTypeDef URB_Status; AOA_HandleTypeDef* aoa = phost->pActiveClass->pData; switch (aoa->outState) { case AOA_SEND_IDLE: break; case AOA_SEND_DATA: USBH_BulkSendData(phost, aoa->outbuff, aoa->outSize, aoa->hc_num_out, 0); aoa->outState = AOA_SEND_DATA_WAIT; break; case AOA_SEND_DATA_WAIT: URB_Status = USBH_LL_GetURBState(phost, aoa->hc_num_out); switch (URB_Status) { case USBH_URB_DONE: aoa->outbuff[aoa->outSize] = '\0'; DEBUG_LOG("AOA: out %d bytes, \"%s\"", aoa->outSize, aoa->outbuff); if (aoa->sendDoneCallback) { aoa->sendDoneCallback(phost, aoa->outbuff, aoa->outSize); } aoa->outbuff = NULL; aoa->outSize = 0; aoa->outState = AOA_SEND_IDLE; break; case USBH_URB_NOTREADY: DEBUG_LOG("AOA: OUT URB_NOTREADY. Retry"); aoa->outState = AOA_SEND_DATA; break; case USBH_URB_STALL: // TODO These codes are not tested /* Issue Clear Feature */ if (USBH_ClrFeature(phost, aoa->BulkOutEp) == USBH_OK) { aoa->outState = AOA_SEND_DATA; DEBUG_LOG("AOA: OUT URB_STALL. Clear feature on EP. Retry."); } break; case USBH_URB_ERROR: aoa->outbuff[aoa->outSize] = '\0'; DEBUG_LOG("AOA: SEND Fail"); if (aoa->sendDoneCallback) { aoa->sendDoneCallback(phost, aoa->outbuff, -1); } aoa->outbuff = NULL; aoa->outSize = 0; aoa->outState = AOA_SEND_IDLE; break; default: break; } break; } return USBH_OK; }