//----------------------------------------------------------------------------- /// Return halted status /// \return stallCASE bitmap, case of the stall condition /// (bit: MSDD_CASE_STALL_OUT or MSDD_CASE_STALL_IN) //----------------------------------------------------------------------------- unsigned int MSDD_IsHalted(void) { unsigned int stallCASE = 0; if (USBD_IsHalted(MSDDriverDescriptors_BULKOUT)) { stallCASE |= MSDD_CASE_STALL_OUT; } if (USBD_IsHalted(MSDDriverDescriptors_BULKIN)) { stallCASE |= MSDD_CASE_STALL_IN; } return stallCASE; }
//------------------------------------------------------------------------------ /// Sends the current status of an endpoints to the USB host. /// \param bEndpoint Endpoint number. //------------------------------------------------------------------------------ static void GetEndpointStatus(unsigned char bEndpoint) { unsigned short data = 0; // Check if the endpoint exists if (bEndpoint > BOARD_USB_NUMENDPOINTS) { USBD_Stall(0); } else { // Check if the endpoint if currently halted if (USBD_IsHalted(bEndpoint)) { data = 1; } // Send the endpoint status USBD_Write(0, &data, 2, 0, 0); } }
/** * Handles HID-specific SETUP request sent by the host. * \param request Pointer to a USBGenericRequest instance */ void HIDDTransferDriver_RequestHandler(const USBGenericRequest *request) { HIDDTransferDriver *pDrv = &hiddTransferDriver; HIDDFunction *pHidd = &pDrv->hidFunction; TRACE_INFO("NewReq "); /* Check if this is a standard request */ if (USBGenericRequest_GetType(request) == USBGenericRequest_STANDARD) { /* This is a standard request */ switch (USBGenericRequest_GetRequest(request)) { case USBGenericRequest_GETDESCRIPTOR: /* Check if this is a HID descriptor, otherwise forward it to the standard driver */ if (!HIDDTransferDriver_GetDescriptor( USBGetDescriptorRequest_GetDescriptorType(request), USBGenericRequest_GetLength(request))) { USBDDriver_RequestHandler(pHidd->pUsbd, request); } return; /* Handled, no need to do others */ case USBGenericRequest_CLEARFEATURE: /* Check which is the requested feature */ switch (USBFeatureRequest_GetFeatureSelector(request)) { case USBFeatureRequest_ENDPOINTHALT: { uint8_t ep = USBGenericRequest_GetEndpointNumber(request); if (USBD_IsHalted(ep)) { /* Unhalt endpoint restart OUT EP */ USBD_Unhalt(ep); if (ep == pHidd->bPipeOUT) { HIDDFunction_StartPollingOutputs(pHidd); } } /* and send a zero-length packet */ USBD_Write(0, 0, 0, 0, 0); return; /* Handled, no need to do others */ } } break; } } /* We use different buffer for SetReport */ else if (USBGenericRequest_GetType(request) == USBGenericRequest_CLASS) { switch (USBGenericRequest_GetRequest(request)) { case HIDGenericRequest_SETREPORT: { uint16_t length = USBGenericRequest_GetLength(request); uint8_t type = HIDReportRequest_GetReportType(request); if (type == HIDReportRequest_OUTPUT) { if (length > HIDDTransferDriver_REPORTSIZE) length = HIDDTransferDriver_REPORTSIZE; USBD_Read(0, pDrv->iReportBuf, length, HIDDTransferDriver_ReportReceived, 0); /* No argument to the callback function */ } else { USBD_Stall(0); } } return; /* Handled, no need do others */ } } /* Process HID requests */ if (USBRC_SUCCESS == HIDDFunction_RequestHandler(pHidd, request)) { return; } else USBDDriver_RequestHandler(pHidd->pUsbd, request); }
/** * State machine for the MSD %device driver * \param pMsdDriver Pointer to a MSDDriver instance */ void MSDD_StateMachine(MSDDriver * pMsdDriver) { MSDCommandState *commandState = &(pMsdDriver->commandState); MSCbw *cbw = &(commandState->cbw); MSCsw *csw = &(commandState->csw); MSDTransfer *transfer = &(commandState->transfer); unsigned char status; /* Identify current driver state */ switch (pMsdDriver->state) { /*---------------------- */ case MSDD_STATE_READ_CBW: /*---------------------- */ /* Start the CBW read operation */ transfer->semaphore = 0; #if 1 status = USBD_Read(commandState->pipeOUT, cbw, MSD_CBW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #else status = MSDD_Read(cbw, MSD_CBW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #endif /* Check operation result code */ if (status == USBD_STATUS_SUCCESS) { /* If the command was successful, wait for transfer */ pMsdDriver->state = MSDD_STATE_WAIT_CBW; } break; /*---------------------- */ case MSDD_STATE_WAIT_CBW: /*---------------------- */ /* Check transfer semaphore */ if (transfer->semaphore > 0) { /* Take semaphore and terminate transfer */ transfer->semaphore--; /* Check if transfer was successful */ if (transfer->status == USBD_STATUS_SUCCESS) { TRACE_INFO_WP("\n\r------------------------------\n\r"); /* Process received command */ pMsdDriver->state = MSDD_STATE_PROCESS_CBW; } else if (transfer->status == USBD_STATUS_RESET) { TRACE_INFO("MSDD_StateMachine: EP resetted\n\r"); pMsdDriver->state = MSDD_STATE_READ_CBW; } else { TRACE_WARNING( "MSDD_StateMachine: Failed to read CBW\n\r"); pMsdDriver->state = MSDD_STATE_READ_CBW; } } break; /*------------------------- */ case MSDD_STATE_PROCESS_CBW: /*------------------------- */ /* Check if this is a new command */ if (commandState->state == 0) { /* Copy the CBW tag */ csw->dCSWTag = cbw->dCBWTag; /* Check that the CBW is 31 bytes long */ if ((transfer->transferred != MSD_CBW_SIZE) || (transfer->remaining != 0)) { TRACE_WARNING( "MSDD_StateMachine: Invalid CBW (len %d)\n\r", (int)transfer->transferred); /* Wait for a reset recovery */ pMsdDriver->waitResetRecovery = 1; /* Halt the Bulk-IN and Bulk-OUT pipes */ //MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN); USBD_Halt(commandState->pipeIN); USBD_Halt(commandState->pipeOUT); csw->bCSWStatus = MSD_CSW_COMMAND_FAILED; pMsdDriver->state = MSDD_STATE_READ_CBW; } /* Check the CBW Signature */ else if (cbw->dCBWSignature != MSD_CBW_SIGNATURE) { TRACE_WARNING( "MSD_BOTStateMachine: Invalid CBW (Bad signature)\n\r"); /* Wait for a reset recovery */ pMsdDriver->waitResetRecovery = 1; /* Halt the Bulk-IN and Bulk-OUT pipes */ //MSDD_Halt(MSDD_CASE_STALL_OUT | MSDD_CASE_STALL_IN); USBD_Halt(commandState->pipeIN); USBD_Halt(commandState->pipeOUT); csw->bCSWStatus = MSD_CSW_COMMAND_FAILED; pMsdDriver->state = MSDD_STATE_READ_CBW; } else { /* Pre-process command */ MSDD_PreProcessCommand(pMsdDriver); } } /* Process command */ if (csw->bCSWStatus == MSDD_STATUS_SUCCESS) { if (MSDD_ProcessCommand(pMsdDriver)) { /* Post-process command if it is finished */ if (MSDD_PostProcessCommand(pMsdDriver)) { TRACE_INFO_WP("WaitHALT "); pMsdDriver->state = MSDD_STATE_WAIT_HALT; } else { pMsdDriver->state = MSDD_STATE_SEND_CSW; } } TRACE_INFO_WP("\n\r"); } break; /*---------------------- */ case MSDD_STATE_SEND_CSW: /*---------------------- */ /* Set signature */ csw->dCSWSignature = MSD_CSW_SIGNATURE; /* Start the CSW write operation */ #if 1 status = USBD_Write(commandState->pipeIN, csw, MSD_CSW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #else status = MSDD_Write(csw, MSD_CSW_SIZE, (TransferCallback) MSDDriver_Callback, (void *) transfer); #endif /* Check operation result code */ if (status == USBD_STATUS_SUCCESS) { TRACE_INFO_WP("SendCSW "); /* Wait for end of transfer */ pMsdDriver->state = MSDD_STATE_WAIT_CSW; } break; /*---------------------- */ case MSDD_STATE_WAIT_CSW: /*---------------------- */ /* Check transfer semaphore */ if (transfer->semaphore > 0) { /* Take semaphore and terminate transfer */ transfer->semaphore--; /* Check if transfer was successful */ if (transfer->status == USBD_STATUS_RESET) { TRACE_INFO("MSDD_StateMachine: EP resetted\n\r"); } else if (transfer->status == USBD_STATUS_ABORTED) { TRACE_WARNING( "MSDD_StateMachine: Failed to send CSW\n\r"); } else { TRACE_INFO_WP("ok"); } /* Read new CBW */ pMsdDriver->state = MSDD_STATE_READ_CBW; } break; /*---------------------- */ case MSDD_STATE_WAIT_HALT: /*---------------------- */ //if (MSDD_IsHalted() == 0) { if (!USBD_IsHalted(commandState->pipeIN)) { pMsdDriver->state = MSDD_STATE_SEND_CSW; } break; } }