RT1050_FreeRTOS_USB_Hello/middleware/usb/host/class/usb_host_phdc.c

1289 lines
52 KiB
C

/*
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
* Copyright 2016,2019 NXP
* All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#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, the callback function is initialized in USB_HostPhdcRecv */
phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, phdcInstance->stallDataBuffer,
phdcInstance->stallDataLength, kStatus_USB_TransferStall);
}
(void)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, callback function is initialized in USB_HostPhdcSend */
phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, phdcInstance->stallDataBuffer,
phdcInstance->stallDataLength, kStatus_USB_TransferStall);
}
(void)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)
{
(void)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
{
/*no action*/
}
}
if (NULL != phdcInstance->controlCallbackFn)
{
/* callback function is initialized in USB_HostPhdcSetInterface */
phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer,
transfer->transferSofar, status);
}
(void)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 = (uint8_t)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, callback function is initialized in USB_HostPhdcSetInterface */
phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, transfer->transferBuffer,
transfer->transferSofar, status);
}
(void)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)
{
(void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
return;
}
}
#endif
if (NULL != phdcInstance->inCallbackFn)
{
/* callback to application, the callback function is initialized in USB_HostPhdcRecv */
phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
status);
}
(void)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;
void *temp;
#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)
{
(void)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 (0U != 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 */
temp = (void *)transfer->transferBuffer;
usb_host_phdc_metadata_preamble_t *metaDataMsgPreamble = (usb_host_phdc_metadata_preamble_t *)temp;
/* Meta-data message preamble signature checking */
for (uint8_t i = 0U; i < USB_HOST_PHDC_MESSAGE_PREAMBLE_SIGNATURE_SIZE; i++)
{
if (*(transfer->transferBuffer + i) != (uint8_t)metaDataMsgPreambleSignature[i])
{
preambleSignatureChecking = 0U;
break;
}
}
if (0U != preambleSignatureChecking)
{
/* Checks if the meta-data message preamble contains an invalid bmLatencyReliability value
or bNumTransfers value */
if ((0U == (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 = (uint8_t)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)
{
/* callback to application, the callback function is initialized in USB_HostPhdcRecv */
phdcInstance->inCallbackFn(phdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
status);
}
(void)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)
{
(void)USB_HostFreeTransfer(phdcInstance->hostHandle, transfer);
return;
}
}
#endif
if (NULL != phdcInstance->outCallbackFn)
{
/* callback to application, callback function is initialized in USB_HostPhdcSend */
phdcInstance->outCallbackFn(phdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
status);
}
(void)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 = (uint8_t)((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 = (uint8_t)((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 = (uint8_t)((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
{
/*no action*/
}
}
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, callback function is initialized in
* USB_HostPhdcSetInterface */
phdcInstance->controlCallbackFn(phdcInstance->controlCallbackParam, NULL, 0U, status);
}
(void)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
{
(void)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 *)OSA_MemoryAllocate(sizeof(usb_host_phdc_instance_t));
uint32_t infoValue;
uint32_t *temp;
if (NULL == phdcInstance)
{
return kStatus_USB_AllocFail;
}
/* Initialize PHDC instance */
phdcInstance->deviceHandle = deviceHandle;
phdcInstance->interfaceHandle = NULL;
(void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &infoValue);
temp = (uint32_t *)infoValue;
phdcInstance->hostHandle = (usb_host_handle)temp;
(void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &infoValue);
temp = (uint32_t *)infoValue;
phdcInstance->controlPipe = (usb_host_pipe_handle)temp;
*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);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
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);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
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);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
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);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
}
/* Close device interface */
(void)USB_HostCloseDeviceInterface(deviceHandle, phdcInstance->interfaceHandle);
/* Release PHDC instance */
OSA_MemoryFree(phdcInstance);
}
else
{
(void)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;
void *temp;
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 = (0U != (qos & 0x01U)) ? (phdcInstance->interruptPipe) : (phdcInstance->bulkInPipe);
if (pipe == phdcInstance->bulkInPipe)
{
/* get bulk in QoS descriptor */
temp = (void *)phdcInstance->bulkInEndpointInformation.epExtension;
qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
transfer->callbackFn = USB_HostPhdcBulkInPipeCallback;
}
else
{
/* get interrupt in QoS descriptor */
temp = (void *)phdcInstance->interruptInEndpointInformation.epExtension;
qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
transfer->callbackFn = USB_HostPhdcInterruptPipeCallback;
}
/* Latency and reliability checking */
if (0U == (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
(void)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;
void *temp;
usb_host_phdc_metadata_preamble_t *preamble;
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 (0U != phdcInstance->numberTransferBulkOut)
{
/* When numberTransferBulkOut reduces to 0, a new meta-data message preamble shall
be transferred */
phdcInstance->numberTransferBulkOut--;
}
else
{
temp = (void *)phdcInstance->bulkOutEndpointInformation.epExtension;
usb_host_phdc_qos_descriptor_t *qosDesc = (usb_host_phdc_qos_descriptor_t *)temp;
temp = (void *)buffer;
preamble = (usb_host_phdc_metadata_preamble_t *)temp;
uint8_t latencyReliability = preamble->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 == preamble->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 = preamble->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
(void)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 = USB_SHORT_TO_LITTLE_ENDIAN(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_SHORT_TO_LITTLE_ENDIAN(
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
(void)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 (kStatus_USB_Success != USB_HostRequestControl(phdcInstance->deviceHandle, request, transfer, param))
{
#ifdef HOST_ECHO
usb_echo("fail for USB_HostRequestControl\r\n");
#endif
(void)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
{
/*no action*/
}
}
return endpointReturn;
}
#endif