summaryrefslogtreecommitdiff
path: root/usb_1.1.0/host/class/usb_host_phdc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usb_1.1.0/host/class/usb_host_phdc.c')
-rw-r--r--usb_1.1.0/host/class/usb_host_phdc.c1272
1 files changed, 1272 insertions, 0 deletions
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