From f7cd9b461ca33845339f4a11f49bdc142696827a Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Tue, 28 Jun 2016 09:51:29 +0200 Subject: Apalis_TK1_K20: SPI Communication, ADC, TSC, GPIO Support for Communication between TK1 SoC and K20 MCU This patch includes ADC, TSC and GPIO functionality. Signed-off-by: Dominik Sliwa --- usb_1.1.0/host/class/usb_host_msd.c | 1155 +++++++++++++++++++++++++++++++++++ 1 file changed, 1155 insertions(+) create mode 100644 usb_1.1.0/host/class/usb_host_msd.c (limited to 'usb_1.1.0/host/class/usb_host_msd.c') diff --git a/usb_1.1.0/host/class/usb_host_msd.c b/usb_1.1.0/host/class/usb_host_msd.c new file mode 100644 index 0000000..ecb9706 --- /dev/null +++ b/usb_1.1.0/host/class/usb_host_msd.c @@ -0,0 +1,1155 @@ +/* + * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * o Redistributions of source code must retain the above copyright notice, this list + * of conditions and the following disclaimer. + * + * o Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * o Neither the name of Freescale Semiconductor, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "usb_host_config.h" +#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD)) +#include "usb_host.h" +#include "usb_host_msd.h" +#include "usb_host_hci.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief clear stall transfer callback. + * + * @param param callback parameter. + * @param transfer transfer. + * @param status transfer result status. + */ +static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief send clear stall transfer. + * + * @param msdInstance msd instance pointer. + * @param callbackFn callback function. + * @param endpoint endpoint address. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t callbackFn, + uint8_t endpoint); + +/*! + * @brief mass storage reset three step processes are done. + * + * @param msdInstance msd instance pointer. + * @param status result status. + */ +static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status); + +/*! + * @brief mass storage reset process step 3 callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage reset process step 2 callback. + * + * @param msdInstance msd instance pointer. + * @transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage reset process step 1 callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief mass storage control transfer callback function. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief this function is called when ufi command is done. + * + * @param msdInstance msd instance pointer. + */ +static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status); + +/*! + * @brief csw transfer callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief cbw transfer callback. + * + * @param msdInstance msd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief data transfer callback. + * + * @param msdInstance sd instance pointer. + * @param transfer transfer + * @param status result status. + */ +static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief msd open interface. + * + * @param msdInstance msd instance pointer. + * + * @return kStatus_USB_Success or error codes. + */ +static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance); + +/*! + * @brief msd set interface callback, open pipes. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief msd control transfer common code. + * + * This function allocate the resource for msd instance. + * + * @param msdInstance the msd class instance. + * @param pipeCallbackFn inner callback function. + * @param callbackFn callback function. + * @param callbackParam callback parameter. + * @param buffer buffer pointer. + * @param bufferLength buffer length. + * @param requestType request type. + * @param requestValue request value. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t pipeCallbackFn, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t *buffer, + uint16_t bufferLength, + uint8_t requestType, + uint8_t requestValue); + +/*! + * @brief command process function, this function is called many time for one command's different state. + * + * @param msdInstance the msd class instance. + * + * @return An error code or kStatus_USB_Success. + */ +static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/******************************************************************************* + * Code + ******************************************************************************/ + +static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_TransferCancel); + } + + if (msdInstance->commandStatus == kMSD_CommandErrorDone) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */ + } + else + { + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } +} + +static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t callbackFn, + uint8_t endpoint) +{ + usb_status_t status; + usb_host_transfer_t *transfer; + + /* malloc one transfer */ + status = USB_HostMallocTransfer(msdInstance->hostHandle, &transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return status; + } + /* save the application callback function */ + msdInstance->controlCallbackFn = NULL; + msdInstance->controlCallbackParam = NULL; + /* initialize transfer */ + transfer->callbackFn = callbackFn; + transfer->callbackParam = msdInstance; + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_CLEAR_FEATURE; + transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; + transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT); + transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(endpoint); + transfer->setupPacket.wLength = 0; + status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer); + + if (status != kStatus_USB_Success) + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + } + msdInstance->controlTransfer = transfer; + + return status; +} + +static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status) +{ + if (msdInstance->internalResetRecovery == 1) /* internal mass reset recovery */ + { + msdInstance->internalResetRecovery = 0; + + if ((status != kStatus_USB_Success) || (msdInstance->commandStatus == kMSD_CommandErrorDone)) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */ + } + else + { + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + } + else /* user call mass storage reset recovery */ + { + if (msdInstance->controlCallbackFn != NULL) + { + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0, + status); /* callback to application */ + } + } +} + +static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ +} + +static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + + if (status == kStatus_USB_Success) + { + if (msdInstance->outPipe != NULL) + { + /* continue to process mass storage reset */ + USB_HostMsdClearHalt( + msdInstance, USB_HostMsdMassResetClearOutCallback, + (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->outPipe)->endpointAddress)); + } + } + else + { + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ + } +} + +static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + if (status == kStatus_USB_Success) + { + if (msdInstance->inPipe != NULL) + { + /* continue to process mass storage reset */ + USB_HostMsdClearHalt(msdInstance, USB_HostMsdMassResetClearInCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)); + } + } + else + { + USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */ + } +} + +static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + if (msdInstance->controlCallbackFn != NULL) + { + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, transfer->transferBuffer, + transfer->transferSofar, status); /* callback to application */ + } + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); +} + +static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status) +{ + if (msdInstance->commandCallbackFn != NULL) + { + /* callback to application */ + msdInstance->commandCallbackFn(msdInstance->commandCallbackParam, msdInstance->msdCommand.dataBuffer, + msdInstance->msdCommand.dataSofar, status); + } + msdInstance->commandStatus = kMSD_CommandIdle; +} + +static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + if ((transfer->transferSofar == 13) && + (msdInstance->msdCommand.cswBlock.CSWSignature == USB_HOST_MSD_CSW_SIGNATURE)) + { + switch (msdInstance->msdCommand.cswBlock.CSWStatus) + { + case 0: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success); + break; + + case 1: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail); + break; + + case 2: + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + break; + + default: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail); + break; + } + } + else + { + /* mass reset recovery to end ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt( + msdInstance, USB_HostMsdClearHaltCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + } +} + +static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + if (transfer->transferSofar == USB_HOST_UFI_CBW_LENGTH) + { + msdInstance->commandStatus = kMSD_CommandTransferData; + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + else + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (msdInstance->msdCommand.retryTime > 0) + { + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt( + msdInstance, USB_HostMsdClearHaltCallback, + (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; + } + if (msdInstance->msdCommand.retryTime > 0) + { + USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */ + } + else + { + /* mass reset recovery to continue ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } + return; + } +} + +static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + uint8_t direction; + + if (status == kStatus_USB_Success) + { + /* kStatus_USB_Success */ + msdInstance->msdCommand.dataSofar += transfer->transferSofar; + USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */ + } + else + { + if (status == kStatus_USB_TransferStall) /* case 1: stall */ + { + if (msdInstance->msdCommand.retryTime > 0) + { + msdInstance->msdCommand.retryTime--; /* retry reduce when error */ + } + if (transfer->direction == USB_IN) + { + direction = USB_REQUEST_TYPE_DIR_IN; + } + else + { + direction = USB_REQUEST_TYPE_DIR_OUT; + } + + if (msdInstance->msdCommand.retryTime == 0) + { + msdInstance->commandStatus = kMSD_CommandTransferCSW; /* next step */ + } + /* clear stall to continue the ufi command */ + if (USB_HostMsdClearHalt(msdInstance, USB_HostMsdClearHaltCallback, + (direction | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) != + kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */ + { + USB_HostMsdCommandDone(msdInstance, status); /* command cancel */ + } + else /* case 3: error */ + { + /* mass reset recovery to finish ufi command */ + msdInstance->internalResetRecovery = 1; + msdInstance->commandStatus = kMSD_CommandErrorDone; + if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success) + { + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); + } + } + } +} + +static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance) +{ + usb_status_t status = kStatus_USB_Success; + usb_host_transfer_t *transfer; + + if (msdInstance->msdCommand.transfer == NULL) + { + /* malloc one transfer */ + status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer)); + if (status != kStatus_USB_Success) + { + msdInstance->msdCommand.transfer = NULL; +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return kStatus_USB_Busy; + } + } + transfer = msdInstance->msdCommand.transfer; + switch (msdInstance->commandStatus) + { + case kMSD_CommandTransferCBW: /* ufi CBW phase */ + transfer->direction = USB_OUT; + transfer->transferBuffer = (uint8_t *)(&(msdInstance->msdCommand.cbwBlock)); + transfer->transferLength = USB_HOST_UFI_CBW_LENGTH; + transfer->callbackFn = USB_HostMsdCbwCallback; + transfer->callbackParam = msdInstance; + status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host send error\r\n"); +#endif + } + break; + + case kMSD_CommandTransferData: /* ufi DATA phase */ + if (msdInstance->msdCommand.dataBuffer != NULL) + { + transfer->direction = msdInstance->msdCommand.dataDirection; + transfer->transferBuffer = (msdInstance->msdCommand.dataBuffer + msdInstance->msdCommand.dataSofar); + transfer->transferLength = (msdInstance->msdCommand.dataLength - msdInstance->msdCommand.dataSofar); + transfer->callbackParam = msdInstance; + if (msdInstance->msdCommand.dataSofar != msdInstance->msdCommand.dataLength) + { + if (transfer->direction == USB_OUT) + { + transfer->callbackFn = USB_HostMsdDataCallback; + status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host send error\r\n"); +#endif + } + } + else + { + transfer->callbackFn = USB_HostMsdDataCallback; + status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host recv error\r\n"); +#endif + } + } + break; + } + else + { + /* don't break */ + } + } + else + { + /* don't break */ + } + case kMSD_CommandTransferCSW: /* ufi CSW phase */ + transfer->direction = USB_IN; + transfer->transferBuffer = (uint8_t *)&msdInstance->msdCommand.cswBlock; + transfer->transferLength = sizeof(usb_host_csw_t); + transfer->callbackFn = USB_HostMsdCswCallback; + transfer->callbackParam = msdInstance; + status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("host recv error\r\n"); +#endif + } + break; + + case kMSD_CommandDone: + USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success); + break; + + default: + break; + } + return status; +} + +/*! + * @brief all ufi function calls this api. + * + * This function implements the common ufi commands. + * + * @param classHandle the class msd handle. + * @param buffer buffer pointer. + * @param bufferLength buffer length. + * @param callbackFn callback function. + * @param callbackParam callback parameter. + * @param direction command direction. + * @param byteValues ufi command fields value. + * + * @return An error code or kStatus_USB_Success. + */ +usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t direction, + uint8_t byteValues[10]) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_host_cbw_t *cbwPointer = &(msdInstance->msdCommand.cbwBlock); + uint8_t index = 0; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + if (msdInstance->commandStatus != kMSD_CommandIdle) + { + return kStatus_USB_Busy; + } + + /* save the application callback function */ + msdInstance->commandCallbackFn = callbackFn; + msdInstance->commandCallbackParam = callbackParam; + + /* initialize CBWCB fields */ + for (index = 0; index < USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; ++index) + { + cbwPointer->CBWCB[index] = byteValues[index]; + } + + /* initialize CBW fields */ + cbwPointer->CBWDataTransferLength = USB_LONG_TO_LITTLE_ENDIAN(bufferLength); + cbwPointer->CBWFlags = direction; + cbwPointer->CBWLun = (byteValues[1] >> USB_HOST_UFI_LOGICAL_UNIT_POSITION); + cbwPointer->CBWCBLength = USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; + + msdInstance->commandStatus = kMSD_CommandTransferCBW; + if (direction == USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN) + { + msdInstance->msdCommand.dataDirection = USB_IN; + } + else + { + msdInstance->msdCommand.dataDirection = USB_OUT; + } + msdInstance->msdCommand.dataBuffer = buffer; + + msdInstance->msdCommand.dataLength = bufferLength; + msdInstance->msdCommand.dataSofar = 0; + msdInstance->msdCommand.retryTime = USB_HOST_MSD_RETRY_MAX_TIME; + + return USB_HostMsdProcessCommand(msdInstance); /* start to process ufi command */ +} + +static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance) +{ + usb_status_t status; + uint8_t epIndex = 0; + usb_host_pipe_init_t pipeInit; + usb_descriptor_endpoint_t *epDesc = NULL; + usb_host_interface_t *interfacePointer; + + if (msdInstance->inPipe != NULL) /* close bulk in pipe if the pipe is open */ + { + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + msdInstance->inPipe = NULL; + } + if (msdInstance->outPipe != NULL) /* close bulk out pipe if the pipe is open */ + { + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + msdInstance->outPipe = NULL; + } + + /* open interface pipes */ + interfacePointer = (usb_host_interface_t *)msdInstance->interfaceHandle; + for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex) + { + epDesc = interfacePointer->epList[epIndex].epDesc; + if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == + USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && + ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK)) + { + pipeInit.devInstance = msdInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_IN; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + pipeInit.interval = epDesc->bInterval; + pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); + pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + + status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->inPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("usb_host_hid_set_interface fail to open pipe\r\n"); +#endif + return status; + } + } + else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == + USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) && + ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK)) + { + pipeInit.devInstance = msdInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_OUT; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + pipeInit.interval = epDesc->bInterval; + pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); + pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) & + USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); + pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; + + status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->outPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("usb_host_hid_set_interface fail to open pipe\r\n"); +#endif + return status; + } + } + else + { + } + } + + return kStatus_USB_Success; +} + +static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param; + + msdInstance->controlTransfer = NULL; + if (status == kStatus_USB_Success) + { + status = USB_HostMsdOpenInterface(msdInstance); /* msd open interface */ + } + + if (msdInstance->controlCallbackFn != NULL) + { + msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0, + status); /* callback to application */ + } + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); +} + +usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle) +{ + uint32_t infoValue; + usb_status_t status; + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)USB_OsaMemoryAllocate( + sizeof(usb_host_msd_instance_t)); /* malloc msd class instance */ + + if (msdInstance == NULL) + { + return kStatus_USB_AllocFail; + } + + /* initialize msd instance */ + msdInstance->deviceHandle = deviceHandle; + msdInstance->interfaceHandle = NULL; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue); + msdInstance->hostHandle = (usb_host_handle)infoValue; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue); + msdInstance->controlPipe = (usb_host_pipe_handle)infoValue; + + msdInstance->msdCommand.cbwBlock.CBWSignature = USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CBW_SIGNATURE); + status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer)); + if (status != kStatus_USB_Success) + { + msdInstance->msdCommand.transfer = NULL; +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + } + + *classHandle = msdInstance; + return kStatus_USB_Success; +} + +usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_status_t status = kStatus_USB_Error; + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + status = USB_HostOpenDeviceInterface(msdInstance->deviceHandle, + interfaceHandle); /* notify host driver the interface is open */ + if (status != kStatus_USB_Success) + { + return status; + } + msdInstance->interfaceHandle = interfaceHandle; + + /* cancel transfers */ + if (msdInstance->inPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when cancel pipe\r\n"); +#endif + } + } + if (msdInstance->outPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when cancel pipe\r\n"); +#endif + } + } + + if (alternateSetting == 0) /* open interface directly */ + { + if (callbackFn != NULL) + { + status = USB_HostMsdOpenInterface(msdInstance); + callbackFn(callbackParam, NULL, 0, status); + } + } + else /* send setup transfer */ + { + /* malloc one transfer */ + if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Busy; + } + /* save the application callback function */ + msdInstance->controlCallbackFn = callbackFn; + msdInstance->controlCallbackParam = callbackParam; + /* initialize transfer */ + transfer->callbackFn = USB_HostMsdSetInterfaceCallback; + transfer->callbackParam = msdInstance; + transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_INTERFACE; + transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN( + ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber); + transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting); + transfer->setupPacket.wLength = 0; + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer); + + if (status == kStatus_USB_Success) + { + msdInstance->controlTransfer = transfer; + } + else + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + } + } + + return status; +} + +usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + usb_status_t status; + + if (classHandle != NULL) + { + if (msdInstance->inPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); /* cancel pipe */ + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); /* close pipe */ + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + } + if (msdInstance->outPipe != NULL) + { + status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); /* cancel pipe */ + status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); /* close pipe */ + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error when close pipe\r\n"); +#endif + } + } + if ((msdInstance->controlPipe != NULL) && + (msdInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */ + { + status = + USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->controlPipe, msdInstance->controlTransfer); + } + if (msdInstance->msdCommand.transfer) + { + USB_HostFreeTransfer(msdInstance->hostHandle, msdInstance->msdCommand.transfer); + } + USB_HostCloseDeviceInterface(deviceHandle, + msdInstance->interfaceHandle); /* notify host driver the interface is closed */ + USB_OsaMemoryFree(msdInstance); + } + else + { + USB_HostCloseDeviceInterface(deviceHandle, NULL); + } + + return kStatus_USB_Success; +} + +static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance, + host_inner_transfer_callback_t pipeCallbackFn, + transfer_callback_t callbackFn, + void *callbackParam, + uint8_t *buffer, + uint16_t bufferLength, + uint8_t requestType, + uint8_t requestValue) +{ + usb_host_transfer_t *transfer; + + if (msdInstance == NULL) + { + return kStatus_USB_InvalidHandle; + } + + /* malloc one transfer */ + if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return kStatus_USB_Busy; + } + /* save the application callback function */ + msdInstance->controlCallbackFn = callbackFn; + msdInstance->controlCallbackParam = callbackParam; + /* initialize transfer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackFn = pipeCallbackFn; + transfer->callbackParam = msdInstance; + + transfer->setupPacket.bmRequestType = requestType; + transfer->setupPacket.bRequest = requestValue; + transfer->setupPacket.wValue = 0x0000; + transfer->setupPacket.wIndex = + ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber; + transfer->setupPacket.wLength = bufferLength; + + if (USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer) != + kStatus_USB_Success) /* call host driver api */ + { + USB_HostFreeTransfer(msdInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + msdInstance->controlTransfer = transfer; + + return kStatus_USB_Success; +} + +usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + + return USB_HostMsdControl(msdInstance, USB_HostMsdMassResetCallback, callbackFn, callbackParam, NULL, 0, + (USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE), + USB_HOST_HID_MASS_STORAGE_RESET); +} + +usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle, + uint8_t *logicalUnitNumber, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle; + + return USB_HostMsdControl( + msdInstance, USB_HostMsdControlCallback, callbackFn, callbackParam, logicalUnitNumber, 1, + (USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE), + USB_HOST_HID_GET_MAX_LUN); +} + +#endif /* USB_HOST_CONFIG_MSD */ -- cgit v1.2.3