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

1278 lines
49 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* 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_CDC) && (USB_HOST_CONFIG_CDC))
#include "usb_host.h"
#include "usb_host_cdc.h"
#include "usb_host_devices.h"
#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
static void USB_HostCdcClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
cdcInstance->controlTransfer = NULL;
if (cdcInstance->inCallbackFn != NULL)
{
/* callback to application, the callback function is initialized in USB_HostCdcDataRecv */
cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, cdcInstance->stallDataBuffer,
cdcInstance->stallDataLength, kStatus_USB_TransferStall);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
static void USB_HostCdcClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
cdcInstance->controlTransfer = NULL;
if (cdcInstance->outCallbackFn != NULL)
{
/* callback to applicationthe callback function is initialized in USB_HostCdcDataSend */
cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, cdcInstance->stallDataBuffer,
cdcInstance->stallDataLength, kStatus_USB_TransferStall);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
static void USB_HostCdcClearInterruptHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
cdcInstance->controlTransfer = NULL;
if (cdcInstance->interruptCallbackFn != NULL)
{
/* callback to application */
cdcInstance->interruptCallbackFn(cdcInstance->interruptCallbackParam, cdcInstance->stallDataBuffer,
cdcInstance->stallDataLength, kStatus_USB_TransferStall);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
static usb_status_t USB_HostCdcClearHalt(usb_host_cdc_instance_struct_t *cdcInstance,
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(cdcInstance->hostHandle, &transfer);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("allocate transfer error\r\n");
#endif
return status;
}
cdcInstance->stallDataBuffer = stallTransfer->transferBuffer;
cdcInstance->stallDataLength = stallTransfer->transferSofar;
/* save the application callback function */
cdcInstance->controlCallbackFn = NULL;
cdcInstance->controlCallbackParam = NULL;
/* initialize transfer */
transfer->callbackFn = callbackFn;
transfer->callbackParam = cdcInstance;
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(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
if (status != kStatus_USB_Success)
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
cdcInstance->controlTransfer = transfer;
return status;
}
#endif
/*!
* @brief cdc data in pipe transfer callback.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcDataInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_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_HostCdcClearHalt(cdcInstance, transfer, USB_HostCdcClearInHaltCallback,
(USB_REQUEST_TYPE_DIR_IN |
((usb_host_pipe_t *)cdcInstance->inPipe)->endpointAddress)) == kStatus_USB_Success)
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return;
}
}
#endif
if (cdcInstance->inCallbackFn != NULL)
{
/* callback to application, the callback function is initialized in USB_HostCdcDataRecv */
cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief cdc data out pipe transfer callback.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcDataOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_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_HostCdcClearHalt(cdcInstance, transfer, USB_HostCdcClearOutHaltCallback,
(USB_REQUEST_TYPE_DIR_OUT |
((usb_host_pipe_t *)cdcInstance->outPipe)->endpointAddress)) == kStatus_USB_Success)
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return;
}
}
#endif
if (cdcInstance->outCallbackFn != NULL)
{
/* callback to applicationthe callback function is initialized in USB_HostCdcDataSend */
cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief cdc data out pipe transfer callback.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcInterruptPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_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_HostCdcClearHalt(
cdcInstance, transfer, USB_HostCdcClearInterruptHaltCallback,
(USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)cdcInstance->interruptPipe)->endpointAddress)) ==
kStatus_USB_Success)
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return;
}
}
#endif
if (cdcInstance->interruptCallbackFn != NULL)
{
cdcInstance->interruptCallbackFn(cdcInstance->interruptCallbackParam, transfer->transferBuffer,
transfer->transferSofar, status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief cdc data out pipe transfer callback.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
if (cdcInstance->controlCallbackFn != NULL)
{
/* callback to application, callback function is initialized in the USB_HostCdcControl,
USB_HostCdcSetControlInterface
or USB_HostCdcSetDataInterface, but is the same function */
cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, transfer->transferBuffer,
transfer->transferSofar, status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief cdc open data interface.
*
* @param cdcInstance cdc instance pointer.
*
* @return kStatus_USB_Success or error codes.
*/
static usb_status_t USB_HostCdcOpenDataInterface(usb_host_cdc_instance_struct_t *cdcInstance)
{
usb_status_t status;
uint8_t ep_index = 0;
usb_host_pipe_init_t pipeInit;
usb_descriptor_endpoint_t *ep_desc = NULL;
usb_host_interface_t *interfaceHandle;
if (cdcInstance->inPipe != NULL)
{
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->inPipe = NULL;
}
if (cdcInstance->outPipe != NULL)
{
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->outPipe = NULL;
}
status = USB_HostOpenDeviceInterface(cdcInstance->deviceHandle, cdcInstance->dataInterfaceHandle);
if (status != kStatus_USB_Success)
{
return status;
}
/* open interface pipes */
interfaceHandle = (usb_host_interface_t *)cdcInstance->dataInterfaceHandle;
for (ep_index = 0; ep_index < interfaceHandle->epCount; ++ep_index)
{
ep_desc = interfaceHandle->epList[ep_index].epDesc;
if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
{
pipeInit.devInstance = cdcInstance->deviceHandle;
pipeInit.pipeType = USB_ENDPOINT_BULK;
pipeInit.direction = USB_IN;
pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
pipeInit.interval = ep_desc->bInterval;
pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
cdcInstance->bulkInPacketSize = pipeInit.maxPacketSize;
status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->inPipe, &pipeInit);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("usb_host_audio_set_interface fail to open pipe\r\n");
#endif
return kStatus_USB_Error;
}
}
else if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
{
pipeInit.devInstance = cdcInstance->deviceHandle;
pipeInit.pipeType = USB_ENDPOINT_BULK;
pipeInit.direction = USB_OUT;
pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
pipeInit.interval = ep_desc->bInterval;
pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
cdcInstance->bulkOutPacketSize = pipeInit.maxPacketSize;
status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->outPipe, &pipeInit);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("usb_host_cdc_set_dat_interface fail to open pipe\r\n");
#endif
return kStatus_USB_Error;
}
}
else
{
}
}
return kStatus_USB_Success;
}
/*!
* @brief cdc set data interface callback, open pipes.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcSetDataInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
cdcInstance->controlTransfer = NULL;
if (status == kStatus_USB_Success)
{
status = USB_HostCdcOpenDataInterface(cdcInstance);
}
if (cdcInstance->controlCallbackFn != NULL)
{
/* callback to application, callback function is initialized in the USB_HostCdcControl,
USB_HostCdcSetControlInterface
or USB_HostCdcSetDataInterface, but is the same function */
cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief cdc open control interface.
*
* @param cdcInstance cdc instance pointer.
*
* @return kStatus_USB_Success or error codes.
*/
static usb_status_t USB_HostCdcOpenControlInterface(usb_host_cdc_instance_struct_t *cdcInstance)
{
usb_status_t status;
uint8_t ep_index = 0;
usb_host_pipe_init_t pipeInit;
usb_descriptor_endpoint_t *ep_desc = NULL;
usb_host_interface_t *interfaceHandle;
if (cdcInstance->interruptPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->interruptPipe = NULL;
}
status = USB_HostOpenDeviceInterface(cdcInstance->deviceHandle, cdcInstance->controlInterfaceHandle);
if (status != kStatus_USB_Success)
{
return status;
}
/* open interface pipes */
interfaceHandle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
for (ep_index = 0; ep_index < interfaceHandle->epCount; ++ep_index)
{
ep_desc = interfaceHandle->epList[ep_index].epDesc;
if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
{
pipeInit.devInstance = cdcInstance->deviceHandle;
pipeInit.pipeType = USB_ENDPOINT_INTERRUPT;
pipeInit.direction = USB_IN;
pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
pipeInit.interval = ep_desc->bInterval;
pipeInit.maxPacketSize = (uint16_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK));
pipeInit.numberPerUframe = (uint8_t)((USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK));
pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
cdcInstance->packetSize = pipeInit.maxPacketSize;
status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->interruptPipe, &pipeInit);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("USB_HostCdcSetControlInterface fail to open pipe\r\n");
#endif
return kStatus_USB_Error;
}
}
}
return kStatus_USB_Success;
}
/*!
* @brief cdc set control interface callback, open pipes.
*
* @param param callback parameter.
* @param transfer callback transfer.
* @param status transfer status.
*/
static void USB_HostCdcSetContorlInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)param;
cdcInstance->controlTransfer = NULL;
if (status == kStatus_USB_Success)
{
status = USB_HostCdcOpenControlInterface(cdcInstance);
}
if (cdcInstance->controlCallbackFn != NULL)
{
/* callback to application, callback function is initialized in the USB_HostCdcControl,
USB_HostCdcSetControlInterface
or USB_HostCdcSetDataInterface, but is the same function */
cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
}
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
/*!
* @brief initialize the cdc instance.
*
* This function allocate the resource for cdc 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_HostCdcInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
{
usb_host_cdc_instance_struct_t *control_ptr =
(usb_host_cdc_instance_struct_t *)OSA_MemoryAllocate(sizeof(usb_host_cdc_instance_struct_t));
uint32_t info_value;
void *temp;
if (control_ptr == NULL)
{
return kStatus_USB_AllocFail;
}
control_ptr->deviceHandle = deviceHandle;
control_ptr->controlInterfaceHandle = NULL;
control_ptr->dataInterfaceHandle = NULL;
(void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetHostHandle, &info_value);
temp = (uint32_t *)info_value;
control_ptr->hostHandle = (usb_host_handle)temp;
(void)USB_HostHelperGetPeripheralInformation(deviceHandle, (uint32_t)kUSB_HostGetDeviceControlPipe, &info_value);
temp = (uint32_t *)info_value;
control_ptr->controlPipe = (usb_host_pipe_handle)temp;
*classHandle = control_ptr;
return kStatus_USB_Success;
}
/*!
* @brief set control interface.
*
* This function bind the control interface with the cdc instance.
*
* @param classHandle the class handle.
* @param interfaceHandle the control 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_HostCdcSetControlInterface(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_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
status = kStatus_USB_Success;
if (classHandle == NULL)
{
return kStatus_USB_InvalidParameter;
}
cdcInstance->controlInterfaceHandle = interfaceHandle;
/* cancel transfers */
if (cdcInstance->interruptPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
}
if (alternateSetting == 0U)
{
if (callbackFn != NULL)
{
status = USB_HostCdcOpenControlInterface(cdcInstance);
callbackFn(callbackParam, NULL, 0U, status);
}
}
else
{
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->controlCallbackFn = callbackFn;
cdcInstance->controlCallbackParam = callbackParam;
/* initialize transfer */
transfer->callbackFn = USB_HostCdcSetContorlInterfaceCallback;
transfer->callbackParam = cdcInstance;
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 *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber);
transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
transfer->setupPacket->wLength = 0;
transfer->transferBuffer = NULL;
transfer->transferLength = 0;
status = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
if (status == kStatus_USB_Success)
{
cdcInstance->controlTransfer = transfer;
}
else
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
}
return status;
}
/*!
* @brief set data interface.
*
* This function bind the control interface with the cdc instance.
*
* @param classHandle the class handle.
* @param interfaceHandle the data 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_HostCdcSetDataInterface(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_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
status = kStatus_USB_Success;
if (classHandle == NULL)
{
return kStatus_USB_InvalidParameter;
}
cdcInstance->dataInterfaceHandle = interfaceHandle;
/* cancel transfers */
if (cdcInstance->inPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
}
if (cdcInstance->outPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when cancel pipe\r\n");
#endif
}
}
if (alternateSetting == 0U)
{
if (callbackFn != NULL)
{
status = USB_HostCdcOpenDataInterface(cdcInstance);
callbackFn(callbackParam, NULL, 0, status);
}
}
else
{
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->controlCallbackFn = callbackFn;
cdcInstance->controlCallbackParam = callbackParam;
/* initialize transfer */
transfer->callbackFn = USB_HostCdcSetDataInterfaceCallback;
transfer->callbackParam = cdcInstance;
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 *)cdcInstance->dataInterfaceHandle)->interfaceDesc->bInterfaceNumber);
transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
transfer->setupPacket->wLength = 0;
transfer->transferBuffer = NULL;
transfer->transferLength = 0;
status = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer);
if (status == kStatus_USB_Success)
{
cdcInstance->controlTransfer = transfer;
}
else
{
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
}
}
return status;
}
/*!
* @brief de-initialize the cdc instance.
*
* This function release the resource for cdc 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_HostCdcDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
{
usb_status_t status = kStatus_USB_Error;
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
if (deviceHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
if (classHandle != NULL)
{
if (cdcInstance->interruptPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when Cancel pipe\r\n");
#endif
}
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->interruptPipe = NULL;
}
(void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->controlInterfaceHandle);
if (cdcInstance->inPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when Cancel pipe\r\n");
#endif
}
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->inPipe = NULL;
}
if (cdcInstance->outPipe != NULL)
{
status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when Cancel pipe\r\n");
#endif
}
status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe);
if (status != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error when close pipe\r\n");
#endif
}
cdcInstance->outPipe = NULL;
}
if ((cdcInstance->controlPipe != NULL) && (cdcInstance->controlTransfer != NULL))
{
status =
USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->controlPipe, cdcInstance->controlTransfer);
}
(void)USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->dataInterfaceHandle);
OSA_MemoryFree(cdcInstance);
}
else
{
(void)USB_HostCloseDeviceInterface(deviceHandle, NULL);
/*add for misra*/
status = kStatus_USB_Success;
}
return status;
}
/*!
* @brief receive data.
*
* This function implements cdc receiving 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 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_HostCdcDataRecv(usb_host_class_handle classHandle,
uint8_t *buffer,
uint32_t bufferLength,
transfer_callback_t callbackFn,
void *callbackParam)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
if (classHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
if (cdcInstance->inPipe == NULL)
{
return kStatus_USB_Error;
}
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->inCallbackFn = callbackFn;
cdcInstance->inCallbackParam = callbackParam;
transfer->transferBuffer = buffer;
transfer->transferLength = bufferLength;
transfer->callbackFn = USB_HostCdcDataInPipeCallback;
transfer->callbackParam = cdcInstance;
if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->inPipe, transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("failed to USB_HostRecv\r\n");
#endif
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return kStatus_USB_Error;
}
return kStatus_USB_Success;
}
/*!
* @brief send data.
*
* This function implements cdc 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 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_HostSend.
*/
usb_status_t USB_HostCdcDataSend(usb_host_class_handle classHandle,
uint8_t *buffer,
uint32_t bufferLength,
transfer_callback_t callbackFn,
void *callbackParam)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
if (classHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
if (cdcInstance->outPipe == NULL)
{
return kStatus_USB_Error;
}
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->outCallbackFn = callbackFn;
cdcInstance->outCallbackParam = callbackParam;
transfer->transferBuffer = buffer;
transfer->transferLength = bufferLength;
transfer->callbackFn = USB_HostCdcDataOutPipeCallback;
transfer->callbackParam = cdcInstance;
if (USB_HostSend(cdcInstance->hostHandle, cdcInstance->outPipe, transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("failed to USB_HostSend\r\n");
#endif
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return kStatus_USB_Error;
}
return kStatus_USB_Success;
}
/*!
* @brief interrupt receive data.
*
* This function implements interrupt receiving 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 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_HostCdcInterruptRecv(usb_host_class_handle classHandle,
uint8_t *buffer,
uint32_t bufferLength,
transfer_callback_t callbackFn,
void *callbackParam)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
if (classHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
if (cdcInstance->interruptPipe == NULL)
{
return kStatus_USB_Error;
}
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->interruptCallbackFn = callbackFn;
cdcInstance->interruptCallbackParam = callbackParam;
transfer->transferBuffer = buffer;
transfer->transferLength = bufferLength;
transfer->callbackFn = USB_HostCdcInterruptPipeCallback;
transfer->callbackParam = cdcInstance;
if (USB_HostRecv(cdcInstance->hostHandle, cdcInstance->interruptPipe, transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("failed to usb_interrupt_recv\r\n");
#endif
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return kStatus_USB_Error;
}
return kStatus_USB_Success;
}
/*!
* @brief get pipe max packet size.
*
* @param[in] classHandle the class handle.
* @param[in] pipeType It's value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
* USB_ENDPOINT_INTERRUPT.
* Please reference to usb_spec.h
* @param[in] direction pipe direction.
*
* @retval 0 The classHandle is NULL.
* @retval max packet size.
*/
uint16_t USB_HostCdcGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
if (classHandle == NULL)
{
return 0;
}
if (pipeType == USB_ENDPOINT_BULK)
{
if (direction == USB_IN)
{
return cdcInstance->bulkInPacketSize;
}
else
{
return cdcInstance->bulkOutPacketSize;
}
}
return 0;
}
/*!
* @brief cdc send control transfer common code.
*
* @param classHandle the class handle.
* @param request_type setup packet request type.
* @param request setup packet request value.
* @param wvalue_l setup packet wvalue low byte.
* @param wvalue_h setup packet wvalue high byte.
* @param wlength setup packet wlength value.
* @param data data buffer pointer
* @param callbackFn this callback is called after this function completes.
* @param callbackParam the first parameter in the callback function.
*
* @return An error code or kStatus_USB_Success.
*/
usb_status_t USB_HostCdcControl(usb_host_class_handle classHandle,
uint8_t request_type,
uint8_t request,
uint8_t wvalue_l,
uint8_t wvalue_h,
uint16_t wlength,
uint8_t *data,
transfer_callback_t callbackFn,
void *callbackParam)
{
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_host_transfer_t *transfer;
if (classHandle == NULL)
{
return kStatus_USB_InvalidHandle;
}
if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("error to get transfer\r\n");
#endif
return kStatus_USB_Error;
}
cdcInstance->controlCallbackFn = callbackFn;
cdcInstance->controlCallbackParam = callbackParam;
transfer->transferBuffer = data;
transfer->transferLength = wlength;
transfer->callbackFn = USB_HostCdcControlPipeCallback;
transfer->callbackParam = cdcInstance;
transfer->setupPacket->bmRequestType = request_type;
transfer->setupPacket->bRequest = request;
transfer->setupPacket->wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue_l | (uint16_t)((uint16_t)wvalue_h << 8));
transfer->setupPacket->wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
((usb_host_interface_t *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber);
transfer->setupPacket->wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
if (USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer) != kStatus_USB_Success)
{
#ifdef HOST_ECHO
usb_echo("failed for USB_HostSendSetup\r\n");
#endif
(void)USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
return kStatus_USB_Error;
}
cdcInstance->controlTransfer = transfer;
return kStatus_USB_Success;
}
/*!
* @brief cdc get line coding.
*
* This function implements cdc GetLineCoding request.refer to pstn spec.
*
* @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 request 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.
*/
usb_status_t USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,
usb_host_cdc_line_coding_struct_t *uartLineCoding,
transfer_callback_t callbackFn,
void *callbackParam)
{
return USB_HostCdcControl(
classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
USB_HOST_CDC_GET_LINE_CODING, 0, 0, 7, (uint8_t *)uartLineCoding, callbackFn, callbackParam);
}
/*!
* @brief cdc setControlLineState.
*
* This function implements cdc etControlLineState request.refer to pstn spec.
*
* @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 request 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.
*/
usb_status_t USB_HostCdcSetAcmCtrlState(
usb_host_class_handle classHandle, uint8_t dtr, uint8_t rts, transfer_callback_t callbackFn, void *callbackParam)
{
uint16_t lineState = 0U;
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
lineState = (0U != dtr) ? USB_HOST_CDC_CONTROL_LINE_STATE_DTR : 0U;
lineState |= (0U != rts) ? USB_HOST_CDC_CONTROL_LINE_STATE_RTS : 0U;
return USB_HostCdcControl(
cdcInstance, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
USB_HOST_CDC_SET_CONTROL_LINE_STATE, (uint8_t)USB_SHORT_GET_LOW(lineState), USB_SHORT_GET_HIGH(lineState), 0U,
NULL, callbackFn, callbackParam);
}
/*!
* @brief cdc send encapsulated command.
*
* This function implements cdc SEND_ENCAPSULATED_COMMAND request.refer to cdc 1.2 spec.
*
* @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 request 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.
*/
usb_status_t USB_HostCdcSendEncapsulatedCommand(usb_host_class_handle classHandle,
uint8_t *buffer,
uint16_t bufferLength,
transfer_callback_t callbackFn,
void *callbackParam)
{
return USB_HostCdcControl(
classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
USB_HOST_CDC_SEND_ENCAPSULATED_COMMAND, 0U, 0U, bufferLength, buffer, callbackFn, callbackParam);
}
/*!
* @brief cdc get encapsulated response.
*
* This function implements cdc GET_ENCAPSULATED_RESPONSE request.refer to cdc 1.2 spec.
*
* @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 request 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.
*/
usb_status_t USB_HostCdcGetEncapsulatedResponse(usb_host_class_handle classHandle,
uint8_t *buffer,
uint16_t bufferLength,
transfer_callback_t callbackFn,
void *callbackParam)
{
return USB_HostCdcControl(
classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
USB_HOST_CDC_GET_ENCAPSULATED_RESPONSE, 0, 0, bufferLength, buffer, callbackFn, callbackParam);
}
/*!
* @brief cdc get acm descriptor.
*
* This function is hunting for class specific acm decriptor in the configuration ,get the corresponding
* descriptor .
*
* @param classHandle the class handle.
* @param headDesc the head function descriptor pointer.
* @param callManageDesc the call management functional descriptor pointer.
* @param abstractControlDesc the abstract control management functional pointer.
* @param unionInterfaceDesc the union functional descriptor pointer.
*
* @retval kStatus_USB_Error analyse descriptor error.
*/
usb_status_t USB_HostCdcGetAcmDescriptor(usb_host_class_handle classHandle,
usb_host_cdc_head_function_desc_struct_t **headDesc,
usb_host_cdc_call_manage_desc_struct_t **callManageDesc,
usb_host_cdc_abstract_control_desc_struct_t **abstractControlDesc,
usb_host_cdc_union_interface_desc_struct_t **unionInterfaceDesc)
{
usb_status_t status;
usb_descriptor_union_t *ptr1;
uint32_t end_address;
usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
usb_cdc_func_desc_struct_t *cdc_common_ptr;
usb_host_interface_t *interface_handle;
void *temp;
status = kStatus_USB_Success;
interface_handle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
temp = (void *)interface_handle->interfaceExtension;
ptr1 = (usb_descriptor_union_t *)temp;
end_address = (uint32_t)(interface_handle->interfaceExtension + interface_handle->interfaceExtensionLength);
while ((uint32_t)ptr1 < end_address)
{
temp = (void *)&ptr1->common;
cdc_common_ptr = (usb_cdc_func_desc_struct_t *)temp;
switch (cdc_common_ptr->common.bDescriptorSubtype)
{
case USB_HOST_DESC_SUBTYPE_HEADER:
*headDesc = &cdc_common_ptr->head;
if ((((uint32_t)((*headDesc)->bcdCDC[1U]) << 8U) + (*headDesc)->bcdCDC[0U]) > 0x0110U)
{
status = kStatus_USB_Error;
}
break;
case USB_HOST_DESC_SUBTYPE_UNION:
if (cdc_common_ptr->unionDesc.bControlInterface == interface_handle->interfaceDesc->bInterfaceNumber)
{
*unionInterfaceDesc = &cdc_common_ptr->unionDesc;
}
else
{
status = kStatus_USB_Error;
}
break;
case USB_HOST_DESC_SUBTYPE_CM:
*callManageDesc = &cdc_common_ptr->callManage;
break;
case USB_HOST_DESC_SUBTYPE_ACM:
*abstractControlDesc = &cdc_common_ptr->acm;
break;
default:
/*no action*/
break;
}
if (kStatus_USB_Success != status)
{
break;
}
temp = (void *)((uint8_t *)ptr1 + ptr1->common.bLength);
ptr1 = (usb_descriptor_union_t *)temp;
}
cdcInstance->headDesc = *headDesc;
cdcInstance->callManageDesc = *callManageDesc;
cdcInstance->abstractControlDesc = *abstractControlDesc;
cdcInstance->unionInterfaceDesc = *unionInterfaceDesc;
return status;
}
#endif