예제 #1
0
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 */
예제 #2
0
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 */
예제 #3
0
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 */
예제 #4
0
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 */
예제 #5
0
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 */
예제 #6
0
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 */
예제 #7
0
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 */
예제 #8
0
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 */