USB_STATUS usb_class_mass_clear_bulk_pipe_on_usb ( USB_MASS_CLASS_INTF_STRUCT_PTR intf_ptr ) { /* Body */ USB_STATUS status = USB_OK; PIPE_INIT_PARAM_STRUCT_PTR pBulk_pipe = NULL; COMMAND_OBJECT_PTR cmd_ptr = NULL; uint_8 direction; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_clear_bulk_pipe_on_usb"); #endif /* Nothing can be done if there is nothing pending */ usb_class_mass_get_pending_request(intf_ptr, &cmd_ptr); if (cmd_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_clear_bulk_pipe_on_usb, no matching request"); #endif return (USB_STATUS)USB_MASS_NO_MATCHING_REQUEST; } /* Endif */ /* Determine pipe (Bulk IN or Bulk OUT) to clear */ if ((cmd_ptr->CBW_PTR->BMCBWFLAGS & MASK_NON_DIRECTION_BITS) == DIRECTION_IN) { pBulk_pipe = (PIPE_INIT_PARAM_STRUCT_PTR)intf_ptr->BULK_IN_PIPE; direction = REQ_TYPE_IN; } else { pBulk_pipe = (PIPE_INIT_PARAM_STRUCT_PTR)intf_ptr->BULK_OUT_PIPE; direction = REQ_TYPE_OUT; } /* Endif */ status = _usb_host_register_ch9_callback(intf_ptr->G.dev_handle, usb_class_mass_reset_callback, (pointer2)intf_ptr); if (status == USB_OK || status == USB_STATUS_TRANSFER_QUEUED) { /* Send a CLEAR PIPE command */ cmd_ptr->STATUS = STATUS_CLEAR_BULK_PIPE; status = _usb_host_ch9_clear_feature(intf_ptr->G.dev_handle, REQ_TYPE_ENDPOINT, (uint_8)(pBulk_pipe->ENDPOINT_NUMBER | direction), ENDPOINT_HALT); } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_clear_bulk_pipe_on_usb, SUCCESSFUL"); #endif return status; } /* Endbody */
USB_STATUS usb_class_mass_reset_recovery_on_usb ( USB_MASS_CLASS_INTF_STRUCT_PTR intf_ptr ) { /* Body */ PIPE_INIT_PARAM_STRUCT_PTR pPipe = NULL; COMMAND_OBJECT_PTR cmd_ptr = NULL; DEV_INSTANCE_PTR dev_ptr = (DEV_INSTANCE_PTR)intf_ptr->G.dev_handle; USB_STATUS status = USB_OK; USB_SETUP request; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb"); #endif /* Nothing can be done if there is nothing pending*/ usb_class_mass_get_pending_request(intf_ptr,&cmd_ptr); if(cmd_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb,no matching request"); #endif return (USB_STATUS) USB_MASS_NO_MATCHING_REQUEST; } /* Endif */ /* BULK device mass storage reset */ request.BMREQUESTTYPE = REQ_TYPE_CLASS | REQ_TYPE_INTERFACE | REQ_TYPE_OUT; request.BREQUEST = MASS_STORAGE_RESET; htou16(request.WVALUE, 0); htou16(request.WINDEX, ((INTERFACE_DESCRIPTOR_PTR)intf_ptr->G.intf_handle)->bInterfaceNumber); htou16(request.WLENGTH, 0); cmd_ptr->STATUS = STATUS_RESET_DEVICE; status = _usb_hostdev_cntrl_request (intf_ptr->G.dev_handle, &request, NULL, usb_class_mass_reset_callback, (pointer2)intf_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb,SUCCESSFUL"); #endif return status; } /* Endbody */
USB_STATUS usb_class_mass_reset_recovery_on_usb ( USB_MASS_CLASS_INTF_STRUCT_PTR intf_ptr ) { /* Body */ COMMAND_OBJECT_PTR cmd_ptr = NULL; USB_STATUS status = USB_OK; USB_SETUP request; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb"); #endif /* Nothing can be done if there is nothing pending*/ usb_class_mass_get_pending_request(intf_ptr,&cmd_ptr); if(cmd_ptr == NULL) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb,no matching request"); #endif return (USB_STATUS) USB_MASS_NO_MATCHING_REQUEST; } /* Endif */ /* BULK device mass storage reset */ request.BMREQUESTTYPE = REQ_TYPE_CLASS | REQ_TYPE_INTERFACE | REQ_TYPE_OUT; request.BREQUEST = MASS_STORAGE_RESET; *(uint_16*)request.WVALUE = HOST_TO_LE_SHORT_CONST(0); *(uint_16*)request.WINDEX = HOST_TO_LE_SHORT(((INTERFACE_DESCRIPTOR_PTR)intf_ptr->G.intf_handle)->bInterfaceNumber); *(uint_16*)request.WLENGTH = HOST_TO_LE_SHORT_CONST(0); cmd_ptr->STATUS = STATUS_RESET_DEVICE; status = _usb_hostdev_cntrl_request (intf_ptr->G.dev_handle, &request, NULL, usb_class_mass_reset_callback, (pointer)intf_ptr); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_recovery_on_usb,SUCCESSFUL"); #endif return USB_log_error(__FILE__,__LINE__,status); } /* Endbody */
static void usb_class_mass_reset_callback ( /* [IN] pointer to pipe */ _usb_pipe_handle pipe_handle, /* [IN] user-defined parameter */ pointer2 user_parm, /* [IN] buffer address */ uchar_ptr buffer, /* [IN] length of data transferred */ uint_32 length_data_transfered, /* [IN] status, hopefully USB_OK or USB_DONE */ uint_32 status ) { /* Body */ USB_MASS_CLASS_INTF_STRUCT_PTR plocal_intf; PIPE_INIT_PARAM_STRUCT_PTR pPipe; COMMAND_OBJECT_PTR cmd_ptr = NULL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_callback"); #endif if (user_parm) { /* Get the pointer to the pending request */ plocal_intf = (USB_MASS_CLASS_INTF_STRUCT_PTR)user_parm; usb_class_mass_get_pending_request(plocal_intf, &cmd_ptr); } /* Endif */ if (!cmd_ptr) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_callback, bad param"); #endif return; } /* Endif */ /* Check the status of the reset and act accordingly */ if (status == USB_OK || status == USB_STATUS_TRANSFER_QUEUED) { switch (cmd_ptr->STATUS) { case STATUS_RESET_DEVICE: /* Reset the Bulk IN pipe */ pPipe = (PIPE_INIT_PARAM_STRUCT_PTR)plocal_intf->BULK_IN_PIPE; if (!_usb_host_register_ch9_callback(plocal_intf->G.dev_handle, usb_class_mass_reset_callback, plocal_intf)) { status = _usb_host_ch9_clear_feature(plocal_intf->G.dev_handle, REQ_TYPE_ENDPOINT, (uint_8)(pPipe->ENDPOINT_NUMBER | REQ_TYPE_IN), ENDPOINT_HALT); cmd_ptr->STATUS = STATUS_RESET_BULK_IN; } /* Endif */ break; case STATUS_RESET_BULK_IN: /* Reset the Bulk OUT pipe*/ pPipe = (PIPE_INIT_PARAM_STRUCT_PTR)plocal_intf->BULK_OUT_PIPE; if (!_usb_host_register_ch9_callback(plocal_intf->G.dev_handle, usb_class_mass_reset_callback, plocal_intf)) { status = _usb_host_ch9_clear_feature(plocal_intf->G.dev_handle, REQ_TYPE_ENDPOINT, (uint_8)(pPipe->ENDPOINT_NUMBER | REQ_TYPE_OUT), ENDPOINT_HALT); cmd_ptr->STATUS = STATUS_RESET_BULK_OUT; } /* Endif */ break; case STATUS_RESET_BULK_OUT: case STATUS_CLEAR_BULK_PIPE: cmd_ptr->STATUS = cmd_ptr->PREV_STATUS; /* restore status */ status = usb_class_mass_pass_on_usb(plocal_intf); break; default: status = usb_class_mass_reset_recovery_on_usb(plocal_intf); break; } /* Endswitch */ } else if (status == USBERR_ENDPOINT_STALLED) { cmd_ptr->STATUS = STATUS_CANCELLED; cmd_ptr->CALLBACK(status, plocal_intf, cmd_ptr, cmd_ptr->TR_BUF_LEN); usb_class_mass_deleteq(plocal_intf); /* go to the next packet if any */ usb_class_mass_pass_on_usb(plocal_intf); } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_reset_callback, SUCCESSFUL"); #endif } /* Endbody */
USB_STATUS usb_class_mass_pass_on_usb ( /* [IN] Interface handle */ USB_MASS_CLASS_INTF_STRUCT_PTR intf_ptr ) { /* Body */ COMMAND_OBJECT_PTR cmd_ptr = NULL; TR_INIT_PARAM_STRUCT tr_init; USB_STATUS status = USB_OK; uint_8 tmp; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_pass_on_usb"); #endif /* Nothing can be done if there is nothing pending */ usb_class_mass_get_pending_request(intf_ptr, &cmd_ptr); if (cmd_ptr == NULL) { USB_unlock(); #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_pass_on_usb, no matching request"); #endif return (USB_STATUS)USB_MASS_NO_MATCHING_REQUEST; } /* Endif */ /* Determine the appropriate action based on the phase */ switch (cmd_ptr->STATUS) { case STATUS_QUEUED_IN_DRIVER: /* means that CBW needs to be sent.*/ usb_hostdev_tr_init(&tr_init, usb_class_mass_call_back_cbw, (pointer2)intf_ptr); tr_init.TX_BUFFER = (uchar_ptr)cmd_ptr->CBW_PTR; tr_init.TX_LENGTH = sizeof(CBW_STRUCT); status = _usb_host_send_data(intf_ptr->G.host_handle, intf_ptr->BULK_OUT_PIPE, &tr_init); break; case STATUS_FINISHED_CBW_ON_USB: /* Determine next phase (DATA or STATUS), length and direction */ if (utoh32(cmd_ptr->CBW_PTR->DCBWDATATRANSFERLENGTH) > 0) { /* Commen TR setup for IN or OUT direction */ usb_hostdev_tr_init(&tr_init,usb_class_mass_call_back_dphase, (pointer2)intf_ptr); tmp = (uint_8)((cmd_ptr->CBW_PTR->BMCBWFLAGS) & MASK_NON_DIRECTION_BITS); switch(tmp) { case DIRECTION_OUT: /* Make a TR with DATA Phase call back.*/ tr_init.TX_BUFFER = (uchar_ptr)cmd_ptr->DATA_BUFFER; tr_init.TX_LENGTH = cmd_ptr->BUFFER_LEN; status = _usb_host_send_data(intf_ptr->G.host_handle, intf_ptr->BULK_OUT_PIPE, &tr_init); break; case DIRECTION_IN: /* Make a TR with DATA call back.*/ tr_init.RX_BUFFER = (uchar_ptr)cmd_ptr->DATA_BUFFER; tr_init.RX_LENGTH = cmd_ptr->BUFFER_LEN; status = _usb_host_recv_data(intf_ptr->G.host_handle, intf_ptr->BULK_IN_PIPE, &tr_init); break; default: break; } /* Endswitch */ break; } /* Endif */ /* ** else case: ** No data transfer is expected of the request. Fall through to ** STATUS phase */ case STATUS_FINISHED_DPHASE_ON_USB: /* Make a TR and send it with STATUS call back */ usb_hostdev_tr_init(&tr_init,usb_class_mass_call_back_csw, (pointer2)intf_ptr); tr_init.RX_BUFFER = (uchar_ptr)cmd_ptr->CSW_PTR; tr_init.RX_LENGTH = sizeof(CSW_STRUCT); status = _usb_host_recv_data(intf_ptr->G.host_handle, intf_ptr->BULK_IN_PIPE, &tr_init); break; case STATUS_FINISHED_CSW_ON_USB: /* No action */ case STATUS_FAILED_IN_CSW: /* Should never happen */ default: break; } /* Endswitch */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_pass_on_usb, SUCCESSFUL"); #endif return status; } /* Endbody */
void usb_class_mass_call_back_csw ( /* [IN] Pipe on which CBW call was made */ _usb_pipe_handle pipe_handle, /* [IN] Pointer to the class instance */ pointer2 user_parm, /* [IN] Pointer to data buffer */ uchar_ptr buffer, /* [IN] Length of data transfered */ uint_32 length_data_transfered, /* [IN] Status of the transfer */ uint_32 status ) { /* Body */ USB_MASS_CLASS_INTF_STRUCT_PTR plocal_intf = NULL; COMMAND_OBJECT_PTR cmd_ptr = NULL; CSW_STRUCT_PTR pCsw = NULL; uint_32 tmp1, tmp2, tmp3; boolean proc_next = FALSE; USB_STATUS return_code; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_csw"); #endif if (user_parm) { /* Get the pointer to the pending request */ plocal_intf = (USB_MASS_CLASS_INTF_STRUCT_PTR) user_parm; usb_class_mass_get_pending_request(plocal_intf, &cmd_ptr); } /* Endif */ if (!cmd_ptr) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_csw, bad param"); #endif return; } /* Endif */ /* Finish transaction and queue next command */ if (status == USB_OK) { pCsw = (CSW_STRUCT_PTR) cmd_ptr->CSW_PTR; tmp1 = utoh32(pCsw->DCSWTAG); tmp2 = utoh32(cmd_ptr->CBW_PTR->DCBWTAG); tmp3 = utoh32(pCsw->DCSWSIGNATURE); /* Size must be verified, as well as the signature and the tags */ if ((length_data_transfered != sizeof(CSW_STRUCT)) || (tmp3 != CSW_SIGNATURE) || (tmp1 != tmp2)) { if (cmd_ptr->RETRY_COUNT < MAX_RETRIAL_ATTEMPTS) { cmd_ptr->RETRY_COUNT++; cmd_ptr->STATUS = STATUS_FINISHED_DPHASE_ON_USB; cmd_ptr->PREV_STATUS = cmd_ptr->STATUS; /* preserve the status */ status = usb_class_mass_reset_recovery_on_usb(plocal_intf); } else { status = STATUS_CANCELLED; /* cannot keep repeating */ } /* Endif */ if ((status != USB_OK) && (status != USBERR_TRANSFER_IN_PROGRESS) && (status != USB_STATUS_TRANSFER_QUEUED)) { proc_next = TRUE; } /* Endif */ } else { /* Check value of status field in CSW */ switch (pCsw->BCSWSTATUS) { case CSW_STATUS_GOOD: /* Command succeed. Notify application and cleanup */ cmd_ptr->STATUS = STATUS_COMPLETED; proc_next = TRUE; break; case CSW_STATUS_FAILED: /* Command failed. Notify application and cleanup */ cmd_ptr->STATUS = STATUS_FAILED_IN_CSW; proc_next = TRUE; break; default: break; } /* Endswitch */ } /* Endif */ } else if (status == USBERR_ENDPOINT_STALLED) { if (cmd_ptr->RETRY_COUNT < MAX_RETRIAL_ATTEMPTS) { cmd_ptr->RETRY_COUNT++; cmd_ptr->STATUS = STATUS_FINISHED_DPHASE_ON_USB; cmd_ptr->PREV_STATUS = cmd_ptr->STATUS; /* preserve the status */ return_code = usb_class_mass_clear_bulk_pipe_on_usb(plocal_intf); if (return_code != USB_OK && return_code != USB_STATUS_TRANSFER_QUEUED) { status = USBERR_TRANSFER_IN_PROGRESS; } } else { status = STATUS_CANCELLED; /* cannot keep repeating */ } /* Endif */ if ((status != USB_OK) && (status != USBERR_TRANSFER_IN_PROGRESS)) { /* Command didn't succeed. Notify application and cleanup */ cmd_ptr->STATUS = STATUS_CANCELLED; proc_next = TRUE; } /* Endbody */ } else { /* Command didn't succeed. Notify application and cleanup */ cmd_ptr->STATUS = STATUS_CANCELLED; proc_next = TRUE; } /* Endif */ /* Should we cleanup and process the next command? */ if (proc_next) { cmd_ptr->CALLBACK(status, plocal_intf, cmd_ptr, cmd_ptr->TR_BUF_LEN); usb_class_mass_deleteq(plocal_intf); /* Send next command, if any */ if (!USB_CLASS_MASS_IS_Q_EMPTY(plocal_intf)) { status = usb_class_mass_pass_on_usb( plocal_intf); } /* Endbody */ } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_csw, SUCCESSFUL"); #endif } /* Endbody */
void usb_class_mass_call_back_dphase ( /* [IN] Pipe on which CBW call was made */ _usb_pipe_handle pipe_handle, /* [IN] Pointer to the class instance */ pointer2 user_parm, /* [IN] Pointer to data buffer */ uchar_ptr buffer, /* [IN] Length of data transfered */ uint_32 length_data_transfered, /* [IN] Status of the transfer */ uint_32 status ) { /* Body */ USB_MASS_CLASS_INTF_STRUCT_PTR plocal_intf; COMMAND_OBJECT_PTR cmd_ptr = NULL; USB_STATUS return_code; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_dphase"); #endif if (user_parm) { /* Get the pointer to the pending request */ plocal_intf = (USB_MASS_CLASS_INTF_STRUCT_PTR) user_parm; usb_class_mass_get_pending_request(plocal_intf, &cmd_ptr); } /* Endif */ if (!cmd_ptr) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_dphase, bad parameter"); #endif return; } /* Endif */ /* Save length transferred during data phase */ cmd_ptr->TR_BUF_LEN = length_data_transfered; /* Test if full or partial data received */ if (status == USB_OK || status == USB_STATUS_TRANSFER_QUEUED || ((status == USBERR_TR_FAILED) && (buffer != NULL))) { /* Everything is OK, update status and go to next phase */ cmd_ptr->STATUS = STATUS_FINISHED_DPHASE_ON_USB; status = usb_class_mass_pass_on_usb(plocal_intf); } else if (status == USBERR_ENDPOINT_STALLED) { if (cmd_ptr->RETRY_COUNT < MAX_RETRIAL_ATTEMPTS) { cmd_ptr->RETRY_COUNT++; cmd_ptr->STATUS = STATUS_QUEUED_IN_DRIVER; cmd_ptr->PREV_STATUS = cmd_ptr->STATUS; /* preserve the status */ return_code = usb_class_mass_clear_bulk_pipe_on_usb(plocal_intf); if (return_code != USB_OK && return_code != USB_STATUS_TRANSFER_QUEUED) { status = STATUS_CANCELLED; } } else { cmd_ptr->STATUS = STATUS_FINISHED_DPHASE_ON_USB; cmd_ptr->PREV_STATUS = cmd_ptr->STATUS; /* preserve the status */ return_code = usb_class_mass_clear_bulk_pipe_on_usb(plocal_intf); if (return_code != USB_OK && return_code != USB_STATUS_TRANSFER_QUEUED) { status = STATUS_CANCELLED; } } /* Endif */ } /* Endif */ if ((status != USB_OK) && (status != USBERR_ENDPOINT_STALLED) && (status != USBERR_TRANSFER_IN_PROGRESS) && (status != USB_STATUS_TRANSFER_QUEUED)) { /* Command didn't succeed. Notify application and cleanup */ cmd_ptr->STATUS =STATUS_CANCELLED; cmd_ptr->CALLBACK((USB_STATUS)USB_MASS_FAILED_IN_DATA, plocal_intf, cmd_ptr, cmd_ptr->TR_BUF_LEN); usb_class_mass_deleteq(plocal_intf); /* Go to the next command, if any */ status = usb_class_mass_pass_on_usb(plocal_intf); } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_dphase, SUCCESSFUL"); #endif } /* Endbody */
void usb_class_mass_call_back_cbw ( /* [IN] Pipe on which CBW call was made */ _usb_pipe_handle pipe_handle, /* [IN] Pointer to the class instance */ pointer2 user_parm, /* [IN] Pointer to data buffer */ uchar_ptr buffer, /* [IN] Length of data transfered */ uint_32 length_data_transfered, /* [IN] Status of the transfer */ uint_32 status ) { /* Body */ USB_MASS_CLASS_INTF_STRUCT_PTR plocal_intf; COMMAND_OBJECT_PTR cmd_ptr = NULL; #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_cbw"); #endif if (user_parm) { /* Get the pointer to the pending request */ plocal_intf = (USB_MASS_CLASS_INTF_STRUCT_PTR)user_parm; usb_class_mass_get_pending_request(plocal_intf, &cmd_ptr); } /* Endif */ /* If there is no user_parm or cmd_ptr we return */ if (!cmd_ptr) { #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_cbw, bad parameter"); #endif return; } /* Endif */ /* Check status of CBW phase and go to the next phase (Data or Status) */ if (status == USB_OK || status == USB_STATUS_TRANSFER_QUEUED) { /* Verify if the length of the data transferred was correct */ if (length_data_transfered != CBW_SIZE) { if (cmd_ptr->RETRY_COUNT < MAX_RETRIAL_ATTEMPTS) { cmd_ptr->RETRY_COUNT++; cmd_ptr->STATUS = STATUS_QUEUED_IN_DRIVER; cmd_ptr->PREV_STATUS = cmd_ptr->STATUS; /* preserve the status */ status = usb_class_mass_reset_recovery_on_usb(plocal_intf); } else { status = STATUS_CANCELLED; /* cannot keep repeating */ } /* Endif */ } else { /* Everything is normal, go to next phase of pending request */ cmd_ptr->STATUS = STATUS_FINISHED_CBW_ON_USB; status = usb_class_mass_pass_on_usb(plocal_intf); } /* Endif */ } /* Endif */ if ((status != USB_OK) && (status != USBERR_TRANSFER_IN_PROGRESS) && (status != USB_STATUS_TRANSFER_QUEUED)) { /* ** Host must do a reset recovery for the device as per the spec. We also ** notify the application of the failure, remove the command from the ** queue and move on the the next command queued */ cmd_ptr->STATUS = STATUS_CANCELLED; cmd_ptr->CALLBACK((USB_STATUS)USB_MASS_FAILED_IN_COMMAND, plocal_intf, cmd_ptr, cmd_ptr->TR_BUF_LEN); usb_class_mass_deleteq(plocal_intf); status = usb_class_mass_pass_on_usb(plocal_intf); } /* Endif */ #ifdef _HOST_DEBUG_ DEBUG_LOG_TRACE("usb_class_mass_call_back_cbw, SUCCESSFUL"); #endif } /* Endbody */