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_phdc.c | 1272 ++++++++++++++++++++++++++++++++++ 1 file changed, 1272 insertions(+) create mode 100644 usb_1.1.0/host/class/usb_host_phdc.c (limited to 'usb_1.1.0/host/class/usb_host_phdc.c') diff --git a/usb_1.1.0/host/class/usb_host_phdc.c b/usb_1.1.0/host/class/usb_host_phdc.c new file mode 100644 index 0000000..e740487 --- /dev/null +++ b/usb_1.1.0/host/class/usb_host_phdc.c @@ -0,0 +1,1272 @@ +/* + * 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_PHDC) && (USB_HOST_CONFIG_PHDC)) +#include "usb_host.h" +#include "usb_host_phdc.h" + +/******************************************************************************* + * Definitions + ******************************************************************************/ + +/******************************************************************************* + * Prototypes + ******************************************************************************/ + +/*! + * @brief phdc control pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief phdc set and clear feature endpoint halt callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcSetClearFeatureEndpointHaltCallback(void *param, + usb_host_transfer_t *transfer, + usb_status_t status); + +/*! + * @brief phdc interrupt pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief phdc bulk in pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcBulkInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief phdc bulk out pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcBulkOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/*! + * @brief phdc set interface callback, open pipes. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status); + +/******************************************************************************* + * Variables + ******************************************************************************/ + +/*! @brief meta-data message preamble signature string */ +static char const metaDataMsgPreambleSignature[] = "PhdcQoSSignature"; + +/******************************************************************************* + * Code + ******************************************************************************/ + +#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) + +static void USB_HostPhdcClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + + phdcInstance->controlTransfer = NULL; + /* Reduces the number of bulk transfer to 0 to expect new message preamble transfer */ + phdcInstance->numberTransferBulkIn = 0U; + if (phdcInstance->inCallbackFn != NULL) + { + /* callback to application */ + phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, phdcInstance->stallDataBuffer, + phdcInstance->stallDataLength, kStatus_USB_TransferStall); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +static void USB_HostPhdcClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + + phdcInstance->controlTransfer = NULL; + if (phdcInstance->outCallbackFn != NULL) + { + /* callback to application */ + phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, phdcInstance->stallDataBuffer, + phdcInstance->stallDataLength, kStatus_USB_TransferStall); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +static usb_status_t USB_HostPhdcClearHalt(usb_host_phdc_instance_t *phdcInstance, + usb_host_transfer_t *stallTransfer, + host_inner_transfer_callback_t callbackFn, + uint8_t endpoint) +{ + usb_status_t status; + usb_host_transfer_t *transfer; + + /* malloc one transfer */ + status = USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("allocate transfer error\r\n"); +#endif + return status; + } + phdcInstance->stallDataBuffer = stallTransfer->transferBuffer; + phdcInstance->stallDataLength = stallTransfer->transferSofar; + /* save the application callback function */ + phdcInstance->controlCallbackFn = NULL; + phdcInstance->controlCallbackParam = NULL; + /* initialize transfer */ + transfer->callbackFn = callbackFn; + transfer->callbackParam = phdcInstance; + 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(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer); + + if (status != kStatus_USB_Success) + { + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + } + phdcInstance->controlTransfer = transfer; + + return status; +} + +#endif + +/*! + * @brief phdc control pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + phdcInstance->controlTransfer = NULL; + if (kStatus_USB_Success == status) + { + if (USB_HOST_PHDC_SET_FEATURE_REQUEST == transfer->setupPacket.bRequest) + { + /* Meta-data message preamble feature is enabled */ + phdcInstance->isMessagePreambleEnabled = 1U; + } + else if (USB_HOST_PHDC_CLEAR_FEATURE_REQUEST == transfer->setupPacket.bRequest) + { + /* Meta-data message preamble feature is disable */ + phdcInstance->isMessagePreambleEnabled = 0U; + } + else + { + } + } + if (NULL != phdcInstance->controlCallbackFn) + { + phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer, + transfer->transferSofar, status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief phdc set and clear feature endpoint halt callback for meta-data message preamble error. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcSetClearFeatureEndpointHaltCallback(void *param, + usb_host_transfer_t *transfer, + usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + phdcInstance->controlTransfer = NULL; + if (kStatus_USB_Success == status) + { + if ((transfer->setupPacket.bRequest == USB_REQUEST_STANDARD_SET_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(phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress))) + { + /* The host shall issue CLEAR_FEATURE ENDPOINT_HALT request to the device */ + usb_host_process_feature_param_t featureParam; + featureParam.requestType = kRequestEndpoint; + featureParam.featureSelector = USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT; + featureParam.interfaceOrEndpoint = phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress; + if (kStatus_USB_Success != USB_HostPhdcSetClearFeatureEndpointHalt(phdcInstance->hostHandle, + USB_REQUEST_STANDARD_CLEAR_FEATURE, + &featureParam, NULL, NULL)) + { +#ifdef HOST_ECHO + usb_echo("Error for USB_HostPhdcSetClearFeatureEndpointHalt\r\n"); +#endif + } + } + if ((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(phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress))) + { + /* Reduces the number of bulk transfer to 0 to expect new message preamble transfer */ + phdcInstance->numberTransferBulkIn = 0U; + } + } + if (NULL != phdcInstance->controlCallbackFn) + { + /* Notify to application the status of request */ + phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer, + transfer->transferSofar, status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief phdc interrupt pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + +#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) + if (status == kStatus_USB_TransferStall) + { + if (USB_HostPhdcClearHalt( + phdcInstance, transfer, USB_HostPhdcClearInHaltCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)phdcInstance->interruptPipe)->endpointAddress)) == + kStatus_USB_Success) + { + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return; + } + } +#endif + if (NULL != phdcInstance->inCallbackFn) + { + phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar, + status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief phdc bulk in pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcBulkInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + +#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) + if (status == kStatus_USB_TransferStall) + { + if (USB_HostPhdcClearHalt( + phdcInstance, transfer, USB_HostPhdcClearInHaltCallback, + (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)phdcInstance->bulkInPipe)->endpointAddress)) == + kStatus_USB_Success) + { + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return; + } + } +#endif + if (status == kStatus_USB_Success) + { + /* The meta-data message preamble is implemented and enabled */ + if (phdcInstance->isMessagePreambleEnabled == 1U) + { + /* The meta-data message preamble feature is enabled, then all data transfers or sets + of data transfers shall be preceded by a meta-data message preamble transfer. The + numberTransferBulkIn is initialized as zero for receiving this message preamble data, + then it is updated to the value of bNumTransfers field of message preamble data */ + if (phdcInstance->numberTransferBulkIn) + { + /* When numberTransferBulkIn reduces to 0, a new meta-data message preamble shall + be transferred */ + phdcInstance->numberTransferBulkIn--; + } + else + { + uint8_t preambleSignatureChecking = 1U; + /* The received packet is meta-data message preamble */ + usb_host_phdc_metadata_preamble_t *metaDataMsgPreamble = + (usb_host_phdc_metadata_preamble_t *)transfer->transferBuffer; + /* Meta-data message preamble signature checking */ + for (uint8_t i = 0U; i < USB_HOST_PHDC_MESSAGE_PREAMBLE_SIGNATURE_SIZE; i++) + { + if (*(transfer->transferBuffer + i) != metaDataMsgPreambleSignature[i]) + { + preambleSignatureChecking = 0U; + break; + } + } + if (preambleSignatureChecking) + { + /* Checks if the meta-data message preamble contains an invalid bmLatencyReliability value + or bNumTransfers value */ + if ((!(metaDataMsgPreamble->bNumberTransfers)) || /* bNumTransfers shall never equal zero */ + (metaDataMsgPreamble->bQosEncodingVersion != 0x01U) || /* Encoding version should be 0x01 */ + ((metaDataMsgPreamble->bmLatencyReliability != + 0x02U) && /* Medium.Good latency, reliability bin */ + (metaDataMsgPreamble->bmLatencyReliability != + 0x04U) && /* Medium.Better latency, reliability bin */ + (metaDataMsgPreamble->bmLatencyReliability != + 0x08U) && /* Medium.Best latency, reliability bin */ + (metaDataMsgPreamble->bmLatencyReliability != + 0x10U) && /* High.Best latency, reliability bin */ + (metaDataMsgPreamble->bmLatencyReliability != + 0x20U) /* VeryHigh.Best latency, reliability bin */)) + { + /* The host shall issue SET_FEATURE ENDPOINT_HALT request to the device */ + usb_host_process_feature_param_t featureParam; + featureParam.requestType = kRequestEndpoint; + featureParam.featureSelector = USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT; + featureParam.interfaceOrEndpoint = + phdcInstance->bulkInEndpointInformation.epDesc->bEndpointAddress; + if (kStatus_USB_Success != + USB_HostPhdcSetClearFeatureEndpointHalt( + phdcInstance->hostHandle, USB_REQUEST_STANDARD_SET_FEATURE, &featureParam, NULL, NULL)) + { +#ifdef HOST_ECHO + usb_echo( + "USB_HostPhdcBulkInPipeCallback: Error for " + "USB_HostPhdcSetClearFeatureEndpointHalt\r\n"); +#endif + } + } + else + { + /* The meta-data message preamble data is correct, update the phdc status and + * numberTransferBulkIn value */ + phdcInstance->numberTransferBulkIn = metaDataMsgPreamble->bNumberTransfers; + } + } + } + } + } + if (NULL != phdcInstance->inCallbackFn) + { + phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar, + status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief phdc bulk out pipe transfer callback. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcBulkOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + +#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) + if (status == kStatus_USB_TransferStall) + { + if (USB_HostPhdcClearHalt( + phdcInstance, transfer, USB_HostPhdcClearOutHaltCallback, + (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)phdcInstance->bulkOutPipe)->endpointAddress)) == + kStatus_USB_Success) + { + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return; + } + } +#endif + if (NULL != phdcInstance->outCallbackFn) + { + phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar, + status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief phdc open interface. + * + * @param phdcInstance phdc instance pointer. + * + * @return kStatus_USB_Success or error codes. + */ +static usb_status_t USB_HostPhdcOpenInterface(usb_host_phdc_instance_t *phdcInstance) +{ + usb_status_t status; + uint8_t epIndex = 0U; + usb_host_pipe_init_t pipeInit; + usb_descriptor_endpoint_t *epDesc = NULL; + usb_host_interface_t *interface; + if (NULL != phdcInstance->interruptPipe) + { + /* Close the PHDC interrupt pipe if it is opening */ + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->interruptPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n"); +#endif + } + phdcInstance->interruptPipe = NULL; + } + + if (NULL != phdcInstance->bulkInPipe) + { + /* Close the PHDC bulk in pipe if it is opening */ + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkInPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n"); +#endif + } + phdcInstance->bulkInPipe = NULL; + } + + if (NULL != phdcInstance->bulkOutPipe) + { + /* Close the PHDC bulk out pipe if it is opening */ + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkOutPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when close pipe\r\n"); +#endif + } + phdcInstance->bulkOutPipe = NULL; + } + + /* open interface pipes */ + interface = (usb_host_interface_t *)phdcInstance->interfaceHandle; + for (epIndex = 0U; epIndex < interface->epCount; ++epIndex) + { + epDesc = interface->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_INTERRUPT)) + { + /* Initialize the interrupt pipe */ + pipeInit.devInstance = phdcInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_INTERRUPT; + 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(phdcInstance->hostHandle, &phdcInstance->interruptPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n"); +#endif + return kStatus_USB_Error; + } + /* save interrupt in endpoint information */ + phdcInstance->interruptInEndpointInformation = interface->epList[epIndex]; + } + else 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)) + { + /* Initialize bulk in pipe */ + pipeInit.devInstance = phdcInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_IN; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + 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(phdcInstance->hostHandle, &phdcInstance->bulkInPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n"); +#endif + return kStatus_USB_Error; + } + /* save bulk in endpoint information */ + phdcInstance->bulkInEndpointInformation = interface->epList[epIndex]; + } + 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)) + { + /* Initialize bulk out pipe */ + pipeInit.devInstance = phdcInstance->deviceHandle; + pipeInit.pipeType = USB_ENDPOINT_BULK; + pipeInit.direction = USB_OUT; + pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); + 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(phdcInstance->hostHandle, &phdcInstance->bulkOutPipe, &pipeInit); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcOpenInterface: Error when open pipe\r\n"); +#endif + return kStatus_USB_Error; + } + /* save bulk out endpoint information */ + phdcInstance->bulkOutEndpointInformation = interface->epList[epIndex]; + } + else + { + } + } + return kStatus_USB_Success; +} + +/*! + * @brief phdc set interface callback, open pipes. + * + * @param param callback parameter. + * @param transfer callback transfer. + * @param status transfer status. + */ +static void USB_HostPhdcSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)param; + + phdcInstance->controlTransfer = NULL; + if (status == kStatus_USB_Success) + { + /* set interface is done, open the interface */ + status = USB_HostPhdcOpenInterface(phdcInstance); + } + + if (NULL != phdcInstance->controlCallbackFn) + { + /* Notify to application the status of set interface request */ + phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, NULL, 0U, status); + } + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); +} + +/*! + * @brief set interface. + * + * This function binds the interface with the phdc instance. + * + * @param classHandle the class handle. + * @param interfaceHandle the interface handle. + * @param alternateSetting the alternate setting value. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup. + * @retval kStatus_USB_Busy callback return status, there is no idle pipe. + * @retval kStatus_USB_TransferStall callback return status, the transfer is stall by device. + * @retval kStatus_USB_Error callback return status, open pipe fail, please reference to USB_HostOpenPipe. + */ +usb_status_t USB_HostPhdcSetInterface(usb_host_class_handle classHandle, + usb_host_interface_handle interfaceHandle, + uint8_t alternateSetting, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_status_t status; + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_host_transfer_t *transfer; + + if (NULL == classHandle) + { + return kStatus_USB_InvalidParameter; + } + + phdcInstance->interfaceHandle = interfaceHandle; + + status = USB_HostOpenDeviceInterface(phdcInstance->deviceHandle, interfaceHandle); + if (status != kStatus_USB_Success) + { + return status; + } + + /* Cancel interrupt transfers */ + if (NULL != phdcInstance->interruptPipe) + { + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->interruptPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n"); +#endif + } + } + /* Cancel bulk in transfers */ + if (NULL != phdcInstance->bulkInPipe) + { + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkInPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n"); +#endif + } + } + /* Cancel bulk out transfers */ + if (NULL != phdcInstance->bulkOutPipe) + { + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, NULL); + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSetInterface: Error when cancel pipe\r\n"); +#endif + } + phdcInstance->bulkOutPipe = NULL; + } + if (0U == alternateSetting) + { + if (NULL != callbackFn) + { + status = USB_HostPhdcOpenInterface(phdcInstance); + callbackFn(callbackParam, NULL, 0U, status); + } + } + else + { + /* Create transfer buffer */ + if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSetInterface: Error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + /* Save application callback function and parameter */ + phdcInstance->controlCallbackFn = callbackFn; + phdcInstance->controlCallbackParam = callbackParam; + /* Initialize transfer */ + transfer->callbackFn = USB_HostPhdcSetInterfaceCallback; + transfer->callbackParam = phdcInstance; + 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 *)phdcInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber); + transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting); + transfer->setupPacket.wLength = 0; + transfer->transferBuffer = NULL; + transfer->transferLength = 0; + /* Send set interface request to device */ + status = USB_HostSendSetup(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer); + if (status == kStatus_USB_Success) + { + phdcInstance->controlTransfer = transfer; + } + else + { + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + } + } + return status; +} + +/*! + * @brief initialize the phdc instance. + * + * This function allocates the resource for phdc instance. + * + * @param deviceHandle the device handle. + * @param classHandle return class handle. + * + * @retval kStatus_USB_Success The device is initialized successfully. + * @retval kStatus_USB_AllocFail Allocate memory fail. + */ +usb_status_t USB_HostPhdcInit(usb_host_handle deviceHandle, usb_host_class_handle *classHandle) +{ + usb_host_phdc_instance_t *phdcInstance = + (usb_host_phdc_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_phdc_instance_t)); + uint32_t infoValue; + + if (NULL == phdcInstance) + { + return kStatus_USB_AllocFail; + } + /* Initialize PHDC instance */ + phdcInstance->deviceHandle = deviceHandle; + phdcInstance->interfaceHandle = NULL; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue); + phdcInstance->hostHandle = (usb_host_handle)infoValue; + USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue); + phdcInstance->controlPipe = (usb_host_pipe_handle)infoValue; + + *classHandle = phdcInstance; + return kStatus_USB_Success; +} + +/*! + * @brief de-initialize the phdc instance. + * + * This function release the resource for phdc instance. + * + * @param deviceHandle the device handle. + * @param classHandle the class handle. + * + * @retval kStatus_USB_Success The device is de-initialized successfully. + */ +usb_status_t USB_HostPhdcDeinit(usb_host_handle deviceHandle, usb_host_class_handle classHandle) +{ + usb_status_t status; + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + + if (NULL == deviceHandle) + { + return kStatus_USB_InvalidHandle; + } + + if (NULL != classHandle) + { + if (NULL != phdcInstance->interruptPipe) + { + /* Cancel/close interrupt transfers/pipe */ + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->interruptPipe, NULL); + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->interruptPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n"); +#endif + } + phdcInstance->interruptPipe = NULL; + } + if (NULL != phdcInstance->bulkInPipe) + { + /* Cancel/close bulk in transfers/pipe */ + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkInPipe, NULL); + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkInPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n"); +#endif + } + phdcInstance->bulkInPipe = NULL; + } + if (NULL != phdcInstance->bulkOutPipe) + { + /* Cancel/close bulk out transfers/pipe */ + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, NULL); + status = USB_HostClosePipe(phdcInstance->hostHandle, phdcInstance->bulkOutPipe); + + if (status != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcDeinit: Error when close pipe\r\n"); +#endif + } + phdcInstance->bulkOutPipe = NULL; + } + if ((NULL != phdcInstance->controlPipe) && (NULL != phdcInstance->controlTransfer)) + { + /* Cancel control transfers */ + status = USB_HostCancelTransfer(phdcInstance->hostHandle, phdcInstance->controlPipe, + phdcInstance->controlTransfer); + } + /* Close device interface */ + USB_HostCloseDeviceInterface(deviceHandle, phdcInstance->interfaceHandle); + /* Release PHDC instance */ + USB_OsaMemoryFree(phdcInstance); + } + else + { + USB_HostCloseDeviceInterface(deviceHandle, NULL); + } + return kStatus_USB_Success; +} + +/*! + * @brief receive data. + * + * This function implements phdc receiving data. + * + * @param classHandle the class handle. + * @param qos QoS of the data being received. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success receive request successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostRecv. + */ +usb_status_t USB_HostPhdcRecv(usb_host_class_handle classHandle, + uint8_t qos, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_host_transfer_t *transfer; + usb_host_pipe_handle pipe; + usb_host_phdc_qos_descriptor_t *qosDesc = NULL; + + if (NULL == classHandle) + { + return kStatus_USB_InvalidHandle; + } + + if ((NULL == phdcInstance->interruptPipe) && (NULL == phdcInstance->bulkInPipe)) + { + return kStatus_USB_Error; + } + /* Allocate the transfer buffer */ + if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + /* Save application callback function and parameter */ + phdcInstance->inCallbackFn = callbackFn; + phdcInstance->inCallbackParam = callbackParam; + /* Initialize the transfer pointer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackParam = phdcInstance; + /* The on can receive the data on interrupt pipe or bulk in pipe depends on the QoS value */ + pipe = (qos & 0x01U) ? (phdcInstance->interruptPipe) : (phdcInstance->bulkInPipe); + if (pipe == phdcInstance->bulkInPipe) + { + /* get bulk in QoS descriptor */ + qosDesc = (usb_host_phdc_qos_descriptor_t *)phdcInstance->bulkInEndpointInformation.epExtension; + transfer->callbackFn = USB_HostPhdcBulkInPipeCallback; + } + else + { + /* get interrupt in QoS descriptor */ + qosDesc = (usb_host_phdc_qos_descriptor_t *)phdcInstance->interruptInEndpointInformation.epExtension; + transfer->callbackFn = USB_HostPhdcInterruptPipeCallback; + } + /* Latency and reliability checking */ + if (!(qos & qosDesc->bmLatencyReliability)) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcRecv, ERROR: invalid QoS bin"); +#endif + return kStatus_USB_Error; + } + /* The previous control transfer is pending */ + if (NULL != phdcInstance->controlTransfer) + { +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcRecv, ERROR: Control transfer is in progress"); +#endif + return kStatus_USB_Busy; + } + if (USB_HostRecv(phdcInstance->hostHandle, pipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("fail to USB_HostRecv\r\n"); +#endif + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + + return kStatus_USB_Success; +} + +/*! + * @brief send data. + * + * This function implements phdc sending data. + * + * @param classHandle the class handle. + * @param buffer the buffer pointer. + * @param bufferLength the buffer length. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send request successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSend. + */ +usb_status_t USB_HostPhdcSend(usb_host_class_handle classHandle, + uint8_t *buffer, + uint32_t bufferLength, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_host_transfer_t *transfer; + usb_status_t status; + if (classHandle == NULL) + { + return kStatus_USB_InvalidHandle; + } + + if (NULL == phdcInstance->bulkOutPipe) + { + return kStatus_USB_Error; + } + if (NULL != phdcInstance->controlTransfer) + { + status = kStatus_USB_Busy; +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSend, Error: control transfer is in progress"); +#endif + return status; + } + /* The meta-data message preamble is implemented and enabled */ + if (phdcInstance->isMessagePreambleEnabled == 1U) + { + /* The meta-data message preamble feature is enabled, then all data transfers or sets + of data transfers shall be preceded by a meta-data message preamble transfer. The + numberTransferBulkOut is initialized as zero for sending this message preamble data, + then it is updated to the value of bNumTransfers field of message preamble data */ + if (phdcInstance->numberTransferBulkOut) + { + /* When numberTransferBulkOut reduces to 0, a new meta-data message preamble shall + be transferred */ + phdcInstance->numberTransferBulkOut--; + } + else + { + usb_host_phdc_qos_descriptor_t *qosDesc = + (usb_host_phdc_qos_descriptor_t *)phdcInstance->bulkOutEndpointInformation.epExtension; + ; + uint8_t latencyReliability = ((usb_host_phdc_metadata_preamble_t *)buffer)->bmLatencyReliability; + /* Latency reliability validity checking */ + if ((latencyReliability != 0x02U) && /* Medium.Good latency, reliability bin */ + (latencyReliability != 0x04U) && /* Medium.Better latency, reliability bin */ + (latencyReliability != 0x08U) && /* Medium.Best latency, reliability bin */ + (latencyReliability != 0x10U) && /* High.Best latency, reliability bin */ + (latencyReliability != 0x20U) /* VeryHigh.Best latency, reliability bin */) + { + status = kStatus_USB_InvalidRequest; +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSend, Error: invalid LatencyReliability"); +#endif + return status; + } + /* LatencyReliablity checking */ + if (0U == (qosDesc->bmLatencyReliability & latencyReliability)) + { + status = kStatus_USB_Error; +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSend, Error: the latency reliability is not supported by Bulk OUT endpoint"); +#endif + return status; + } + if (0U == ((usb_host_phdc_metadata_preamble_t *)buffer)->bNumberTransfers) + { + status = kStatus_USB_Error; +#ifdef HOST_ECHO + usb_echo("USB_HostPhdcSend, Error: the numTransfer should never zero"); +#endif + return status; + } + /* Update the number of bulk out transfer */ + phdcInstance->numberTransferBulkOut = ((usb_host_phdc_metadata_preamble_t *)buffer)->bNumberTransfers; + } + } + /* Allocate the transfer pointer */ + if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + /* Save the application callback function and parameter */ + phdcInstance->outCallbackFn = callbackFn; + phdcInstance->outCallbackParam = callbackParam; + /* Initialize the transfer pointer */ + transfer->transferBuffer = buffer; + transfer->transferLength = bufferLength; + transfer->callbackFn = USB_HostPhdcBulkOutPipeCallback; + transfer->callbackParam = phdcInstance; + if (USB_HostSend(phdcInstance->hostHandle, phdcInstance->bulkOutPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("fail to USB_HostSend\r\n"); +#endif + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + return kStatus_USB_Success; +} + +/*! + * @brief phdc sends control request. + * + * @param classHandle the class handle. + * @param request_type setup packet request. + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send request successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSend. + */ +usb_status_t USB_HostPhdcSendControlRequest(usb_host_class_handle classHandle, + uint8_t request, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_status_t status = kStatus_USB_Success; + usb_host_transfer_t *transfer; + + if (NULL == classHandle) + { + return kStatus_USB_InvalidHandle; + } + + if (NULL == phdcInstance->controlPipe) + { + return kStatus_USB_Error; + } + + if (NULL != phdcInstance->controlTransfer) + { + return kStatus_USB_Busy; + } + /* Allocate the transfer pointer */ + if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + /* Save the callback function and parameter */ + phdcInstance->controlCallbackFn = callbackFn; + phdcInstance->controlCallbackParam = callbackParam; + /* Initialize the transfer pointer */ + transfer->callbackFn = USB_HostPhdcControlPipeCallback; + transfer->callbackParam = phdcInstance; + transfer->setupPacket.bRequest = request; + transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN( + ((usb_host_interface_t *)phdcInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber); + switch (request) + { + case USB_HOST_PHDC_GET_STATUS_REQUEST: + /* Initialize the PHDC get status request */ + transfer->setupPacket.wValue = 0U; + transfer->setupPacket.bmRequestType = + USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket.wLength = 2U; + break; + case USB_HOST_PHDC_SET_FEATURE_REQUEST: + case USB_HOST_PHDC_CLEAR_FEATURE_REQUEST: + /* Initialize the PHDC set/clear feature request */ + transfer->setupPacket.bmRequestType = + USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE; + transfer->setupPacket.wValue = + (USB_HOST_PHDC_FEATURE_METADATA | (uint16_t)((uint16_t)USB_HOST_PHDC_QOS_ENCODING_VERSION << 8U)); + transfer->setupPacket.wLength = 0U; + break; + default: + status = kStatus_USB_InvalidRequest; + break; + } + if (USB_HostSendSetup(phdcInstance->hostHandle, phdcInstance->controlPipe, transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("fail for USB_HostSendSetup\r\n"); +#endif + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + phdcInstance->controlTransfer = transfer; + + return status; +} + +/*! + * @brief phdc set and clear feature endpoint halt request for meta-data message preamble error. + * + * @param classHandle the class handle. + * @param request setup packet request. + * @param param request parameter + * @param callbackFn this callback is called after this function completes. + * @param callbackParam the first parameter in the callback function. + * + * @retval kStatus_USB_Success send request successfully. + * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. + * @retval kStatus_USB_Busy There is no idle transfer. + * @retval kStatus_USB_Error pipe is not initialized. + * Or, send transfer fail, please reference to USB_HostSend. + */ +usb_status_t USB_HostPhdcSetClearFeatureEndpointHalt(usb_host_class_handle classHandle, + uint8_t request, + void *param, + transfer_callback_t callbackFn, + void *callbackParam) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_host_transfer_t *transfer; + if (NULL == classHandle) + { + return kStatus_USB_InvalidHandle; + } + + if (NULL == phdcInstance->controlPipe) + { + return kStatus_USB_Error; + } + + if (NULL != phdcInstance->controlTransfer) + { + return kStatus_USB_Busy; + } + /* Allocate the transfer pointer */ + if (USB_HostMallocTransfer(phdcInstance->hostHandle, &transfer) != kStatus_USB_Success) + { +#ifdef HOST_ECHO + usb_echo("error to get transfer\r\n"); +#endif + return kStatus_USB_Error; + } + /* Save application callback function and parameter */ + phdcInstance->controlCallbackFn = callbackFn; + phdcInstance->controlCallbackParam = callbackParam; + /* Initialize the transfer request */ + transfer->callbackFn = USB_HostPhdcSetClearFeatureEndpointHaltCallback; + transfer->callbackParam = phdcInstance; + if (USB_HostRequestControl(phdcInstance->hostHandle, request, transfer, param)) + { +#ifdef HOST_ECHO + usb_echo("fail for USB_HostRequestControl\r\n"); +#endif + USB_HostFreeTransfer(phdcInstance->hostHandle, transfer); + return kStatus_USB_Error; + } + phdcInstance->controlTransfer = transfer; + + return kStatus_USB_Success; +} + +/*! + * @brief USB_HostPhdcGetEndpointInformation. + * This function returns the PHDC endpoint information structure contains endpoint + * descriptor and endpoint extended descriptor. + * + * @param classHandle the class handle. + * @param pipeType pipe type. + * @param direction pipe direction. + * + * @retval endpointReturn All input parameters are valid. + * @retval NULL One or more input parameters are invalid. + */ +usb_host_ep_t *USB_HostPhdcGetEndpointInformation(usb_host_class_handle classHandle, + uint8_t pipeType, + uint8_t direction) +{ + usb_host_phdc_instance_t *phdcInstance = (usb_host_phdc_instance_t *)classHandle; + usb_host_ep_t *endpointReturn = NULL; + if (NULL != classHandle) + { + if (pipeType == USB_ENDPOINT_BULK) + { + if (direction == USB_IN) + { + /* bulk in endpoint information */ + endpointReturn = (usb_host_ep_t *)&phdcInstance->bulkInEndpointInformation; + } + else + { + /* bulk out endpoint information */ + endpointReturn = (usb_host_ep_t *)&phdcInstance->bulkOutEndpointInformation; + } + } + else if (pipeType == USB_ENDPOINT_INTERRUPT) + { + /* interrupt in endpoint information */ + endpointReturn = (usb_host_ep_t *)&phdcInstance->interruptInEndpointInformation; + } + else + { + } + } + return endpointReturn; +} +#endif -- cgit v1.2.3