summaryrefslogtreecommitdiff
path: root/usb_1.1.0/host/class
diff options
context:
space:
mode:
Diffstat (limited to 'usb_1.1.0/host/class')
-rw-r--r--usb_1.1.0/host/class/usb_host_audio.c1051
-rw-r--r--usb_1.1.0/host/class/usb_host_audio.h549
-rw-r--r--usb_1.1.0/host/class/usb_host_cdc.c1200
-rw-r--r--usb_1.1.0/host/class/usb_host_cdc.h518
-rw-r--r--usb_1.1.0/host/class/usb_host_hid.c804
-rw-r--r--usb_1.1.0/host/class/usb_host_hid.h411
-rw-r--r--usb_1.1.0/host/class/usb_host_hub.c612
-rw-r--r--usb_1.1.0/host/class/usb_host_hub.h390
-rw-r--r--usb_1.1.0/host/class/usb_host_hub_app.c1106
-rw-r--r--usb_1.1.0/host/class/usb_host_hub_app.h103
-rw-r--r--usb_1.1.0/host/class/usb_host_msd.c1155
-rw-r--r--usb_1.1.0/host/class/usb_host_msd.h872
-rw-r--r--usb_1.1.0/host/class/usb_host_msd_ufi.c473
-rw-r--r--usb_1.1.0/host/class/usb_host_phdc.c1272
-rw-r--r--usb_1.1.0/host/class/usb_host_phdc.h329
-rw-r--r--usb_1.1.0/host/class/usb_host_printer.c775
-rw-r--r--usb_1.1.0/host/class/usb_host_printer.h301
17 files changed, 11921 insertions, 0 deletions
diff --git a/usb_1.1.0/host/class/usb_host_audio.c b/usb_1.1.0/host/class/usb_host_audio.c
new file mode 100644
index 0000000..798d7ef
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_audio.c
@@ -0,0 +1,1051 @@
+/*
+ * 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_AUDIO) && (USB_HOST_CONFIG_AUDIO))
+#include "usb_host.h"
+#include "usb_host_audio.h"
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/* usb audio feature uint command request declaration */
+static usb_audio_request_t s_usbAudioFuRequests[NUMBER_OF_FEATURE_COMMANDS] = {
+ /* Mute command request */
+ {AUDIO_FU_MUTE_MASK, ITF_REQUEST, CUR_REQUEST, AUDIO_FU_MUTE, 1U},
+ /* Volume command request */
+ {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, CUR_REQUEST, AUDIO_FU_VOLUME, 2U},
+ {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, MIN_REQUEST, AUDIO_FU_VOLUME, 2U},
+ {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, MAX_REQUEST, AUDIO_FU_VOLUME, 2U},
+ {AUDIO_FU_VOLUME_MASK, ITF_REQUEST, RES_REQUEST, AUDIO_FU_VOLUME, 2U},
+};
+/* USB audio endpoint command declaration */
+static usb_audio_request_t s_usbAudioEpRequests[NUMBER_OF_ENDPOINT_COMMANDS] = {
+ /* USB audio Pitch command request */
+ {AUDIO_PITCH_MASK, EP_REQUEST, CUR_REQUEST, AUDIO_PITCH_CONTROL, 1U},
+
+ /* USB audio Sampling frequency command request */
+ {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, CUR_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
+ {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, MIN_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
+ {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, MAX_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
+ {AUDIO_SAMPLING_FREQ_MASK, EP_REQUEST, RES_REQUEST, AUDIO_SAMPLING_FREQ_CONTROL, 3U},
+};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/*!
+ * @brief initialize the audio instance.
+ *
+ * This function allocate the resource for audio instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandlePtr return class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+usb_status_t USB_HostAudioInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandlePtr)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)USB_OsaMemoryAllocate(sizeof(audio_instance_t));
+ uint32_t info_value;
+
+ if (audioPtr == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ audioPtr->deviceHandle = deviceHandle;
+ audioPtr->controlIntfHandle = NULL;
+ audioPtr->streamIntfHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &info_value);
+ audioPtr->hostHandle = (usb_host_handle)info_value;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &info_value);
+ audioPtr->controlPipe = (usb_host_pipe_handle)info_value;
+
+ *classHandlePtr = audioPtr;
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief de-initialize the audio instance.
+ *
+ * This function release the resource for audio 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_HostAudioDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
+{
+ usb_status_t status;
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (classHandle != NULL)
+ {
+ if (audioPtr->isoInPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoInPipe, NULL);
+ status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoInPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ audioPtr->isoInPipe = NULL;
+ }
+ if (audioPtr->isoOutPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoOutPipe, NULL);
+ status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ audioPtr->isoOutPipe = NULL;
+ }
+ USB_HostCloseDeviceInterface(deviceHandle, audioPtr->streamIntfHandle);
+
+ if ((audioPtr->controlPipe != NULL) && (audioPtr->controlTransfer != NULL))
+ {
+ status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->controlPipe, audioPtr->controlTransfer);
+ }
+ USB_HostCloseDeviceInterface(deviceHandle, audioPtr->controlIntfHandle);
+ USB_OsaMemoryFree(audioPtr);
+ }
+ else
+ {
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief audiostream iso in pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void _USB_HostAudioStreamIsoInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)param;
+
+ if (audioPtr->inCallbackFn != NULL)
+ {
+ audioPtr->inCallbackFn(audioPtr->inCallbackParam, transfer->transferBuffer, transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+}
+
+/*!
+ * @brief audiostream iso out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void _USB_HostAudioStreamIsoOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)param;
+
+ if (audioPtr->outCallbackFn != NULL)
+ {
+ audioPtr->outCallbackFn(audioPtr->outCallbackParam, transfer->transferBuffer, transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+}
+
+/*!
+ * @brief audiocontrol pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void _USB_HostAudioControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)param;
+
+ audioPtr->controlTransfer = NULL;
+ if (audioPtr->controlCallbackFn != NULL)
+ {
+ audioPtr->controlCallbackFn(audioPtr->controlCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status);
+ }
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ audioPtr->isSetup = 0U;
+}
+
+/*!
+ * @brief hid send control transfer common code.
+ *
+ * @param classHandle the class handle.
+ * @param typeRequest setup packet request type.
+ * @param request setup packet request value.
+ * @param wvalue setup packet wvalue value.
+ * @param windex setup packet index value.
+ * @param wlength setup packet wlength value.
+ * @param data data buffer pointer will be transfer.
+ * @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.
+ */
+static usb_status_t _USB_HostAudioControl(usb_host_class_handle classHandle,
+ uint8_t typeRequest,
+ uint8_t request,
+ uint16_t wvalue,
+ uint16_t windex,
+ uint16_t wlength,
+ uint8_t *data,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ audioPtr->controlCallbackFn = callbackFn;
+ audioPtr->controlCallbackParam = callbackParam;
+
+ transfer->transferBuffer = data;
+ transfer->transferLength = wlength;
+ transfer->callbackFn = _USB_HostAudioControlCallback;
+ transfer->callbackParam = audioPtr;
+ transfer->setupPacket.bmRequestType = typeRequest;
+ transfer->setupPacket.bRequest = request;
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(windex);
+
+ transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
+ audioPtr->isSetup = 1;
+
+ if (USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt for USB_HostSendSetup\r\n");
+#endif
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ audioPtr->controlTransfer = transfer;
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief audio open interface.
+ *
+ * @param audioPtr audio instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t _USB_HostAudioOpenInterface(audio_instance_t *audioPtr)
+{
+ usb_status_t status;
+ uint8_t ep_index = 0U;
+ usb_host_pipe_init_t pipe_init;
+ usb_descriptor_endpoint_t *ep_desc = NULL;
+ usb_host_interface_t *interface_ptr;
+
+ if (audioPtr->isoInPipe != NULL)
+ {
+ status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoInPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ audioPtr->isoInPipe = NULL;
+ }
+ if (audioPtr->isoOutPipe != NULL)
+ {
+ status = USB_HostClosePipe(audioPtr->hostHandle, audioPtr->isoOutPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ audioPtr->isoOutPipe = NULL;
+ }
+
+ /* open interface pipes */
+ interface_ptr = (usb_host_interface_t *)audioPtr->streamIntfHandle;
+ for (ep_index = 0U; ep_index < interface_ptr->epCount; ++ep_index)
+ {
+ ep_desc = interface_ptr->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_ISOCHRONOUS))
+ {
+ pipe_init.devInstance = audioPtr->deviceHandle;
+ pipe_init.pipeType = USB_ENDPOINT_ISOCHRONOUS;
+ pipe_init.direction = USB_IN;
+ pipe_init.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipe_init.interval = ep_desc->bInterval;
+ pipe_init.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipe_init.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipe_init.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ audioPtr->inPacketSize = pipe_init.maxPacketSize;
+ audioPtr->isoEpNum = pipe_init.endpointAddress;
+ status = USB_HostOpenPipe(audioPtr->hostHandle, &audioPtr->isoInPipe, &pipe_init);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_host_audio_stream_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_ISOCHRONOUS))
+ {
+ pipe_init.devInstance = audioPtr->deviceHandle;
+ pipe_init.pipeType = USB_ENDPOINT_ISOCHRONOUS;
+ pipe_init.direction = USB_OUT;
+ pipe_init.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipe_init.interval = ep_desc->bInterval;
+ pipe_init.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipe_init.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipe_init.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ audioPtr->outPacketSize = pipe_init.maxPacketSize;
+ audioPtr->isoEpNum = pipe_init.endpointAddress;
+ status = USB_HostOpenPipe(audioPtr->hostHandle, &audioPtr->isoOutPipe, &pipe_init);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_host_audio_stream_set_interface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ }
+ else
+ {
+ return kStatus_USB_Error;
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief audio set interface callback, open pipes.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void _USB_HostAudioSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)param;
+
+ audioPtr->controlTransfer = NULL;
+ if (status == kStatus_USB_Success)
+ {
+ status = _USB_HostAudioOpenInterface(audioPtr);
+ }
+
+ if (audioPtr->controlCallbackFn != NULL)
+ {
+ audioPtr->controlCallbackFn(audioPtr->controlCallbackParam, NULL, 0U, status);
+ }
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+}
+
+/*!
+ * @brief set audioclass stream interface.
+ *
+ * This function bind the interface with the audio 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_HostAudioStreamSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_status_t status;
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ usb_host_interface_t *interface_ptr;
+ usb_host_transfer_t *transfer;
+ audio_descriptor_union_t ptr1;
+ uint32_t length = 0U, ep = 0U;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ audioPtr->streamIntfHandle = interfaceHandle;
+
+ status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+
+ if (audioPtr->isoInPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoInPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+
+ if (audioPtr->isoOutPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(audioPtr->hostHandle, audioPtr->isoOutPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+ /* open interface pipes */
+ interface_ptr = (usb_host_interface_t *)interfaceHandle;
+ ptr1.bufr = interface_ptr->interfaceExtension;
+
+ length = 0U;
+ while (length < interface_ptr->interfaceExtensionLength)
+ {
+ if ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting))
+ {
+ interface_ptr->epCount = ptr1.interface->bNumEndpoints;
+ break;
+ }
+ ptr1.bufr += ptr1.common->bLength;
+ length += ptr1.common->bLength;
+ }
+ while (ep < interface_ptr->epCount)
+ {
+ if (ptr1.common->bDescriptorType == 0x24U)
+ {
+ if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AS_CS_GENERAL)
+ {
+ audioPtr->asIntfDesc = (usb_audio_stream_spepific_as_intf_desc_t *)ptr1.bufr;
+ }
+ else if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AS_CS_FORMAT_TYPE)
+ {
+ audioPtr->formatTypeDesc = (usb_audio_stream_format_type_desc_t *)ptr1.bufr;
+ }
+ else
+ {
+ }
+ }
+ if (ptr1.common->bDescriptorType == 0x05U)
+ {
+ interface_ptr->epList[ep].epDesc = (usb_descriptor_endpoint_t *)ptr1.bufr;
+ audioPtr->isoEndpDesc = (usb_audio_stream_specific_iso_endp_desc_t *)ptr1.bufr;
+ ep++;
+ ptr1.bufr += ptr1.common->bLength;
+ interface_ptr->epList[ep].epExtension = ptr1.bufr;
+ interface_ptr->epList[ep].epExtensionLength = ptr1.common->bLength;
+ break;
+ }
+ ptr1.bufr += ptr1.common->bLength;
+ }
+
+ if (alternateSetting == 0U)
+ {
+ if (callbackFn != NULL)
+ {
+ status = _USB_HostAudioOpenInterface(audioPtr);
+ callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
+ }
+ }
+ else
+ {
+ if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ audioPtr->controlCallbackFn = callbackFn;
+ audioPtr->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->callbackFn = _USB_HostAudioSetInterfaceCallback;
+ transfer->callbackParam = audioPtr;
+ 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 *)audioPtr->streamIntfHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
+ transfer->setupPacket.wLength = 0;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ status = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ audioPtr->controlTransfer = transfer;
+ }
+ else
+ {
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ }
+ }
+
+ return status;
+}
+
+/*!
+ * @brief set audioclass control interface.
+ *
+ * This function bind the interface with the audio 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_HostAudioControlSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_status_t status;
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ usb_host_interface_t *interface_ptr;
+ usb_host_transfer_t *transfer;
+ audio_descriptor_union_t ptr1;
+ uint32_t length = 0U;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+ audioPtr->controlIntfHandle = interfaceHandle;
+ interface_ptr = (usb_host_interface_t *)interfaceHandle;
+
+ status = USB_HostOpenDeviceInterface(audioPtr->deviceHandle, interfaceHandle);
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+ ptr1.bufr = interface_ptr->interfaceExtension;
+
+ length = 0U;
+
+ while (length < interface_ptr->interfaceExtensionLength)
+ {
+ if (((interface_ptr->interfaceDesc->bDescriptorType == 0x04U) &&
+ (interface_ptr->interfaceDesc->bAlternateSetting == alternateSetting)) ||
+ ((ptr1.common->bDescriptorType == 0x04U) && (ptr1.interface->bAlternateSetting == alternateSetting)))
+ {
+ break;
+ }
+
+ ptr1.bufr += ptr1.common->bLength;
+ length += ptr1.common->bLength;
+ }
+ while (length < interface_ptr->interfaceExtensionLength)
+ {
+ if (ptr1.common->bDescriptorType == 0x24U)
+ {
+ if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AUDIO_CS_HEADER)
+ {
+ audioPtr->headerDesc = (usb_audio_ctrl_header_desc_t *)ptr1.bufr;
+ }
+ else if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AUDIO_CS_IT)
+ {
+ audioPtr->itDesc = (usb_audio_ctrl_it_desc_t *)ptr1.bufr;
+ }
+ else if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AUDIO_CS_OT)
+ {
+ audioPtr->otDesc = (usb_audio_ctrl_ot_desc_t *)ptr1.bufr;
+ }
+ else if (ptr1.common->bData[0] == USB_DESC_SUBTYPE_AUDIO_CS_FU)
+ {
+ audioPtr->fuDesc = (usb_audio_ctrl_fu_desc_t *)ptr1.bufr;
+ }
+ else
+ {
+ }
+ }
+ ptr1.bufr += ptr1.common->bLength;
+ length += ptr1.common->bLength;
+ }
+
+ if (alternateSetting == 0U)
+ {
+ if (callbackFn != NULL)
+ {
+ callbackFn(callbackParam, NULL, 0U, kStatus_USB_Success);
+ }
+ }
+ else
+ {
+ if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ audioPtr->controlCallbackFn = callbackFn;
+ audioPtr->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->callbackFn = _USB_HostAudioControlCallback;
+ transfer->callbackParam = audioPtr;
+ 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 *)audioPtr->controlIntfHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
+ transfer->setupPacket.wLength = 0;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ status = USB_HostSendSetup(audioPtr->hostHandle, audioPtr->controlPipe, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ audioPtr->controlTransfer = transfer;
+ }
+ else
+ {
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ }
+ }
+
+ return status;
+}
+
+/*!
+ * @brief get pipe max packet size.
+ *
+ * @param classHandle the class handle.
+ * @param 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 direction pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval max packet size.
+ */
+uint16_t USB_HostAudioPacketSize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (pipeType == USB_ENDPOINT_ISOCHRONOUS)
+ {
+ if (direction == USB_IN)
+ {
+ return audioPtr->inPacketSize;
+ }
+ else
+ {
+ return audioPtr->outPacketSize;
+ }
+ }
+ return 0U;
+}
+
+/*!
+ * @brief audio stream receive data.
+ *
+ * This function implements audioreceiving data.
+ *
+ * @param classHandle The class handle.
+ * @param buffer The buffer pointer.
+ * @param bufferLen 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_HostAudioStreamRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLen,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (audioPtr->isoInPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ audioPtr->inCallbackFn = callbackFn;
+ audioPtr->inCallbackParam = callbackParam;
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLen;
+ transfer->callbackFn = _USB_HostAudioStreamIsoInPipeCallback;
+ transfer->callbackParam = audioPtr;
+
+ if (USB_HostRecv(audioPtr->hostHandle, audioPtr->isoInPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt to USB_HostRecv\r\n");
+#endif
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief audio stream send data.
+ *
+ * This function implements audio sending data.
+ *
+ * @param classHandle The class handle.
+ * @param buffer The buffer pointer.
+ * @param bufferLen 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_HostAudioStreamSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLen,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (audioPtr->isoOutPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ if (USB_HostMallocTransfer(audioPtr->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ audioPtr->outCallbackFn = callbackFn;
+ audioPtr->outCallbackParam = callbackParam;
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLen;
+ transfer->callbackFn = _USB_HostAudioStreamIsoOutPipeCallback;
+ transfer->callbackParam = audioPtr;
+
+ if (USB_HostSend(audioPtr->hostHandle, audioPtr->isoOutPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt to USB_HostSend\r\n");
+#endif
+ USB_HostFreeTransfer(audioPtr->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief get audio stream current altsetting descriptor.
+ *
+ * This function implements get audio stream current altsetting descriptor.
+ *
+ * @param classHandle The class handle.
+ * @param asIntfDesc The pointer of class specific AS interface descriptor.
+ * @param formatTypeDesc The pointer of format type descriptor.
+ * @param isoEndpDesc The pointer of specific iso endp descriptor.
+ *
+ * @retval kStatus_USB_Success Get audio stream current altsetting descriptor request successfully.
+ * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
+ *
+ */
+usb_status_t USB_HostAudioStreamGetCurrentAltsettingDescriptors(
+
+ usb_host_class_handle classHandle,
+ usb_audio_stream_spepific_as_intf_desc_t **asIntfDesc,
+ usb_audio_stream_format_type_desc_t **formatTypeDesc,
+ usb_audio_stream_specific_iso_endp_desc_t **isoEndpDesc)
+{
+ audio_instance_t *audioPtr = (audio_instance_t *)classHandle;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ *asIntfDesc = audioPtr->asIntfDesc;
+ *formatTypeDesc = audioPtr->formatTypeDesc;
+ *isoEndpDesc = audioPtr->isoEndpDesc;
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief usb audio feature unit request.
+ *
+ * This function implements usb audio feature unit request.
+ *
+ * @param classHandle The class handle.
+ * @param channelNo The channel number of audio feature unit.
+ * @param buf The feature unit request buffer pointer.
+ * @param cmdCode The feature unit command code, for example USB_AUDIO_GET_CUR_MUTE etc.
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Feature unit 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_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,
+ uint8_t channelNo,
+ void *buf,
+ uint32_t cmdCode,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{ /* Body */
+ uint16_t windex;
+ uint16_t request_value;
+ audio_instance_t *if_ptr;
+ usb_audio_request_t *p_feature_request;
+ uint8_t *bmacontrols = NULL;
+ uint8_t atribute_index;
+ usb_status_t status = kStatus_USB_Error;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if_ptr = (audio_instance_t *)classHandle;
+
+ /* pointer to command */
+ p_feature_request = &(s_usbAudioFuRequests[cmdCode & 0xfU]);
+ /* get request value */
+ request_value = (uint16_t)((uint16_t)((uint16_t)p_feature_request->requestValue << 8U) | channelNo);
+
+ /* Check whether this attribute valid or not */
+ if (if_ptr->fuDesc == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+ windex = (uint16_t)((uint16_t)((uint16_t)(if_ptr->fuDesc->bunitid) << 8U) | (if_ptr->streamIfnum));
+ atribute_index = if_ptr->fuDesc->bcontrolsize * channelNo;
+
+ if (atribute_index < (if_ptr->fuDesc->blength - 7))
+ {
+ bmacontrols = &(if_ptr->fuDesc->bcontrolsize);
+ }
+
+ if (bmacontrols == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ bmacontrols++;
+ if (bmacontrols[atribute_index] & p_feature_request->controlMask)
+ {
+ status = kStatus_USB_Success;
+ }
+
+ if (kStatus_USB_Success == status)
+ {
+ status = _USB_HostAudioControl(classHandle, (p_feature_request->typeRequest | (cmdCode & 0x80U)),
+ (p_feature_request->codeRequest | (cmdCode & 0x80U)), request_value, windex,
+ p_feature_request->length, (uint8_t *)buf, callbackFn, callbackParam);
+ }
+ return status;
+}
+
+/*!
+ * @brief usb audio endpoint request.
+ *
+ * This function implements usb audio endpoint request.
+ *
+ * @param classHandle The class handle.
+ * @param buf The feature unit buffer pointer.
+ * @param cmdCode The feature unit command code, for example USB_AUDIO_GET_CUR_PITCH etc .
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Endpoint 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_HostAudioEndpointRequest(
+ usb_host_class_handle classHandle, void *buf, uint32_t cmdCode, transfer_callback_t callbackFn, void *callbackParam)
+{
+ uint8_t endp_num;
+ usb_status_t status = kStatus_USB_Error;
+ uint16_t request_value;
+ usb_audio_request_t *p_endpoint_request;
+ audio_instance_t *audioPtr;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ audioPtr = (audio_instance_t *)classHandle;
+
+ /* pointer to command */
+ p_endpoint_request = &(s_usbAudioEpRequests[cmdCode & 0xfU]);
+ /* get request value */
+ request_value = (uint16_t)((uint16_t)((uint16_t)p_endpoint_request->requestValue << 8U));
+
+ /* Check whether this attribute valid or not */
+ if (audioPtr->isoEndpDesc == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+ if ((audioPtr->isoEndpDesc->bmattributes) && (p_endpoint_request->controlMask))
+ {
+ status = kStatus_USB_Success;
+ }
+ else
+ {
+ status = kStatus_USB_InvalidRequest;
+ }
+
+ if (kStatus_USB_Success == status)
+ {
+ /* Any isochronous pipe is supported? */
+ if ((NULL == audioPtr->isoInPipe) && (NULL == audioPtr->isoOutPipe))
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+ else if (NULL != audioPtr->isoInPipe)
+ {
+ endp_num = (audioPtr->isoEpNum | 0x80U);
+ }
+ else
+ {
+ endp_num = audioPtr->isoEpNum;
+ } /* Endif */
+
+ status = _USB_HostAudioControl(classHandle, (p_endpoint_request->typeRequest | (cmdCode & 0x80U)),
+ (p_endpoint_request->codeRequest | (cmdCode & 0x80U)), request_value, endp_num,
+ p_endpoint_request->length, (uint8_t *)buf, callbackFn, callbackParam);
+ }
+
+ return status;
+}
+#endif /* USB_HOST_CONFIG_AUDIO */
diff --git a/usb_1.1.0/host/class/usb_host_audio.h b/usb_1.1.0/host/class/usb_host_audio.h
new file mode 100644
index 0000000..e6728fd
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_audio.h
@@ -0,0 +1,549 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef __USB_HOST_AUDIO_H__
+#define __USB_HOST_AUDIO_H__
+
+/*******************************************************************************
+ * Audio class private structure, enumerations, macros
+ ******************************************************************************/
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/* Structure for an AUDIO class descriptor according to the 6.2.1 in Audio specification*/
+#define AUDIO_FU_MUTE 0x01
+#define AUDIO_FU_VOLUME 0x02
+#define AUDIO_FU_BASS 0x03
+#define AUDIO_FU_MID 0x04
+#define AUDIO_FU_TREBLE 0x05
+#define AUDIO_FU_GRAPHIC_EQ 0x06
+#define AUDIO_FU_AGC 0x07
+#define AUDIO_FU_DELAY 0x08
+#define AUDIO_FU_BASS_BOOST 0x09
+
+/* Audio class codes */
+#define SET_COMMAND (0x00)
+#define GET_COMMAND (0x80)
+#define CUR_REQUEST (0x01)
+#define MIN_REQUEST (0x02)
+#define MAX_REQUEST (0x03)
+#define RES_REQUEST (0x04)
+#define MEM_REQUEST (0x05)
+#define GET_STATUS (0xFF)
+
+#define ITF_REQUEST (0x21)
+#define EP_REQUEST (0x22)
+
+#define AUDIO_FU_MUTE_MASK 0x01
+#define AUDIO_FU_VOLUME_MASK 0x02
+#define AUDIO_FU_BASS_MASK 0x04
+#define AUDIO_FU_MID_MASK 0x08
+#define AUDIO_FU_TREBLE_MASK 0x10
+#define AUDIO_FU_GRAPHIC_EQ_MASK 0x20
+#define AUDIO_FU_AGC_MASK 0x40
+#define AUDIO_FU_DELAY_MASK 0x80
+#define AUDIO_FU_BASS_BOOST_MASK 0x01
+
+/* USB audio Endpoint Control Selectors */
+#define AUDIO_EP_CONTROL_UNDEFINED (0x00)
+#define AUDIO_SAMPLING_FREQ_CONTROL (0x01)
+#define AUDIO_PITCH_CONTROL (0x02)
+
+#define AUDIO_SAMPLING_FREQ_MASK (0x01)
+#define AUDIO_PITCH_MASK (0x02)
+typedef enum _fu_request_code
+{
+ kUSB_AudioCurMute = 0,
+ kUSB_AudioCurVolume,
+ kUSB_AudioMinVolume,
+ kUSB_AudioMaxVolume,
+ kUSB_AudioResVolume,
+ NUMBER_OF_FEATURE_COMMANDS,
+} fu_request_code_t;
+
+typedef enum _ep_request_code
+{
+ kUSB_AudioCurPitch = 0,
+ kUSB_AudioCurSamplingFreq,
+ kUSB_AudioMinSamplingFreq,
+ kUSB_AudioMaxSamplingFreq,
+ kUSB_AudioResSamplingFreq,
+ NUMBER_OF_ENDPOINT_COMMANDS,
+} ep_request_code_t;
+
+typedef union _audio_descriptor_union
+{
+ uint8_t *bufr;
+ usb_descriptor_common_t *common;
+ usb_descriptor_device_t *device;
+ usb_descriptor_configuration_t *configuration;
+ usb_descriptor_interface_t *interface;
+ usb_descriptor_endpoint_t *endpoint;
+} audio_descriptor_union_t;
+
+/* Audio command structure */
+typedef struct _usb_audio_request
+{
+ uint8_t controlMask;
+ uint8_t typeRequest;
+ uint8_t codeRequest;
+ uint8_t requestValue;
+ uint8_t length;
+} usb_audio_request_t;
+
+#define USB_DESC_SUBTYPE_AUDIO_CS_HEADER 0x01
+#define USB_DESC_SUBTYPE_AUDIO_CS_IT 0x02
+#define USB_DESC_SUBTYPE_AUDIO_CS_OT 0x03
+#define USB_DESC_SUBTYPE_AUDIO_CS_FU 0x06
+#define USB_DESC_CLASS_ENDPOINT_GENERAL 0x01
+#define USB_DESC_SUBTYPE_AS_CS_GENERAL 0X01
+#define USB_DESC_SUBTYPE_AS_CS_FORMAT_TYPE 0X02
+
+/*******************************************************************************
+ * Audio class public structure, enumeration, macros, functions
+ ******************************************************************************/
+/*!
+ * @addtogroup usb_host_audio_drv
+ * @{
+ */
+/*! @brief Audio class code */
+#define USB_AUDIO_CLASS_CODE 1
+/*! @brief Audio class control interface code*/
+#define USB_AUDIO_SUBCLASS_CODE_CONTROL 1
+/*! @brief Audio class stream interface code*/
+#define USB_AUDIO_SUBCLASS_CODE_AUDIOSTREAMING 2
+
+/*! @brief AUDIO class-specific feature unit get current mute command*/
+#define USB_AUDIO_GET_CUR_MUTE 0x80
+/*! @brief AUDIO class-specific feature unit set current mute command*/
+#define USB_AUDIO_SET_CUR_MUTE 0x00
+/*! @brief AUDIO class-specific feature unit get current volume command*/
+#define USB_AUDIO_GET_CUR_VOLUME 0x81
+/*! @brief AUDIO class-specific feature unit set current volume command*/
+#define USB_AUDIO_SET_CUR_VOLUME 0x01
+/*! @brief AUDIO class-specific feature unit get minimum volume command*/
+#define USB_AUDIO_GET_MIN_VOLUME 0x82
+/*! @brief AUDIO class-specific feature unit set minimum volume command*/
+#define USB_AUDIO_SET_MIN_VOLUME 0x02
+/*! @brief AUDIO class-specific feature unit get maximum volume command*/
+#define USB_AUDIO_GET_MAX_VOLUME 0x83
+/*! @brief AUDIO class-specific feature unit set maximum volume command*/
+#define USB_AUDIO_SET_MAX_VOLUME 0x03
+/*! @brief AUDIO class-specific feature unit get resolution volume command*/
+#define USB_AUDIO_GET_RES_VOLUME 0x84
+/*! @brief AUDIO class-specific feature unit set resolution volume command*/
+#define USB_AUDIO_SET_RES_VOLUME 0x04
+
+/*! @brief AUDIO class-specific endpoint get current pitch control command*/
+#define USB_AUDIO_GET_CUR_PITCH 0x80
+/*! @brief AUDIO class-specific endpoint set current pitch control command*/
+#define USB_AUDIO_SET_CUR_PITCH 0x00
+/*! @brief AUDIO class-specific endpoint get current sampling frequency command*/
+#define USB_AUDIO_GET_CUR_SAMPLING_FREQ 0x81
+/*! @brief AUDIO class-specific endpoint set current sampling frequency command*/
+#define USB_AUDIO_SET_CUR_SAMPLING_FREQ 0x01
+/*! @brief AUDIO class-specific endpoint get minimum sampling frequency command*/
+#define USB_AUDIO_GET_MIN_SAMPLING_FREQ 0x82
+/*! @brief AUDIO class-specific endpoint set minimum sampling frequency command*/
+#define USB_AUDIO_SET_MIN_SAMPLING_FREQ 0x02
+/*! @brief AUDIO class-specific endpoint get maximum sampling frequency command*/
+#define USB_AUDIO_GET_MAX_SAMPLING_FREQ 0x83
+/*! @brief AUDIO class-specific endpoint set maximum sampling frequency command*/
+#define USB_AUDIO_SET_MAX_SAMPLING_FREQ 0x03
+/*! @brief AUDIO class-specific endpoint get resolution sampling frequency command*/
+#define USB_AUDIO_GET_RES_SAMPLING_FREQ 0x84
+/*! @brief AUDIO class-specific endpoint set resolution sampling frequency command*/
+#define USB_AUDIO_SET_RES_SAMPLING_FREQ 0x04
+
+/*! @brief Audio control interface header descriptor structure */
+typedef struct _usb_audio_ctrl_header_desc
+{
+ uint8_t blength; /*!< Total size of the header descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of audio header descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of an audio header descriptor*/
+ uint8_t bcdcdc[2]; /*!< Audio Device Class Specification Release Number in Binary-Coded Decimal*/
+ uint8_t wtotallength[2]; /*!< Total number of bytes returned for the class-specific AudioControl interface
+ descriptor. Includes the combined length of this descriptor header and all unit and
+ terminal descriptors.*/
+ uint8_t bincollection; /*!< The number of AudioStreaming and MIDIStreaming interfaces in the Audio Interface
+ Collection to which this AudioControl interface belongs to*/
+} usb_audio_ctrl_header_desc_t;
+
+/*! @brief Audio control interface input terminal descriptor structure */
+typedef struct _usb_audio_ctrl_it_desc
+{
+ uint8_t blength; /*!< Total size of the input terminal descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of audio input terminal descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of audio input terminal descriptor*/
+ uint8_t bterminalid; /*!< Constant uniquely identifying the Terminal within the audio function. This value is used
+ in all requests to address this Terminal*/
+ uint8_t wterminaltype[2]; /*!< Constant characterizing the type of Terminal*/
+ uint8_t bassocterminal; /*!< ID of the Output Terminal to which this Input Terminal is associated*/
+ uint8_t bnrchannels; /*!< Number of logical output channels in the Terminal's output audio channel cluster*/
+ uint8_t wchannelconfig[2]; /*!< Describes the spatial location of the logical channels.*/
+ uint8_t ichannelnames; /*!< Index of a string descriptor, describing the name of the first logical channel*/
+ uint8_t iterminal; /*!<Index of a string descriptor, describing the Input Terminal*/
+} usb_audio_ctrl_it_desc_t;
+
+/*! @brief Audio control interface output terminal descriptor structure */
+typedef struct _usb_audio_ctrl_ot_desc
+{
+ uint8_t blength; /*!< Total size of the output terminal descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of audio output terminal descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of audio output terminal descriptor*/
+ uint8_t bterminalid; /*!< Constant uniquely identifying the Terminal within the audio function. This value is used
+ in all requests to address this Terminal*/
+ uint8_t wterminaltype[2]; /*!< Constant characterizing the type of Terminal*/
+ uint8_t bassocterminal; /*!< Constant, identifying the Input Terminal to which this Output Terminal is associated*/
+ uint8_t bsourceid; /*!< ID of the Unit or Terminal to which this Terminal is connected*/
+ uint8_t iterminal; /*!< Index of a string descriptor, describing the Output Terminal*/
+} usb_audio_ctrl_ot_desc_t;
+
+/*! @brief Audio control interface feature unit descriptor structure */
+typedef struct _usb_audio_ctrl_fu_desc
+{
+ uint8_t blength; /*!< Total size of the output terminal descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of audio output terminal descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of audio output terminal descriptor*/
+ uint8_t bunitid; /*!< Constant uniquely identifying the unit within the audio function. This value is used in all
+ requests to address this unit*/
+ uint8_t bsourceid; /*!< ID of the Unit or Terminal to which this Feature Unit is connected*/
+ uint8_t bcontrolsize; /*!< Size in bytes of an element of the bmaControls*/
+} usb_audio_ctrl_fu_desc_t;
+
+/*! @brief Audio as isochronous audio data endpoint descriptor structure */
+typedef struct _usb_audio_stream_specific_iso_endp_desc
+{
+ uint8_t blength; /*!< Total size of the descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of the descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of the descriptor*/
+ uint8_t bmattributes; /*!< A bit in the range D6..0 set to 1 indicates that the mentioned Control is supported by
+ this endpoint*/
+ uint8_t blockdlayunits; /*!< Indicates the units used for the wLockDelay field*/
+ uint8_t wlockdelay[2]; /*!< Indicates the time it takes this endpoint to reliably lock its internal clock recovery
+ circuitry. Units used depend on the value of the bLockDelayUnits field.*/
+} usb_audio_stream_specific_iso_endp_desc_t;
+
+/*! @brief Audio standard as isochronous synch endpoint descriptor structure */
+typedef struct _usb_audio_stream_synch_endp_desc
+{
+ uint8_t blength; /*!< Total size of the descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of the endpoint descriptor*/
+ uint8_t bendpointaddress; /*!< The address of the endpoint on the USB device described by this descriptor*/
+ uint8_t bmattributes; /*!< D3..2: Synchronization type, D1..0: Transfer type*/
+ uint8_t wmaxpacketsize[2]; /*!< Maximum packet size this endpoint is capable of sending or receiving when this
+ configuration is selected*/
+ uint8_t binterval; /*!< Interval for polling endpoint for data transfers expressed in milliseconds*/
+ uint8_t brefresh; /*!< This field indicates the rate at which an isochronous synchronization pipe provides new
+ synchronization feedback data*/
+ uint8_t bsynchaddress; /*!< Must be reset to zero*/
+} usb_audio_stream_synch_endp_desc_t;
+
+/*! @brief Audio class-specific as interface descriptor structure */
+typedef struct _usb_audio_stream_spepific_as_intf_desc
+{
+ uint8_t blength; /*!< Total size of the descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of the descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of the descriptor*/
+ uint8_t bterminallink; /*!< The Terminal ID of the Terminal to which the endpoint of this interface is connected*/
+ uint8_t bdelay; /*!< Expressed in number of frames*/
+ uint8_t wformattag[2]; /*!< The Audio Data Format that has to be used to communicate with this interface*/
+} usb_audio_stream_spepific_as_intf_desc_t;
+
+/* Format type descriptor */
+/*! @brief audio Format type descriptor structure */
+typedef struct _usb_audio_stream_format_type_desc
+{
+ uint8_t blength; /*!< Total size of the descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor type of the descriptor*/
+ uint8_t bdescriptorsubtype; /*!< Subtype of the descriptor*/
+ uint8_t bformattype; /*!< Constant identifying the Format Type the AudioStreaming interface is using*/
+ uint8_t bnrchannels; /*!< Number of channels of device*/
+ uint8_t bsubframesize; /*!< Bytes per audio subframe*/
+ uint8_t bbitresolution; /*!< Bits per sample*/
+ uint8_t bsamfreqtype; /*!< Frequency supported*/
+ uint8_t tsamfreq[1][3]; /*!< Sample frequency*/
+} usb_audio_stream_format_type_desc_t;
+
+/*! @brief Audio instance structure and audio usb_host_class_handle pointer to this structure */
+typedef struct _audio_instance
+{
+ usb_host_handle hostHandle; /*!< This instance's related host handle*/
+ usb_device_handle deviceHandle; /*!< This instance's related device handle*/
+ usb_host_interface_handle streamIntfHandle; /*!< This instance's audio stream interface handle*/
+ usb_host_interface_handle controlIntfHandle; /*!< This instance's control stream interface handle*/
+ usb_audio_stream_spepific_as_intf_desc_t
+ *asIntfDesc; /*!< Audio class class-specific as interface descriptor pointer*/
+ usb_audio_stream_format_type_desc_t
+ *formatTypeDesc; /*!< Audio class class-specific format type descriptor pointer*/
+ usb_audio_stream_specific_iso_endp_desc_t
+ *isoEndpDesc; /*!< Audio class class-specific ISO audio data endpoint descriptor pointer*/
+ usb_host_pipe_handle isoInPipe; /*!< Audio class ISO in pipe*/
+ usb_host_pipe_handle isoOutPipe; /*!< Audio class ISO out pipe*/
+ transfer_callback_t inCallbackFn; /*!< Audio class ISO in transfer callback function*/
+ void *inCallbackParam; /*!< Audio class ISO in transfer callback parameter*/
+ transfer_callback_t outCallbackFn; /*!< Audio class ISO out transfer callback function*/
+ void *outCallbackParam; /*!< Audio class ISO out transfer callback function*/
+ usb_audio_ctrl_header_desc_t *headerDesc; /*!< Audio class header descriptor pointer*/
+ usb_audio_ctrl_it_desc_t *itDesc; /*!< Audio class input terminal descriptor pointer*/
+ usb_audio_ctrl_ot_desc_t *otDesc; /*!< Audio class output terminal descriptor pointer*/
+ usb_audio_ctrl_fu_desc_t *fuDesc; /*!< Audio class feature unit descriptor pointer*/
+ usb_host_pipe_handle controlPipe; /*!< Audio class device control pipe*/
+ transfer_callback_t controlCallbackFn; /*!< Audio control transfer callback function*/
+ void *controlCallbackParam; /*!< Audio control transfer callback function*/
+ usb_host_transfer_t *controlTransfer; /*!< On-going control transfer*/
+ uint16_t inPacketSize; /*!< Audio ISO in maximum packet size*/
+ uint16_t outPacketSize; /*!< Audio ISO out maximum packet size*/
+ uint8_t isSetup; /*!< Whether the audio setup transfer is transmitting*/
+ uint8_t isoEpNum; /*!< Audio stream ISO endpoint number*/
+ uint8_t streamIfnum; /*!< Audio stream ISO interface number*/
+} audio_instance_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host audio class APIs
+ * @{
+ */
+
+/*!
+ * @brief Initializes the audio instance.
+ *
+ * This function allocates the resource for the audio instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandlePtr Return class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+extern usb_status_t USB_HostAudioInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandlePtr);
+
+/*!
+ * @brief Deinitializes the Audio instance.
+ *
+ * This function release the resource for audio instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is deinitialized successfully.
+ */
+extern usb_status_t USB_HostAudioDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Sets the audio class stream interface.
+ *
+ * This function binds the interface with the audio 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostAudioStreamSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Sets the audio class control interface.
+ *
+ * This function binds the interface with the audio 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostAudioControlSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Gets the pipe maximum packet size.
+ *
+ * @param classHandle The class handle.
+ * @param pipeType Its value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
+ * USB_ENDPOINT_INTERRUPT.
+ * See the usb_spec.h
+ * @param direction Pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval max Packet size.
+ */
+extern uint16_t USB_HostAudioPacketSize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction);
+
+/*!
+ * @brief Audio stream receive data.
+ *
+ * This function implements the audio receiving data.
+ *
+ * @param classHandle The class handle.
+ * @param buffer The buffer pointer.
+ * @param bufferLen 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostAudioStreamRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLen,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Audio stream send data.
+ *
+ * This function implements the audio sending data.
+ *
+ * @param classHandle The class handle.
+ * @param buffer The buffer pointer.
+ * @param bufferLen 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostAudioStreamSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLen,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Gets the audio stream current altsetting descriptor.
+ *
+ * This function implements the get audio stream current altsetting descriptor.
+ *
+ * @param classHandle The class handle.
+ * @param asIntfDesc The pointer of class-specific AS interface descriptor.
+ * @param formatTypeDesc The pointer of format type descriptor.
+ * @param isoEndpDesc The pointer of specific ISO endp descriptor.
+ *
+ * @retval kStatus_USB_Success Get the audio stream current altsetting descriptor request successfully.
+ * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer.
+ *
+ */
+extern usb_status_t USB_HostAudioStreamGetCurrentAltsettingDescriptors(
+ usb_host_class_handle classHandle,
+ usb_audio_stream_spepific_as_intf_desc_t **asIntfDesc,
+ usb_audio_stream_format_type_desc_t **formatTypeDesc,
+ usb_audio_stream_specific_iso_endp_desc_t **isoEndpDesc);
+
+/*!
+ * @brief The USB audio feature unit request.
+ *
+ * This function implements the USB audio feature unit request.
+ *
+ * @param classHandle The class handle.
+ * @param channelNo The channel number of audio feature unit.
+ * @param buf The feature unit request buffer pointer.
+ * @param cmdCode The feature unit command code, for example USB_AUDIO_GET_CUR_MUTE, and so on.
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Feature unit 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. See the USB_HostSendSetup.
+ *
+ */
+extern usb_status_t USB_HostAudioFeatureUnitRequest(usb_host_class_handle classHandle,
+ uint8_t channelNo,
+ void *buf,
+ uint32_t cmdCode,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief The USB audio endpoint request.
+ *
+ * This function implements the USB audio endpoint request.
+ *
+ * @param classHandle The class handle.
+ * @param buf The feature unit buffer pointer.
+ * @param cmdCode The feature unit command code, for example USB_AUDIO_GET_CUR_PITCH, and so on.
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Endpoint 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. See the USB_HostSendSetup.
+ *
+ */
+extern usb_status_t USB_HostAudioEndpointRequest(usb_host_class_handle classHandle,
+ void *buf,
+ uint32_t cmdCode,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*! @}*/
+#ifdef __cplusplus
+}
+#endif
+/*! @}*/
+#endif /* __USB_HOST_AUDIO_H__ */
diff --git a/usb_1.1.0/host/class/usb_host_cdc.c b/usb_1.1.0/host/class/usb_host_cdc.c
new file mode 100644
index 0000000..378e07f
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_cdc.c
@@ -0,0 +1,1200 @@
+/*
+ * 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_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 */
+ cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, cdcInstance->stallDataBuffer,
+ cdcInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ 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 application */
+ cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, cdcInstance->stallDataBuffer,
+ cdcInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ 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);
+ }
+ 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)
+ {
+ 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.
+ */
+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)
+ {
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+
+ if (cdcInstance->inCallbackFn != NULL)
+ {
+ cdcInstance->inCallbackFn(cdcInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status);
+ }
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+}
+
+/*!
+ * @brief cdc data out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+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)
+ {
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+ if (cdcInstance->outCallbackFn != NULL)
+ {
+ cdcInstance->outCallbackFn(cdcInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status);
+ }
+
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+}
+
+/*!
+ * @brief cdc data out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+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)
+ {
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+
+ if (cdcInstance->interruptCallbackFn != NULL)
+ {
+ cdcInstance->interruptCallbackFn(cdcInstance->interruptCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(cdcInstance->hostHandle, transfer);
+}
+
+/*!
+ * @brief cdc data out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+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)
+ {
+ cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status);
+ }
+ 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 = (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 = (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)
+ {
+ cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
+ }
+ 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);
+ 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 = (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)
+ {
+ cdcInstance->controlCallbackFn(cdcInstance->controlCallbackParam, NULL, 0, status);
+ }
+ 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 *)USB_OsaMemoryAllocate(sizeof(usb_host_cdc_instance_struct_t));
+ uint32_t info_value;
+
+ if (control_ptr == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ control_ptr->deviceHandle = deviceHandle;
+ control_ptr->controlInterfaceHandle = NULL;
+ control_ptr->dataInterfaceHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &info_value);
+ control_ptr->hostHandle = (usb_host_handle)info_value;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &info_value);
+ control_ptr->controlPipe = (usb_host_pipe_handle)info_value;
+
+ *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 == 0)
+ {
+ if (callbackFn != NULL)
+ {
+ status = USB_HostCdcOpenControlInterface(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_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
+ {
+ 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 == 0)
+ {
+ 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
+ {
+ 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;
+ 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);
+ 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;
+ }
+
+ USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->controlInterfaceHandle);
+
+ if (cdcInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(cdcInstance->hostHandle, 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_HostCancelTransfer(cdcInstance->hostHandle, 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;
+ }
+ if ((cdcInstance->controlPipe != NULL) && (cdcInstance->controlTransfer != NULL))
+ {
+ status =
+ USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->controlPipe, cdcInstance->controlTransfer);
+ }
+ USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->dataInterfaceHandle);
+
+ USB_OsaMemoryFree(cdcInstance);
+ }
+ else
+ {
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @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("failt to USB_HostRecv\r\n");
+#endif
+ 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("failt to USB_HostSend\r\n");
+#endif
+ 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("failt to usb_interrupt_recv\r\n");
+#endif
+ 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 = (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("failt for USB_HostSendSetup\r\n");
+#endif
+ 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 = 0;
+
+ usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle;
+
+ lineState = dtr ? USB_HOST_CDC_CONTROL_LINE_STATE_DTR : 0;
+ lineState |= rts ? USB_HOST_CDC_CONTROL_LINE_STATE_RTS : 0;
+ 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, USB_SHORT_GET_LOW(lineState), USB_SHORT_GET_HIGH(lineState), 0, NULL,
+ 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;
+
+ status = kStatus_USB_Success;
+ interface_handle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle;
+ ptr1 = (usb_descriptor_union_t *)interface_handle->interfaceExtension;
+ end_address = (uint32_t)(interface_handle->interfaceExtension + interface_handle->interfaceExtensionLength);
+
+ while ((uint32_t)ptr1 < end_address)
+ {
+ cdc_common_ptr = (usb_cdc_func_desc_struct_t *)&ptr1->common;
+ switch (cdc_common_ptr->common.bDescriptorSubtype)
+ {
+ case USB_HOST_DESC_SUBTYPE_HEADER:
+ *headDesc = &cdc_common_ptr->head;
+ if ((((uint32_t)((*headDesc)->bcdCDC[1]) << 8) + (*headDesc)->bcdCDC[0]) > 0x0110)
+ {
+ 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:
+ break;
+ }
+
+ if (kStatus_USB_Success != status)
+ {
+ break;
+ }
+ ptr1 = (usb_descriptor_union_t *)((uint8_t *)ptr1 + ptr1->common.bLength);
+ }
+ cdcInstance->headDesc = *headDesc;
+ cdcInstance->callManageDesc = *callManageDesc;
+ cdcInstance->abstractControlDesc = *abstractControlDesc;
+ cdcInstance->unionInterfaceDesc = *unionInterfaceDesc;
+ return status;
+}
+
+#endif
diff --git a/usb_1.1.0/host/class/usb_host_cdc.h b/usb_1.1.0/host/class/usb_host_cdc.h
new file mode 100644
index 0000000..0acc181
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_cdc.h
@@ -0,0 +1,518 @@
+/*
+ * 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.
+ */
+
+#ifndef __USB_HOST_CDC_H__
+#define __USB_HOST_CDC_H__
+
+/*!
+ * @addtogroup usb_host_cdc_drv
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* Class-specific request PSTN*/
+/*! @brief CDC class-specific request (SET_LINE_CODING) */
+#define USB_HOST_CDC_SET_LINE_CODING 0x20U
+/*! @brief CDC class-specific request (GET_LINE_CODING) */
+#define USB_HOST_CDC_GET_LINE_CODING 0x21U
+/*! @brief CDC class-specific request (SET_CONTROL_LINE_STATE) */
+#define USB_HOST_CDC_SET_CONTROL_LINE_STATE 0x22U
+
+/*! @brief CDC class-specific notifications(SerialState) bitmap*/
+#define USB_HOST_ACM_UART_STATE_BITMAP_BTXCARRITER 0x01U
+/*! @brief CDC class-specific notifications(SerialState) bitmap*/
+#define USB_HOST_ACM_UART_STATE_BITMAP_BRXCARRITER 0x02U
+/*! @brief CDC class-specific notifications(SerialState) bitmap*/
+#define USB_HOST_ACM_UART_STATE_BITMAP_BBREAK 0x04U
+/*! @brief CDC class-specific notifications(SerialState) bitmap*/
+#define USB_HOST_ACM_UART_STATE_BITMAP_BBRINGSIGNAL 0x10U
+
+/*! @brief CDC class-specific request (SET_CONTROL_LINE_STATE) bitmap*/
+#define USB_HOST_CDC_CONTROL_LINE_STATE_DTR 0x01U
+/*! @brief CDC class-specific request (SET_CONTROL_LINE_STATE) bitmap*/
+#define USB_HOST_CDC_CONTROL_LINE_STATE_RTS 0x02U
+
+/*CDC SPEC*/
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_HEADER 0x00U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_CM 0x01U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_ACM 0x02U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_DLM 0x03U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_TR 0x04U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_TC_LSR 0x05U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_UNION 0x06U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_CS 0x07U
+/*! @brief CDC class-specific bDescriptor SubType in functional descriptors*/
+#define USB_HOST_DESC_SUBTYPE_TOM 0x08U
+
+/*See the CDC specification page20*/
+/*! @brief CDC class-specific code, Communications Interface Class Code*/
+#define USB_HOST_CDC_COMMUNICATIONS_CLASS_CODE 0x02U
+/*! @brief CDC class-specific code,Communications Class Subclass Codes*/
+#define USB_HOST_CDC_SUBCLASS_ACM_CODE 0x02U
+/*No class specific protocol required. See the CDC specification page22*/
+#define USB_HOST_CDC_PROTOCOL_CODE 0x00U
+/*! @brief CDC class-specific code,Data Class Interface Codes*/
+#define USB_HOST_CDC_DATA_CLASS_CODE 0x0AU
+/* This field is unused for Data Class interfaces and should have a value of 00h.*/
+#define USB_HOST_CDC_DATA_SUBCLASS_CODE 0x00U
+/*No class-specific protocol required. See the CDC specification page22*/
+#define USB_HOST_CDC_DATA_PROTOCOL_CODE 0x00U
+
+/*! @brief CDC GetLineCoding structure according to the 6.3 in PSTN specification */
+typedef struct _usb_host_cdc_line_coding_struct
+{
+ uint32_t dwDTERate; /*!< Data terminal rate, in bits per second*/
+ uint8_t bCharFormat; /*!< Stop bits*/
+ uint8_t bParityType; /*!< Parity*/
+ uint8_t bDataBits; /*!< Data bits (5, 6, 7, 8 or 16).*/
+} usb_host_cdc_line_coding_struct_t;
+
+/*! @brief CDC GetLineCoding structure according to the 6.3 in PSTN specification */
+typedef struct _usb_host_cdc_control_line_state_struct
+{
+ uint16_t line_state; /*!< D1, This signal corresponds to V.24 signal 105 and RS-232 signal RTS*/
+ /*!< D0, This signal corresponds to V.24 signal 108/2 and RS-232 signal DTR*/
+} usb_host_cdc_control_line_state_struct_t;
+
+/*! @brief CDC SerialState structure according to the 6.5.4 in PSTN specification */
+typedef struct _usb_host_cdc_acm_state_struct
+{
+ uint8_t reserved[8]; /*!< Notify response by the device, this is used as notification header, which is returned by the
+ device */
+ uint8_t bmstate; /*!< UART State Bitmap Values*/
+ uint8_t reserved1[1]; /*!< Fix 4B align issue*/
+ uint8_t reserved2[2]; /*!< Fix 4B align issue*/
+} usb_host_cdc_acm_state_struct_t;
+
+/*! @brief CDC Header Functional Descriptor structure according to the 5.2.3 in CDC specification */
+typedef struct _usb_host_cdc_head_function_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE descriptor type.*/
+ uint8_t bDescriptorSubtype; /*!<Header functional descriptor subtype.*/
+ uint8_t bcdCDC[2]; /*!<USB Class Definitions for Communications Devices Specification release number in binary-coded
+ decimal.*/
+} usb_host_cdc_head_function_desc_struct_t;
+
+/*! @brief CDC Call Management Functional Descriptor structure according to the 5.3.1 in PSTN specification */
+typedef struct _usb_host_cdc_call_manage_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Call Management functional descriptor subtype.*/
+ uint8_t bmCapabilities; /*!<The capabilities that this configuration supports.*/
+ uint8_t bDataInterface; /*!<Interface number of Data Class interface optionally used for call management.*/
+} usb_host_cdc_call_manage_desc_struct_t;
+
+/*! @brief CDC Abstract Control Management Functional Descriptor structure according to the 5.3.2 in PSTN specification
+ */
+typedef struct _usb_host_cdc_abstract_control_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Abstract Control Management functional descriptor subtype.*/
+ uint8_t bmCapabilities; /*!<The capabilities that this configuration supports.*/
+} usb_host_cdc_abstract_control_desc_struct_t;
+
+/*! @brief CDC Direct Line Management Functional Descriptor structure according to the 5.3.3 in PSTN specification */
+typedef struct _usb_host_cdc_direct_line_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Direct Line Management functional descriptor subtype,.*/
+ uint8_t bmCapabilities; /*!<The capabilities that this configuration supports.*/
+} usb_host_cdc_direct_line_desc_struct_t;
+
+/*! @brief CDC Telephone Ringer Functional Descriptor structure according to the 5.3.4 in PSTN specification */
+typedef struct _usb_host_cdc_telephone_ringer_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Telephone Ringer functional descriptor subtype*/
+ uint8_t bRingerVolSteps; /*!<Number of discrete steps in volume supported by the ringer,.*/
+ uint8_t bNumRingerPatterns; /*!<Number of ringer patterns supported.*/
+} usb_host_cdc_telephone_ringer_desc_struct_t;
+
+/*! @brief CDC Telephone Call and Line State Reporting Capabilities Descriptor structure according to the 5.3.6 in PSTN
+ * specification */
+typedef struct _usb_host_cdc_tcLsr_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Telephone Call State Reporting Capabilities descriptor subtype.*/
+ uint8_t bmCapabilities[4]; /*!<Call and line state reporting capabilities of the device.*/
+} usb_host_cdc_tcLsr_desc_struct_t;
+
+/*! @brief CDC Header Functional Descriptor structure according to the 5.2.3 in CDC specification */
+typedef struct _usb_host_cdc_union_interface_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE descriptor type.*/
+ uint8_t bDescriptorSubtype; /*!<Union Functional Descriptor SubType.*/
+ uint8_t bControlInterface; /*!<USB Class Definitions for Communications Devices Specification release number in
+ binary-coded decimal.*/
+} usb_host_cdc_union_interface_desc_struct_t;
+
+/*! @brief CDC Telephone Operational Modes Functional Descriptor structure according to the 5.3.5 in PSTN specification
+ */
+typedef struct _usb_host_cdc_tom_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE.*/
+ uint8_t bDescriptorSubtype; /*!<Telephone Operational Modes functional descriptor subtype.*/
+ uint8_t bmCapabilities; /*!<Operational modes:.*/
+} usb_host_cdc_tom_desc_struct_t;
+
+/*! @brief CDC common Functional Descriptor structure */
+typedef struct _usb_host_cdc_common_desc_struct
+{
+ uint8_t bFunctionLength; /*!<Size of this descriptor in bytes.*/
+ uint8_t bDescriptorType; /*!<CS_INTERFACE descriptor type.*/
+ uint8_t bDescriptorSubtype; /*!<Header functional descriptor subtype.*/
+} usb_host_cdc_common_desc_struct_t;
+
+/*! @brief CDC union Functional Descriptor structure for analyze a class-specific descriptor */
+typedef union _usb_cdc_func_desc_struct
+{
+ usb_host_cdc_common_desc_struct_t common;
+ usb_host_cdc_head_function_desc_struct_t head;
+ usb_host_cdc_union_interface_desc_struct_t unionDesc;
+ usb_host_cdc_call_manage_desc_struct_t callManage;
+ usb_host_cdc_abstract_control_desc_struct_t acm;
+ usb_host_cdc_direct_line_desc_struct_t dl;
+ usb_host_cdc_telephone_ringer_desc_struct_t tr;
+ usb_host_cdc_tom_desc_struct_t tom;
+ usb_host_cdc_tcLsr_desc_struct_t tcLsr;
+} usb_cdc_func_desc_struct_t;
+
+typedef struct _usb_host_cdc_instance_struct
+{
+ usb_host_handle hostHandle; /*!< The handle of the USB host. */
+ usb_device_handle deviceHandle; /*!< The handle of the USB device structure. */
+ usb_host_interface_handle controlInterfaceHandle; /*!< The handle of the CDC device control interface. */
+ usb_host_interface_handle dataInterfaceHandle; /*!< The handle of the CDC device data interface. */
+ usb_host_pipe_handle interruptPipe; /*!< Interrupt pipe for the CDC device data interface. */
+ usb_host_pipe_handle controlPipe; /*!< Control pipe*/
+ usb_host_pipe_handle inPipe; /*!< CDC bulk in pipe*/
+ usb_host_pipe_handle outPipe; /*!< CDC bulk out pipe*/
+ usb_host_cdc_head_function_desc_struct_t *headDesc; /*!< CDC class-specific head function descriptor*/
+ usb_host_cdc_call_manage_desc_struct_t *callManageDesc; /*!< cdCDCc class-specific call manage descriptor*/
+ usb_host_cdc_abstract_control_desc_struct_t
+ *abstractControlDesc; /*!< CDC class-specific abstract control descriptor*/
+ usb_host_cdc_union_interface_desc_struct_t *unionInterfaceDesc; /*!< CDC class-specific union function descriptor*/
+ void *interruptCallbackParam; /*!< CDC interrupt in transfer callback parameter*/
+ void *controlCallbackParam; /*!< CDC control transfer callback parameter*/
+ void *inCallbackParam; /*!< CDC bulk in transfer callback parameter*/
+ void *outCallbackParam; /*!< CDC bulk out transfer callback parameter*/
+ usb_host_transfer_t *controlTransfer; /*!< Ongoing control transfer*/
+ transfer_callback_t controlCallbackFn; /*!< CDC control transfer callback function pointer*/
+ transfer_callback_t interruptCallbackFn; /*!< CDC interrupt transfer callback function pointer*/
+ transfer_callback_t outCallbackFn; /*!< CDC bulk out transfer callback function pointer*/
+ transfer_callback_t inCallbackFn; /*!< CDC bulk in transfer callback function pointer*/
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+ uint8_t *stallDataBuffer; /*!< Keep the data buffer for stall transfer's data*/
+ uint32_t stallDataLength; /*!< Keep the data length for stall transfer's data*/
+#endif
+ uint16_t packetSize; /*!< CDC control pipe maximum packet size*/
+ uint16_t bulkOutPacketSize; /*!< CDC bulk out maximum packet size*/
+ uint16_t bulkInPacketSize; /*!< CDC bulk in maximum packet size*/
+} usb_host_cdc_instance_struct_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @name USB CDC host class driver
+ * @{
+ */
+
+/*!
+ * @brief Initializes the CDC instance.
+ *
+ * This function allocates the resource for the CDC instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandle Returns class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+extern usb_status_t USB_HostCdcInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief CDC set data interface callback and opens pipes.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceHandle The interface handle.
+ * @param[in] alternateSetting The alternate setting value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+
+extern usb_status_t USB_HostCdcSetDataInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief CDC set control interface callback and opens pipes.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceHandle The interface handle.
+ * @param[in] alternateSetting The alternate setting value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+
+extern usb_status_t USB_HostCdcSetControlInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Deinitializes the CDC instance.
+ *
+ * This function frees the resource for the CDC instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is de-initialized successfully.
+ */
+extern usb_status_t USB_HostCdcDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Gets the pipe maximum packet size.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] pipeType Its value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
+ * USB_ENDPOINT_INTERRUPT.
+ * See the usb_spec.h
+ * @param[in] direction Pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval max Packet size.
+ */
+extern uint16_t USB_HostCdcGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction);
+
+/*!
+ * @brief Receives data.
+ *
+ * This function implements the 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostCdcDataRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Sends data.
+ *
+ * This function implements the 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostCdcDataSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Interrupts the receive data.
+ *
+ * This function implements the 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostCdcInterruptRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief CDC get line coding.
+ *
+ * This function implements the CDC GetLineCoding request. See the PSTN specification.
+ *
+ * @param classHandle The class handle.
+ * @param uartLineCoding The line coding pointer.
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostCdcGetAcmLineCoding(usb_host_class_handle classHandle,
+ usb_host_cdc_line_coding_struct_t *uartLineCoding,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief CDC setControlLineState.
+ *
+ * This function implements the CDC etControlLineState request. See PSTN specification.
+ *
+ * @param classHandle The class handle.
+ * @param dtr The DRS value.
+ * @param rts The RTS value.
+ * @param callbackFn This callback is called after this function completes.
+ * @param callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostCdcSetAcmCtrlState(
+ usb_host_class_handle classHandle, uint8_t dtr, uint8_t rts, transfer_callback_t callbackFn, void *callbackParam);
+
+/*!
+ * @brief CDC gets the ACM descriptor.
+ *
+ * This function is hunting for the class-specific ACM descriptor in the configuration and gets 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.
+ */
+extern 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);
+
+/*!
+ * @brief CDC send control transfer common code.
+ *
+ * @param classHandle The class handle.
+ * @param request_type Set up the packet request type.
+ * @param request Set up the packet request value.
+ * @param wvalue_l Set up the packet wvalue low byte.
+ * @param wvalue_h Set up the packet wvalue high byte.
+ * @param wlength Set up the 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.
+ */
+extern 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);
+/*@}*/
+
+#ifdef __cplusplus
+}
+#endif
+/*@}*/
+
+#endif /*__USB_HOST_CDC_H__*/
diff --git a/usb_1.1.0/host/class/usb_host_hid.c b/usb_1.1.0/host/class/usb_host_hid.c
new file mode 100644
index 0000000..ddaf3be
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hid.c
@@ -0,0 +1,804 @@
+/*
+ * 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_HID) && (USB_HOST_CONFIG_HID))
+#include "usb_host.h"
+#include "usb_host_hid.h"
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief hid in pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHidInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hid out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHidOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hid control pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHidControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hid open interface. It is called when set interface request success or open alternate setting 0 interface.
+ *
+ * @param hidInstance hid instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostHidOpenInterface(usb_host_hid_instance_t *hidInstance);
+
+/*!
+ * @brief hid set interface callback, open pipes.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHidSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hid send control transfer common code.
+ *
+ * @param classHandle the class handle.
+ * @param requestType setup packet request type.
+ * @param request setup packet request value.
+ * @param wvalueL setup packet wvalue low byte.
+ * @param wvalueH 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.
+ */
+static usb_status_t USB_HostHidControl(usb_host_class_handle classHandle,
+ uint8_t requestType,
+ uint8_t request,
+ uint8_t wvalueL,
+ uint8_t wvalueH,
+ uint16_t wlength,
+ uint8_t *data,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+
+static void USB_HostHidClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
+
+ hidInstance->controlTransfer = NULL;
+ if (hidInstance->inCallbackFn != NULL)
+ {
+ /* callback to application */
+ hidInstance->inCallbackFn(hidInstance->inCallbackParam, hidInstance->stallDataBuffer,
+ hidInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+static void USB_HostHidClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
+
+ hidInstance->controlTransfer = NULL;
+ if (hidInstance->outCallbackFn != NULL)
+ {
+ /* callback to application */
+ hidInstance->outCallbackFn(hidInstance->outCallbackParam, hidInstance->stallDataBuffer,
+ hidInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+static usb_status_t USB_HostHidClearHalt(usb_host_hid_instance_t *hidInstance,
+ 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(hidInstance->hostHandle, &transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ return status;
+ }
+ hidInstance->stallDataBuffer = stallTransfer->transferBuffer;
+ hidInstance->stallDataLength = stallTransfer->transferSofar;
+ /* save the application callback function */
+ hidInstance->controlCallbackFn = NULL;
+ hidInstance->controlCallbackParam = NULL;
+ /* initialize transfer */
+ transfer->callbackFn = callbackFn;
+ transfer->callbackParam = hidInstance;
+ 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(hidInstance->hostHandle, hidInstance->controlPipe, transfer);
+
+ if (status != kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ }
+ hidInstance->controlTransfer = transfer;
+
+ return status;
+}
+#endif
+
+static void USB_HostHidInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_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_HostHidClearHalt(hidInstance, transfer, USB_HostHidClearInHaltCallback,
+ (USB_REQUEST_TYPE_DIR_IN |
+ ((usb_host_pipe_t *)hidInstance->inPipe)->endpointAddress)) == kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+ if (hidInstance->inCallbackFn != NULL)
+ {
+ hidInstance->inCallbackFn(hidInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+static void USB_HostHidOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_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_HostHidClearHalt(hidInstance, transfer, USB_HostHidClearOutHaltCallback,
+ (USB_REQUEST_TYPE_DIR_OUT |
+ ((usb_host_pipe_t *)hidInstance->outPipe)->endpointAddress)) == kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+ if (hidInstance->outCallbackFn != NULL)
+ {
+ hidInstance->outCallbackFn(hidInstance->outCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+static void USB_HostHidControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
+
+ hidInstance->controlTransfer = NULL;
+ if (hidInstance->controlCallbackFn != NULL)
+ {
+ hidInstance->controlCallbackFn(hidInstance->controlCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+static usb_status_t USB_HostHidOpenInterface(usb_host_hid_instance_t *hidInstance)
+{
+ usb_status_t status;
+ uint8_t epIndex = 0;
+ usb_host_pipe_init_t pipeInit;
+ usb_descriptor_endpoint_t *epDesc = NULL;
+ usb_host_interface_t *interfacePointer;
+
+ if (hidInstance->inPipe != NULL) /* close interrupt in pipe if it is open */
+ {
+ status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->inPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ hidInstance->inPipe = NULL;
+ }
+ if (hidInstance->outPipe != NULL) /* close interrupt out pipe if it is open */
+ {
+ status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->outPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ hidInstance->outPipe = NULL;
+ }
+
+ /* open interface pipes */
+ interfacePointer = (usb_host_interface_t *)hidInstance->interfaceHandle;
+ for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
+ {
+ epDesc = interfacePointer->epList[epIndex].epDesc;
+ if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
+ USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
+ ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT))
+ {
+ pipeInit.devInstance = hidInstance->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;
+
+ hidInstance->inPacketSize = pipeInit.maxPacketSize;
+
+ status = USB_HostOpenPipe(hidInstance->hostHandle, &hidInstance->inPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("USB_HostHidSetInterface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ }
+ 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_INTERRUPT))
+ {
+ pipeInit.devInstance = hidInstance->deviceHandle;
+ pipeInit.pipeType = USB_ENDPOINT_INTERRUPT;
+ pipeInit.direction = USB_OUT;
+ pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipeInit.interval = epDesc->bInterval;
+ pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ hidInstance->outPacketSize = pipeInit.maxPacketSize;
+
+ status = USB_HostOpenPipe(hidInstance->hostHandle, &hidInstance->outPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("USB_HostHidSetInterface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ }
+ else
+ {
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+static void USB_HostHidSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)param;
+
+ hidInstance->controlTransfer = NULL;
+ if (status == kStatus_USB_Success)
+ {
+ status = USB_HostHidOpenInterface(hidInstance); /* hid open interface */
+ }
+
+ if (hidInstance->controlCallbackFn != NULL)
+ {
+ hidInstance->controlCallbackFn(hidInstance->controlCallbackParam, NULL, 0,
+ status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+}
+
+usb_status_t USB_HostHidInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
+{
+ uint32_t infoValue;
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)USB_OsaMemoryAllocate(
+ sizeof(usb_host_hid_instance_t)); /* malloc hid class instance */
+
+ if (hidInstance == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ /* initialize hid instance */
+ hidInstance->deviceHandle = deviceHandle;
+ hidInstance->interfaceHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue);
+ hidInstance->hostHandle = (usb_host_handle)infoValue;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue);
+ hidInstance->controlPipe = (usb_host_pipe_handle)infoValue;
+
+ *classHandle = hidInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHidSetInterface(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_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ hidInstance->interfaceHandle = interfaceHandle;
+ status = USB_HostOpenDeviceInterface(hidInstance->deviceHandle,
+ interfaceHandle); /* notify host driver the interface is open */
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+
+ /* cancel transfers */
+ if (hidInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->inPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+ if (hidInstance->outPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->outPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+
+ if (alternateSetting == 0) /* open interface directly */
+ {
+ if (callbackFn != NULL)
+ {
+ status = USB_HostHidOpenInterface(hidInstance);
+ callbackFn(callbackParam, NULL, 0, status);
+ }
+ }
+ else /* send setup transfer */
+ {
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(hidInstance->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 */
+ hidInstance->controlCallbackFn = callbackFn;
+ hidInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->callbackFn = USB_HostHidSetInterfaceCallback;
+ transfer->callbackParam = hidInstance;
+ 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 *)hidInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
+ transfer->setupPacket.wLength = 0;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ status = USB_HostSendSetup(hidInstance->hostHandle, hidInstance->controlPipe, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ hidInstance->controlTransfer = transfer;
+ }
+ else
+ {
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ }
+ }
+
+ return status;
+}
+
+usb_status_t USB_HostHidDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
+{
+ usb_status_t status;
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (classHandle != NULL) /* class instance has initialized */
+ {
+ if (hidInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->inPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->inPipe); /* close pipe */
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ hidInstance->inPipe = NULL;
+ }
+ if (hidInstance->outPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->outPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(hidInstance->hostHandle, hidInstance->outPipe); /* close pipe */
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ hidInstance->outPipe = NULL;
+ }
+ if ((hidInstance->controlPipe != NULL) &&
+ (hidInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */
+ {
+ status =
+ USB_HostCancelTransfer(hidInstance->hostHandle, hidInstance->controlPipe, hidInstance->controlTransfer);
+ }
+ USB_HostCloseDeviceInterface(deviceHandle,
+ hidInstance->interfaceHandle); /* notify host driver the interface is closed */
+ USB_OsaMemoryFree(hidInstance);
+ }
+ else
+ {
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+uint16_t USB_HostHidGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+ if (classHandle == NULL)
+ {
+ return 0;
+ }
+
+ if (pipeType == USB_ENDPOINT_INTERRUPT)
+ {
+ if (direction == USB_IN)
+ {
+ return hidInstance->inPacketSize;
+ }
+ else
+ {
+ return hidInstance->outPacketSize;
+ }
+ }
+
+ return 0;
+}
+
+usb_status_t USB_HostHidRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (hidInstance->inPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(hidInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ hidInstance->inCallbackFn = callbackFn;
+ hidInstance->inCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostHidInPipeCallback;
+ transfer->callbackParam = hidInstance;
+
+ if (USB_HostRecv(hidInstance->hostHandle, hidInstance->inPipe, transfer) !=
+ kStatus_USB_Success) /* call host driver api */
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt to USB_HostRecv\r\n");
+#endif
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHidSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (hidInstance->outPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(hidInstance->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 */
+ hidInstance->outCallbackFn = callbackFn;
+ hidInstance->outCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostHidOutPipeCallback;
+ transfer->callbackParam = hidInstance;
+
+ if (USB_HostSend(hidInstance->hostHandle, hidInstance->outPipe, transfer) !=
+ kStatus_USB_Success) /* call host driver api */
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt to USB_HostSend\r\n");
+#endif
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostHidControl(usb_host_class_handle classHandle,
+ uint8_t requestType,
+ uint8_t request,
+ uint8_t wvalueL,
+ uint8_t wvalueH,
+ uint16_t wlength,
+ uint8_t *data,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_hid_instance_t *hidInstance = (usb_host_hid_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(hidInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ hidInstance->controlCallbackFn = callbackFn;
+ hidInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = data;
+ transfer->transferLength = wlength;
+ transfer->callbackFn = USB_HostHidControlCallback;
+ transfer->callbackParam = hidInstance;
+ transfer->setupPacket.bmRequestType = requestType;
+ transfer->setupPacket.bRequest = request;
+ transfer->setupPacket.wValue = (wvalueL | (uint16_t)((uint16_t)wvalueH << 8));
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
+ ((usb_host_interface_t *)hidInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
+
+ if (USB_HostSendSetup(hidInstance->hostHandle, hidInstance->controlPipe, transfer) !=
+ kStatus_USB_Success) /* call host driver api */
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt for USB_HostSendSetup\r\n");
+#endif
+ USB_HostFreeTransfer(hidInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ hidInstance->controlTransfer = transfer;
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHidGetReportDescriptor(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t buffer_len,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_REQUEST_STANDARD_GET_DESCRIPTOR, 0, USB_DESCRIPTOR_TYPE_HID_REPORT, buffer_len, buffer, callbackFn,
+ callbackParam);
+}
+
+usb_status_t USB_HostHidGetIdle(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t *idleRate,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_GET_IDLE, reportId, 0, 1, idleRate, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostHidSetIdle(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t idleRate,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_SET_IDLE, reportId, idleRate, 0, NULL, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostHidGetProtocol(usb_host_class_handle classHandle,
+ uint8_t *protocol,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_GET_PROTOCOL, 0, 0, 1, protocol, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostHidSetProtocol(usb_host_class_handle classHandle,
+ uint8_t protocol,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_SET_PROTOCOL, protocol, 0, 0, NULL, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostHidGetReport(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t reportType,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_GET_REPORT, reportId, reportType, bufferLength, buffer, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostHidSetReport(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t reportType,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHidControl(
+ classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_HID_SET_REPORT, reportId, reportType, bufferLength, buffer, callbackFn, callbackParam);
+}
+
+#endif /* USB_HOST_CONFIG_HID */
diff --git a/usb_1.1.0/host/class/usb_host_hid.h b/usb_1.1.0/host/class/usb_host_hid.h
new file mode 100644
index 0000000..86e66d6
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hid.h
@@ -0,0 +1,411 @@
+/*
+ * 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.
+ */
+
+#ifndef _USB_HOST_HID_H_
+#define _USB_HOST_HID_H_
+
+/*******************************************************************************
+ * HID class public structure, enumerations, macros, functions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*!
+ * @addtogroup usb_host_hid_drv
+ * @{
+ */
+
+/*! @brief HID class-specific request (get report) */
+#define USB_HOST_HID_GET_REPORT (0x01U)
+/*! @brief HID class-specific request (get idle) */
+#define USB_HOST_HID_GET_IDLE (0x02U)
+/*! @brief HID class-specific request (get protocol) */
+#define USB_HOST_HID_GET_PROTOCOL (0x03U)
+/*! @brief HID class-specific request (set report) */
+#define USB_HOST_HID_SET_REPORT (0x09U)
+/*! @brief HID class-specific request (set idle) */
+#define USB_HOST_HID_SET_IDLE (0x0AU)
+/*! @brief HID class-specific request (set protocol) */
+#define USB_HOST_HID_SET_PROTOCOL (0x0BU)
+
+/*! @brief HID class code */
+#define USB_HOST_HID_CLASS_CODE (3U)
+/*! @brief HID sub-class code */
+#define USB_HOST_HID_SUBCLASS_CODE_NONE (0U)
+/*! @brief HID sub-class code */
+#define USB_HOST_HID_SUBCLASS_CODE_BOOT (1U)
+/*! @brief HID class protocol code */
+#define USB_HOST_HID_PROTOCOL_KEYBOARD (1U)
+/*! @brief HID class protocol code */
+#define USB_HOST_HID_PROTOCOL_MOUSE (2U)
+/*! @brief HID class protocol code */
+#define USB_HOST_HID_PROTOCOL_NONE (0U)
+
+/*! @brief HID get/set protocol request data code */
+#define USB_HOST_HID_REQUEST_PROTOCOL_BOOT (0U)
+/*! @brief HID get/set protocol request data code */
+#define USB_HOST_HID_REQUEST_PROTOCOL_REPORT (1U)
+
+/*! @brief HID instance structure and HID usb_host_class_handle pointer to this structure */
+typedef struct _usb_host_hid_instance
+{
+ usb_host_handle hostHandle; /*!< This instance's related host handle*/
+ usb_device_handle deviceHandle; /*!< This instance's related device handle*/
+ usb_host_interface_handle interfaceHandle; /*!< This instance's related interface handle*/
+ usb_host_pipe_handle controlPipe; /*!< This instance's related device control pipe*/
+ usb_host_pipe_handle inPipe; /*!< HID interrupt in pipe*/
+ usb_host_pipe_handle outPipe; /*!< HID interrupt out pipe*/
+ transfer_callback_t inCallbackFn; /*!< HID interrupt in transfer callback function pointer*/
+ void *inCallbackParam; /*!< HID interrupt in transfer callback parameter*/
+ transfer_callback_t outCallbackFn; /*!< HID interrupt out transfer callback function pointer*/
+ void *outCallbackParam; /*!< HID interrupt out transfer callback parameter*/
+ transfer_callback_t controlCallbackFn; /*!< HID control transfer callback function pointer*/
+ void *controlCallbackParam; /*!< HID control transfer callback parameter*/
+ usb_host_transfer_t *controlTransfer; /*!< Ongoing control transfer*/
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+ uint8_t *stallDataBuffer; /*!< keep the data buffer for stall transfer's data*/
+ uint32_t stallDataLength; /*!< keep the data length for stall transfer's data*/
+#endif
+
+ uint16_t inPacketSize; /*!< HID interrupt in maximum packet size*/
+ uint16_t outPacketSize; /*!< HID interrupt out maximum packet size*/
+} usb_host_hid_instance_t;
+
+/*! @brief HID descriptor structure according to the 6.2.1 in HID specification */
+typedef struct _usb_host_hid_descriptor
+{
+ uint8_t bLength; /*!< Total size of the HID descriptor*/
+ uint8_t bDescriptorType; /*!< Constant name specifying type of HID descriptor*/
+ uint8_t bcdHID[2]; /*!< Numeric expression identifying the HID Class Specification release*/
+ uint8_t bCountryCode; /*!< Numeric expression identifying country code of the localized hardware*/
+ uint8_t bNumDescriptors; /*!< Numeric expression specifying the number of class descriptors*/
+ uint8_t bHidDescriptorType; /*!< Constant name identifying type of class descriptor*/
+ uint8_t wDescriptorLength[2]; /*!< Numeric expression that is the total size of the Report descriptor*/
+} usb_host_hid_descriptor_t;
+
+/*! @brief HID descriptor structure according to the 6.2.1 in HID specification */
+typedef struct _usb_host_hid_class_descriptor
+{
+ uint8_t bHidDescriptorType; /*!< Constant name specifying type of optional descriptor*/
+ uint8_t wDescriptorLength[2]; /*!< Numeric expression that is the total size of the optional descriptor*/
+} usb_host_hid_class_descriptor_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host HID class APIs
+ * @{
+ */
+
+/*!
+ * @brief Initializes the HID instance.
+ *
+ * This function allocate the resource for the HID instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[out] classHandle Return class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+extern usb_status_t USB_HostHidInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief Sets the interface.
+ *
+ * This function binds the interface with the HID instance.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceHandle The interface handle.
+ * @param[in] alternateSetting The alternate setting value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostHidSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Deinitializes the the HID instance.
+ *
+ * This function frees the resources for the HID instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[in] classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is de-initialized successfully.
+ */
+extern usb_status_t USB_HostHidDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Gets the pipe maximum packet size.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] pipeType Its value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
+ * USB_ENDPOINT_INTERRUPT.
+ * See the usb_spec.h
+ * @param[in] direction Pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval Maximum packet size.
+ */
+extern uint16_t USB_HostHidGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction);
+
+/*!
+ * @brief HID get report descriptor.
+ *
+ * This function implements the HID report descriptor request.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[out] buffer The buffer pointer.
+ * @param[in] buffer_len The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidGetReportDescriptor(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t buffer_len,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Receives data.
+ *
+ * This function implements the HID receiving data.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[out] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostHidRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Sends data.
+ *
+ * This function implements the HID sending data.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostHidSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID get idle.
+ *
+ * This function implements the HID class-specific request (get idle).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] reportId Report ID.
+ * @param[out] idleRate Return idle rate value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidGetIdle(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t *idleRate,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID set idle.
+ *
+ * This function implements the HID class-specific request (set idle).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] reportId Report ID.
+ * @param[in] idleRate Idle rate value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidSetIdle(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t idleRate,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID get protocol.
+ *
+ * This function implements the HID class-specific request (get protocol).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[out] protocol Return protocol value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidGetProtocol(usb_host_class_handle classHandle,
+ uint8_t *protocol,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID set protocol.
+ *
+ * This function implements the HID class-specific request (set protocol).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] protocol Protocol value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidSetProtocol(usb_host_class_handle classHandle,
+ uint8_t protocol,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID get report.
+ *
+ * This function implements the HID class-specific request (get report).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] reportId Report ID.
+ * @param[in] reportType Report type.
+ * @param[out] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidGetReport(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t reportType,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HID set report.
+ *
+ * This function implements the HID class-specific request (set report).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] reportId Report ID.
+ * @param[in] reportType Report type.
+ * @param[in] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHidSetReport(usb_host_class_handle classHandle,
+ uint8_t reportId,
+ uint8_t reportType,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_HID_H_ */
diff --git a/usb_1.1.0/host/class/usb_host_hub.c b/usb_1.1.0/host/class/usb_host_hub.c
new file mode 100644
index 0000000..1200770
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hub.c
@@ -0,0 +1,612 @@
+/*
+ * 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_HUB) && (USB_HOST_CONFIG_HUB))
+#include "usb_host.h"
+#include "usb_host_hub.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*!
+ * @brief hub control transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hub interrupt in transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief USB_HostHubSendPortReset's transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief hub control transfer common code.
+ *
+ * @param classHandle the class handle.
+ * @param requestType request type.
+ * @param request setup packet request field.
+ * @param wvalue setup packet wValue field.
+ * @param windex setup packet wIndex field.
+ * @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.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle,
+ uint8_t requestType,
+ uint8_t request,
+ uint16_t wvalue,
+ uint16_t windex,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static void USB_HostHubControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
+
+ hubInstance->controlTransfer = NULL;
+ if (hubInstance->controlCallbackFn)
+ {
+ hubInstance->controlCallbackFn(hubInstance->controlCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+}
+
+static void USB_HostHubInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
+
+ if (hubInstance->inCallbackFn)
+ {
+ hubInstance->inCallbackFn(hubInstance->inCallbackParam, transfer->transferBuffer, transfer->transferSofar,
+ status); /* callback to application */
+ }
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+}
+
+static void USB_HostHubResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
+
+ /* note: there is not callback to application, the re-enumeration will start automatically after reset. */
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+}
+
+static usb_status_t USB_HostHubClassRequestCommon(usb_host_class_handle classHandle,
+ uint8_t requestType,
+ uint8_t request,
+ uint16_t wvalue,
+ uint16_t windex,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (hubInstance->controlTransfer != NULL)
+ {
+ return kStatus_USB_Busy;
+ }
+
+ /* get transfer */
+ if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+ /* save hub application callback */
+ hubInstance->controlCallbackFn = callbackFn;
+ hubInstance->controlCallbackParam = callbackParam;
+
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostHubControlCallback;
+ transfer->callbackParam = hubInstance;
+ transfer->setupPacket.bmRequestType = requestType;
+ transfer->setupPacket.bRequest = request;
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(wvalue);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(windex);
+ transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(bufferLength);
+
+ /* send transfer */
+ if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("Error in hid get report descriptor\r\n");
+#endif
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ hubInstance->controlTransfer = transfer; /* record the on-going setup transfer */
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHubInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
+{
+ /* malloc the hub instance */
+ usb_host_hub_instance_t *hubInstance =
+ (usb_host_hub_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_hub_instance_t));
+ uint32_t infoValue;
+
+ if (hubInstance == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ /* initialize hub instance structure */
+ hubInstance->deviceHandle = deviceHandle;
+ hubInstance->interfaceHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue);
+ hubInstance->hostHandle = (usb_host_handle)infoValue;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue);
+ hubInstance->controlPipe = (usb_host_pipe_handle)infoValue;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue);
+ hubInstance->hubLevel = infoValue;
+
+ *classHandle = hubInstance; /* return the hub class handle */
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHubSetInterface(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_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
+ usb_host_interface_t *interface = (usb_host_interface_t *)interfaceHandle;
+ usb_descriptor_endpoint_t *epDesc = NULL;
+ usb_host_pipe_init_t pipeInit;
+ uint8_t epIndex;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ hubInstance->interfaceHandle = interfaceHandle; /* save the interface handle */
+
+ /* notify the host driver that the interface is used by class */
+ status = USB_HostOpenDeviceInterface(hubInstance->deviceHandle, interfaceHandle);
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+
+ /* close opened hub interrupt pipe */
+ if (hubInstance->interruptPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL);
+ status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ hubInstance->interruptPipe = NULL;
+ }
+
+ /* open hub interrupt pipe */
+ for (epIndex = 0; 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))
+ {
+ /* get pipe information from endpoint descriptor */
+ pipeInit.devInstance = hubInstance->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;
+
+ /* open hub interrupt in pipe */
+ status = USB_HostOpenPipe(hubInstance->hostHandle, &hubInstance->interruptPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ break;
+ }
+ }
+
+ /* hub don't support alternatesetting that is not 0 */
+ if (alternateSetting == 0)
+ {
+ if (callbackFn != NULL)
+ {
+ callbackFn(callbackParam, NULL, 0, kStatus_USB_Success);
+ }
+ }
+ else
+ {
+#ifdef HOST_ECHO
+ usb_echo("host don't supprt alternate setting\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+ return status;
+}
+
+usb_status_t USB_HostHubDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
+ uint8_t status;
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (classHandle != NULL)
+ {
+ /* close opened hub interrupt pipe */
+ if (hubInstance->interruptPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->interruptPipe, NULL);
+ status = USB_HostClosePipe(hubInstance->hostHandle, hubInstance->interruptPipe);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("hub close interrupt pipe error\r\n");
+#endif
+ }
+ hubInstance->interruptPipe = NULL;
+ }
+
+ /* cancel control transfer if exist */
+ if ((hubInstance->controlPipe != NULL) && (hubInstance->controlTransfer != NULL))
+ {
+ status =
+ USB_HostCancelTransfer(hubInstance->hostHandle, hubInstance->controlPipe, hubInstance->controlTransfer);
+ }
+
+ /* notify host driver that the interface will not be used */
+ USB_HostCloseDeviceInterface(deviceHandle, hubInstance->interfaceHandle);
+ USB_OsaMemoryFree(hubInstance);
+ }
+ else
+ {
+ /* notify host driver that the interface will not be used */
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHubInterruptRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* get transfer */
+ if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+ /* save hub application callback */
+ hubInstance->inCallbackFn = callbackFn;
+ hubInstance->inCallbackParam = callbackParam;
+
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostHubInPipeCallback;
+ transfer->callbackParam = hubInstance;
+
+ /* call host driver API to receive data */
+ if (USB_HostRecv(hubInstance->hostHandle, hubInstance->interruptPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt to USB_HostRecv\r\n");
+#endif
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHubSendPortReset(usb_host_class_handle classHandle, uint8_t portNumber)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* get transfer */
+ if (USB_HostMallocTransfer(hubInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+
+ /* initialize transfer */
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ transfer->callbackFn = USB_HostHubResetCallback;
+ transfer->callbackParam = hubInstance;
+ transfer->setupPacket.bmRequestType =
+ USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_FEATURE;
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(PORT_RESET);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(portNumber);
+ transfer->setupPacket.wLength = 0;
+
+ /* send the transfer */
+ if (USB_HostSendSetup(hubInstance->hostHandle, hubInstance->controlPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("Error in hid get report descriptor\r\n");
+#endif
+ USB_HostFreeTransfer(hubInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief hub get descriptor.
+ *
+ * This function implements get hub descriptor specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubGetDescriptor(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_DEVICE,
+ USB_REQUEST_STANDARD_GET_DESCRIPTOR, 0x00, 0, buffer, bufferLength, callbackFn, callbackParam);
+}
+
+/*!
+ * @brief hub clear feature.
+ *
+ * This function implements clear hub feature specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubClearFeature(usb_host_class_handle classHandle,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS,
+ USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, 0, NULL, 0, callbackFn,
+ callbackParam);
+}
+
+/*!
+ * @brief hub get status.
+ *
+ * This function implements get hub status specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubGetStatus(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS,
+ USB_REQUEST_STANDARD_GET_STATUS, 0, 0, buffer, bufferLength, callbackFn,
+ callbackParam);
+}
+
+/*!
+ * @brief hub set feature.
+ *
+ * This function implements set hub feature specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubSetPortFeature(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(
+ classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
+ USB_REQUEST_STANDARD_SET_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam);
+}
+
+/*!
+ * @brief hub clear port feature.
+ *
+ * This function implements clear hub port feature specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubClearPortFeature(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(
+ classHandle, USB_REQUEST_TYPE_DIR_OUT | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
+ USB_REQUEST_STANDARD_CLEAR_FEATURE, feature, portNumber, NULL, 0, callbackFn, callbackParam);
+}
+
+/*!
+ * @brief hub port get status.
+ *
+ * This function implements get hub port status specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+usb_status_t USB_HostHubGetPortStatus(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ return USB_HostHubClassRequestCommon(
+ classHandle, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_OTHER,
+ USB_REQUEST_STANDARD_GET_STATUS, 0, portNumber, buffer, bufferLength, callbackFn, callbackParam);
+}
+
+#endif /* USB_HOST_CONFIG_HUB */
diff --git a/usb_1.1.0/host/class/usb_host_hub.h b/usb_1.1.0/host/class/usb_host_hub.h
new file mode 100644
index 0000000..4ea3700
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hub.h
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef _USB_HOST_HUB_H_
+#define _USB_HSOT_HUB_H_
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief USB host HUB maximum port count */
+#define USB_HOST_HUB_MAX_PORT (7U)
+
+/*! @brief HUB class code */
+#define USB_HOST_HUB_CLASS_CODE (9U)
+/*! @brief HUB sub-class code */
+#define USB_HOST_HUB_SUBCLASS_CODE_NONE (0U)
+
+/* HUB and PORT status according to Table 11-17 in chapter 11.*/
+/*! @brief Local Power Status Change: This field indicates that a change has occurred in the HUB's Local Power Source */
+#define C_HUB_LOCAL_POWER (0U)
+/*! @brief Over-Current Change: This field indicates if a change has occurred in the Over-Current field*/
+#define C_HUB_OVER_CURRENT (1U)
+/*! @brief Current Connect Status: This field reflects whether or not a device is currently connected to this port*/
+#define PORT_CONNECTION (0U)
+/*! @brief Port Enabled/Disabled: Ports can be enabled by the USB System Software only. Ports
+can be disabled by either a fault condition (disconnect event or other fault condition) or by the USB System
+Software*/
+#define PORT_ENABLE (1U)
+/*! @brief Suspend: This field indicates whether or not the device on this port is suspended */
+#define PORT_SUSPEND (2U)
+/*! @brief this field indicate that the current drain on the port exceeds the specified maximum. */
+#define PORT_OVER_CURRENT (3U)
+/*! @brief This field is set when the host wishes to reset the attached device */
+#define PORT_RESET (4U)
+/*! @brief This field reflects a port's logical, power control state */
+#define PORT_POWER (8U)
+/*! @brief Low- Speed Device Attached: This is relevant only if a device is attached */
+#define PORT_LOW_SPEED (9U)
+/*! @brief High-speed Device Attached: This is relevant only if a device is attached */
+#define PORT_HIGH_SPEED (10U)
+/*! @brief Connect Status Change: Indicates a change has occurred in the port's Current Connect Status */
+#define C_PORT_CONNECTION (16U)
+/*! @brief Port Enable/Disable Change: This field is set to one when a port is disabled because of a Port_Error
+ * condition */
+#define C_PORT_ENABLE (17U)
+/*! @brief Suspend Change: This field indicates a change in the host-visible suspend state of the attached device */
+#define C_PORT_SUSPEND (18U)
+/*! @brief Over-Current Indicator Change: This field applies only to HUBs that report over-current conditions on a
+ * per-port basis */
+#define C_PORT_OVER_CURRENT (19U)
+/*! @brief Reset Change: This field is set when reset processing on this port is complete */
+#define C_PORT_RESET (20U)
+
+/*! @brief Get HUB think time value */
+#define USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_MASK (0x60U)
+/*! @brief Get HUB think time value */
+#define USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_SHIFT (5U)
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*! @brief HUB descriptor structure */
+typedef struct _usb_host_hub_descriptor
+{
+ uint8_t blength; /*!< Number of bytes in this descriptor*/
+ uint8_t bdescriptortype; /*!< Descriptor Type*/
+ uint8_t bnrports; /*!< Number of downstream facing ports that this HUB supports*/
+ uint8_t whubcharacteristics[2]; /*!< HUB characteristics please reference to Table 11-13 in usb2.0 specification*/
+ uint8_t bpwron2pwrgood; /*!< Time (in 2 ms intervals) from the time the power-on sequence begins on a port until
+ power is good on that port.*/
+ uint8_t bhubcontrcurrent; /*!< Maximum current requirements of the HUB Controller electronics in mA*/
+ uint8_t deviceremovable; /*!< Indicates if a port has a removable device attached*/
+} usb_host_hub_descriptor_t;
+
+/*! @brief HUB port instance structure */
+typedef struct _usb_host_hub_port_instance
+{
+ usb_device_handle deviceHandle; /*!< Device handle*/
+ uint8_t portStatus; /*!< Port running status*/
+ uint8_t resetCount; /*!< Port reset time*/
+ uint8_t speed; /*!< Port's device speed*/
+} usb_host_hub_port_instance_t;
+
+/*! @brief HUB instance structure */
+typedef struct _usb_host_hub_instance
+{
+ struct _usb_host_hub_instance *next; /*!< Next HUB instance*/
+ usb_host_handle hostHandle; /*!< Host handle*/
+ usb_device_handle deviceHandle; /*!< Device handle*/
+ usb_host_interface_handle interfaceHandle; /*!< Interface handle*/
+ usb_host_pipe_handle controlPipe; /*!< Control pipe handle*/
+ usb_host_pipe_handle interruptPipe; /*!< HUB interrupt in pipe handle*/
+ usb_host_hub_port_instance_t *portList; /*!< HUB's port instance list*/
+ usb_host_transfer_t *controlTransfer; /*!< Control transfer in progress*/
+ transfer_callback_t inCallbackFn; /*!< Interrupt in callback*/
+ void *inCallbackParam; /*!< Interrupt in callback parameter*/
+ transfer_callback_t controlCallbackFn; /*!< Control callback*/
+ void *controlCallbackParam; /*!< Control callback parameter*/
+ /* HUB property */
+ uint16_t totalThinktime; /*!< HUB total think time*/
+ uint8_t hubLevel; /*!< HUB level, the root HUB's level is 1*/
+
+ /* HUB application parameter */
+ uint8_t hubDescriptor[7 + (USB_HOST_HUB_MAX_PORT >> 3) + 1]; /*!< HUB descriptor buffer*/
+ uint8_t hubBitmapBuffer[(USB_HOST_HUB_MAX_PORT >> 3) + 1]; /*!< HUB receiving bitmap data buffer*/
+ uint8_t hubStatusBuffer[4]; /*!< HUB status buffer*/
+ uint8_t portStatusBuffer[4]; /*!< Port status buffer*/
+ uint8_t hubStatus; /*!< HUB instance running status*/
+ uint8_t portCount; /*!< HUB port count*/
+ uint8_t portIndex; /*!< Record the index when processing ports in turn*/
+ uint8_t portProcess; /*!< The port that is processing*/
+ uint8_t primeStatus; /*!< Data prime transfer status*/
+ uint8_t invalid; /*!< 0/1, when invalid, cannot send transfer to the class*/
+} usb_host_hub_instance_t;
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @brief Initializes the HUB instance.
+ *
+ * This function allocates the resource for HUB 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.
+ */
+extern usb_status_t USB_HostHubInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief Sets interface.
+ *
+ * This function binds the interfaces with the HUB 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 Open pipe fail. See the USB_HostOpenPipe.
+ * Or send transfer fail. See the USB_HostSendSetup,
+ */
+extern usb_status_t USB_HostHubSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Deinitializes the HUB instance.
+ *
+ * This function releases the resource for HUB instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is deinitialized successfully.
+ */
+extern usb_status_t USB_HostHubDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Receives data.
+ *
+ * This function implements the HUB 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostHubInterruptRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Port reset setup.
+ *
+ * This function sends the HUB port reset transfer.
+ *
+ * @param classHandle The class handle.
+ * @param portNumber Port number.
+ *
+ * @retval kStatus_USB_Success Send 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubSendPortReset(usb_host_class_handle classHandle, uint8_t portNumber);
+
+/*!
+ * @brief HUB get descriptor.
+ *
+ * This function implements get HUB descriptor-specific request.
+ *
+ * @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 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubGetDescriptor(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HUB clear feature.
+ *
+ * This function implements clear HUB feature specific request.
+ *
+ * @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 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_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubClearFeature(usb_host_class_handle classHandle,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HUB get status.
+ *
+ * This function implements the get HUB status-specific request.
+ *
+ * @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 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubGetStatus(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HUB set feature.
+ *
+ * This function implements the set HUB feature-specific request.
+ *
+ * @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 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubSetPortFeature(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HUB clear port feature.
+ *
+ * This function implements the clear HUB port feature-specific request.
+ *
+ * @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 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubClearPortFeature(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t feature,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief HUB port get status.
+ *
+ * This function implements the get HUB port status-specific request.
+ *
+ * @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 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostHubGetPortStatus(usb_host_class_handle classHandle,
+ uint8_t portNumber,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* USB_HOST_CONFIG_HUB */
+
+#endif /* _USB_HSOT_HUB_H_ */
diff --git a/usb_1.1.0/host/class/usb_host_hub_app.c b/usb_1.1.0/host/class/usb_host_hub_app.c
new file mode 100644
index 0000000..1755b69
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hub_app.c
@@ -0,0 +1,1106 @@
+/*
+ * Copyright (c) 2015, 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_HUB) && (USB_HOST_CONFIG_HUB))
+
+#include "usb_host.h"
+#include "usb_host_hub.h"
+#include "usb_host_hub_app.h"
+#include "usb_host_devices.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief prime interrupt in data.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub process state machine. hub is enable after the state machine.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub port attach process state machine. one device is attached to the port after the state machine.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub port detach process state machine. one device is detached from the port after the state machine.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub port process.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub interrupt in data process.
+ *
+ * @param hubInstance hub instance pointer.
+ */
+static void USB_HostHubProcessData(usb_host_hub_instance_t *hubInstance);
+
+/*!
+ * @brief hub control pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status);
+
+/*!
+ * @brief hub interrupt pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+static usb_device_handle s_HubDeviceHandle;
+static usb_host_interface_handle s_HubInterfaceHandle;
+static usb_host_hub_global_t s_HubGlobal;
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static void USB_HostHubGetInterruptStatus(usb_host_hub_instance_t *hubInstance)
+{
+ if (hubInstance == NULL)
+ {
+ return;
+ }
+
+ /* there is no prime for control or interrupt */
+ if (hubInstance->primeStatus != kPrimeNone)
+ {
+ return;
+ }
+
+ /* receive interrupt data */
+ if (USB_HostHubInterruptRecv(hubInstance, hubInstance->hubBitmapBuffer, (hubInstance->portCount >> 3) + 1,
+ USB_HostHubInterruptInCallback, hubInstance) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error in hub interrupt recv\r\n");
+#endif
+ }
+ else
+ {
+ hubInstance->primeStatus = kPrimeInterrupt;
+ }
+}
+
+static void USB_HostHubProcess(usb_host_hub_instance_t *hubInstance)
+{
+ uint8_t needPrimeInterrupt = 0; /* need to prime interrupt in transfer (0 - don't need; 1 - need) */
+ uint8_t processSuccess = 0; /* the code excute successfully (0 - fail; 1 - success) */
+ uint32_t tmp = 0;
+ usb_host_hub_descriptor_t *hubDescriptor;
+
+ switch (hubInstance->hubStatus)
+ {
+ case kHubRunIdle:
+ case kHubRunInvalid:
+ break;
+
+ case kHubRunWaitSetInterface:
+ hubInstance->hubStatus = kHubRunGetDescriptor7; /* update as next state */
+ /* get hub descriptor */
+ if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, 7, USB_HostHubControlCallback,
+ hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl; /* control transfer is on-going */
+ processSuccess = 1;
+#ifdef HOST_ECHO
+ usb_echo("hub get descriptor 7\r\n");
+#endif
+ }
+ else
+ {
+#ifdef HOST_ECHO
+ usb_echo("hub get descriptor 7 error\r\n");
+#endif
+ break;
+ }
+ break;
+
+ case kHubRunGetDescriptor7:
+ hubDescriptor = (usb_host_hub_descriptor_t *)&hubInstance->hubDescriptor[0];
+
+ /* get the hub think time */
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetHubThinkTime, &tmp);
+ hubInstance->totalThinktime = tmp + (((uint32_t)hubDescriptor->whubcharacteristics[0] &
+ USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_MASK) >>
+ USB_HOST_HUB_DESCRIPTOR_CHARACTERISTICS_THINK_TIME_SHIFT);
+
+ /* get hub port number */
+ hubInstance->portCount = hubDescriptor->bnrports;
+ if (hubInstance->portCount > USB_HOST_HUB_MAX_PORT)
+ {
+#ifdef HOST_ECHO
+ usb_echo("port number is bigger than USB_HOST_HUB_MAX_PORT\r\n");
+#endif
+ return;
+ }
+
+ hubInstance->hubStatus = kHubRunGetDescriptor; /* update as next state */
+ /* get hub descriptor */
+ if (USB_HostHubGetDescriptor(hubInstance, hubInstance->hubDescriptor, 7 + (hubInstance->portCount >> 3) + 1,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl; /* control transfer is on-going */
+ processSuccess = 1;
+#ifdef HOST_ECHO
+ usb_echo("hub get descriptor\r\n");
+#endif
+ }
+ else
+ {
+#ifdef HOST_ECHO
+ usb_echo("hub get descriptor error\r\n");
+#endif
+ break;
+ }
+ break;
+
+ case kHubRunGetDescriptor:
+ /* malloc port instance for the hub's ports */
+ hubInstance->portList = (usb_host_hub_port_instance_t *)USB_OsaMemoryAllocate(
+ hubInstance->portCount * sizeof(usb_host_hub_port_instance_t));
+ if (hubInstance->portList == NULL)
+ {
+#ifdef HOST_ECHO
+ usb_echo("port list allocate fail\r\n");
+#endif
+ hubInstance->hubStatus = kHubRunInvalid;
+ break;
+ }
+ /* TODO: port instance status -> can be removed. app_status */
+
+ hubInstance->hubStatus = kHubRunSetPortPower; /* update as next state */
+ hubInstance->portIndex = 0;
+
+ /* there is no significance, just for fixing misra error */
+ if (hubInstance->hubStatus != kHubRunSetPortPower)
+ {
+ break;
+ }
+
+ case kHubRunSetPortPower:
+ /* set PORT_POWER for all ports */
+ if (hubInstance->portIndex < hubInstance->portCount)
+ {
+ hubInstance->portIndex++;
+ if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portIndex, PORT_POWER,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl; /* update as next state */
+ processSuccess = 1;
+#ifdef HOST_ECHO
+ usb_echo("set port feature PORT_POWER\r\n");
+#endif
+ }
+ else
+ {
+#ifdef HOST_ECHO
+ usb_echo("set port feature PORT_POWER fail\r\n");
+#endif
+ needPrimeInterrupt = 1;
+ break;
+ }
+ break;
+ }
+ hubInstance->portProcess = 0;
+ /* reset port information as default */
+ for (tmp = 0; tmp < hubInstance->portCount; ++tmp)
+ {
+ hubInstance->portList[tmp].deviceHandle = NULL;
+ hubInstance->portList[tmp].resetCount = USB_HOST_HUB_PORT_RESET_TIMES;
+ hubInstance->portList[tmp].portStatus = kPortRunWaitPortChange;
+ }
+ hubInstance->hubStatus = kHubRunIdle;
+ needPrimeInterrupt = 1;
+ break;
+
+ case kHubRunGetStatusDone: /* process hub status change */
+ tmp = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS((&hubInstance->hubStatusBuffer[2]));
+ hubInstance->hubStatus = kHubRunIdle;
+ if ((1 << C_HUB_LOCAL_POWER) & tmp) /* C_HUB_LOCAL_POWER */
+ {
+ if (USB_HostHubClearFeature(hubInstance, C_HUB_LOCAL_POWER, USB_HostHubControlCallback, hubInstance) ==
+ kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl;
+ processSuccess = 1;
+ }
+ else
+ {
+ needPrimeInterrupt = 1;
+ }
+ }
+ else if ((1 << C_HUB_OVER_CURRENT) & tmp) /* C_HUB_OVER_CURRENT */
+ {
+ if (USB_HostHubClearFeature(hubInstance, C_HUB_OVER_CURRENT, USB_HostHubControlCallback, hubInstance) ==
+ kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl;
+ processSuccess = 1;
+ }
+ else
+ {
+ needPrimeInterrupt = 1;
+ }
+ }
+ else
+ {
+ needPrimeInterrupt = 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (needPrimeInterrupt == 1) /* prime interrupt in transfer */
+ {
+ hubInstance->hubStatus = kHubRunIdle;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+ else
+ {
+ if (processSuccess == 0)
+ {
+ hubInstance->hubStatus = kHubRunInvalid;
+ }
+ }
+}
+
+static void USB_HostHubProcessPort(usb_host_hub_instance_t *hubInstance)
+{
+ usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1];
+
+ /* for device attach */
+ if (portInstance->deviceHandle == NULL)
+ {
+ USB_HostHubProcessPortAttach(hubInstance);
+ }
+ else /* for device detach */
+ {
+ USB_HostHubProcessPortDetach(hubInstance);
+ }
+}
+
+static void USB_HostHubProcessPortAttach(usb_host_hub_instance_t *hubInstance)
+{
+ usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1];
+ uint8_t processSuccess = 0;
+ uint32_t specStatus;
+ uint8_t feature;
+ uint32_t infoValue;
+
+ switch (portInstance->portStatus)
+ {
+ case kPortRunIdle:
+ case kPortRunInvalid:
+ break;
+ case kPortRunWaitPortChange: /* (1) port is changed, and get port status */
+ portInstance->portStatus = kPortRunCheckCPortConnection; /* update as next state */
+ /* send class-specific request to get port status */
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+
+ case kPortRunCheckCPortConnection: /* (2) check port status, and clear the status bits */
+ feature = 0;
+ specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS((hubInstance->portStatusBuffer));
+ if ((1 << C_PORT_CONNECTION) & specStatus)
+ {
+ portInstance->portStatus = kPortRunGetPortConnection; /* update as next state */
+ /* clear C_PORT_CONNECTION */
+ if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+ }
+ else if ((1 << PORT_CONNECTION) & specStatus)
+ {
+ portInstance->portStatus = kPortRunWaitPortResetDone; /* update as next state */
+ /* set PORT_RESET */
+ if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ if (portInstance->resetCount > 0)
+ {
+ portInstance->resetCount--;
+ }
+ }
+ break;
+ }
+ else if ((1 << C_PORT_RESET) & specStatus)
+ {
+ feature = C_PORT_RESET; /* clear C_PORT_RESET */
+#ifdef HOST_ECHO
+ usb_echo("hub: C_PORT_RESET when detached\r\n");
+#endif
+ }
+ else if ((1 << C_PORT_ENABLE) & specStatus)
+ {
+ feature = C_PORT_ENABLE; /* clear C_PORT_ENABLE */
+#ifdef HOST_ECHO
+ usb_echo("hub: C_PORT_ENABLE when detached\r\n");
+#endif
+ }
+ else if ((1 << C_PORT_OVER_CURRENT) & specStatus)
+ {
+ feature = C_PORT_OVER_CURRENT; /* clear C_PORT_OVER_CURRENT */
+#ifdef HOST_ECHO
+ usb_echo("hub: C_PORT_OVER_CURRENT when detached\r\n");
+#endif
+ }
+ else
+ {
+ }
+
+ if (feature != 0)
+ {
+ portInstance->portStatus = kPortRunWaitPortChange; /* update as next state */
+ /* clear feature */
+ if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, feature,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ }
+ break;
+
+ case kPortRunGetPortConnection: /* (3) get port status */
+ portInstance->portStatus = kPortRunCheckPortConnection; /* update as next state */
+ /* get port status bits */
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl; /* control transfer is on-going */
+ processSuccess = 1;
+ }
+ break;
+
+ case kPortRunCheckPortConnection: /* (4) check PORT_CONNECTION bit */
+ specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
+ if ((1 << PORT_CONNECTION) & specStatus)
+ {
+ portInstance->portStatus = kPortRunWaitPortResetDone; /* update as next state */
+ /* set PORT_RESET */
+ if (USB_HostHubSetPortFeature(hubInstance, hubInstance->portProcess, PORT_RESET,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ if (portInstance->resetCount > 0)
+ {
+ portInstance->resetCount--;
+ }
+ }
+ }
+ break;
+
+ case kPortRunWaitPortResetDone: /* (5) wait port change */
+ portInstance->portStatus = kPortRunWaitCPortReset; /* update as next state */
+ processSuccess = 1;
+ /* must wait the enumeration done, then operate the next port */
+ USB_HostHubGetInterruptStatus(hubInstance);
+ break;
+
+ case kPortRunWaitCPortReset: /* (6) get port satus for checking C_PORT_RESET */
+ portInstance->portStatus = KPortRunCheckCPortReset; /* update as next state */
+ /* get port status bits */
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+
+ case KPortRunCheckCPortReset: /* (7) check C_PORT_RESET and clear C_PORT_RESET */
+ specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
+ if ((1 << C_PORT_RESET) & specStatus)
+ {
+ if (portInstance->resetCount == 0)
+ {
+ portInstance->portStatus = kPortRunPortAttached; /* update as next state */
+ /* get port's device speed */
+ if (specStatus & (1 << PORT_HIGH_SPEED))
+ {
+ portInstance->speed = USB_SPEED_HIGH;
+ }
+ else if (specStatus & (1 << PORT_LOW_SPEED))
+ {
+ portInstance->speed = USB_SPEED_LOW;
+ }
+ else
+ {
+ portInstance->speed = USB_SPEED_FULL;
+ }
+ }
+ else
+ {
+ portInstance->portStatus = kPortRunResetAgain; /* update as next state */
+ }
+
+ /* clear C_PORT_RESET */
+ if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_RESET,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ }
+ break;
+
+ case kPortRunResetAgain: /* (8) reset again */
+ portInstance->portStatus = kPortRunCheckPortConnection; /* check connection then reset again */
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+
+ case kPortRunPortAttached: /* (9) the port have one device attached */
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
+ USB_HostAttachDevice(hubInstance->hostHandle, portInstance->speed, infoValue, hubInstance->portProcess,
+ hubInstance->hubLevel + 1, &portInstance->deviceHandle);
+ processSuccess = 1;
+ hubInstance->portProcess = 0;
+ s_HubGlobal.hubProcess = NULL;
+ portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ break;
+
+ default:
+ break;
+ }
+
+ if (processSuccess == 0)
+ {
+ portInstance->portStatus = kPortRunWaitPortChange;
+ hubInstance->portProcess = 0;
+ s_HubGlobal.hubProcess = NULL;
+ portInstance->resetCount = USB_HOST_HUB_PORT_RESET_TIMES;
+
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+}
+
+static void USB_HostHubProcessPortDetach(usb_host_hub_instance_t *hubInstance)
+{
+ usb_host_hub_port_instance_t *portInstance = &hubInstance->portList[hubInstance->portProcess - 1];
+ uint8_t processSuccess = 0;
+ uint32_t specStatus;
+
+ switch (portInstance->portStatus)
+ {
+ case kPortRunIdle:
+ case kPortRunInvalid:
+ break;
+
+ case kPortRunPortAttached: /* (1) port is changed, then get port status */
+ portInstance->portStatus = kPortRunCheckPortDetach;
+ /* get port status */
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+
+ case kPortRunCheckPortDetach: /* (2) check port status bits */
+ specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
+ portInstance->portStatus = kPortRunGetConnectionBit;
+ if ((1 << C_PORT_CONNECTION) & specStatus) /* C_PORT_CONNECTION */
+ {
+ if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_CONNECTION,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+ }
+ else if ((1 << C_PORT_ENABLE) & specStatus) /* C_PORT_ENABLE */
+ {
+ if (USB_HostHubClearPortFeature(hubInstance, hubInstance->portProcess, C_PORT_ENABLE,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+ }
+ else
+ {
+ /* don't break to check CONNECTION bit */
+ }
+
+ case kPortRunGetConnectionBit: /* (3) get port status */
+ portInstance->portStatus = kPortRunCheckConnectionBit;
+ if (USB_HostHubGetPortStatus(hubInstance, hubInstance->portProcess, hubInstance->portStatusBuffer, 4,
+ USB_HostHubControlCallback, hubInstance) == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimePortControl;
+ processSuccess = 1;
+ }
+ break;
+
+ case kPortRunCheckConnectionBit: /* (4) check port connection bit */
+ specStatus = USB_LONG_FROM_LITTLE_ENDIAN_ADDRESS(hubInstance->portStatusBuffer);
+ if ((1 << PORT_CONNECTION) & specStatus) /* PORT_CONNECTION */
+ {
+ portInstance->portStatus = kPortRunPortAttached;
+#ifdef HOST_ECHO
+ usb_echo("PORT_CONNECTION in attach for detach\r\n");
+#endif
+ }
+ else
+ {
+ processSuccess = 1;
+ /* port's device is detached */
+ portInstance->portStatus = kPortRunWaitPortChange;
+ USB_HostDetachDeviceInternal(hubInstance->hostHandle, portInstance->deviceHandle);
+ portInstance->deviceHandle = NULL;
+ s_HubGlobal.hubProcess = NULL;
+ hubInstance->portProcess = 0;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (processSuccess == 0)
+ {
+ portInstance->portStatus = kPortRunPortAttached;
+ s_HubGlobal.hubProcess = NULL;
+ hubInstance->portProcess = 0;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+}
+
+static void USB_HostHubProcessData(usb_host_hub_instance_t *hubInstance)
+{
+ uint8_t needPrimeInterrupt = 1;
+ uint8_t portIndex;
+
+ /* process the port which status change */
+ for (portIndex = 0; portIndex <= hubInstance->portCount; ++portIndex)
+ {
+ if ((0x01u << (portIndex & 0x07u)) & (hubInstance->hubBitmapBuffer[portIndex >> 3]))
+ {
+ if (portIndex == 0) /* hub status change */
+ {
+ if ((s_HubGlobal.hubProcess == NULL) ||
+ ((s_HubGlobal.hubProcess == hubInstance) && (hubInstance->portProcess == 0)))
+ {
+ hubInstance->hubStatus = kHubRunGetStatusDone;
+ if (USB_HostHubGetStatus(hubInstance, hubInstance->hubStatusBuffer, 4, USB_HostHubControlCallback,
+ hubInstance) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error in usb_class_hub_get_status\r\n");
+#endif
+ hubInstance->hubStatus = kHubRunIdle;
+ }
+ else
+ {
+ hubInstance->primeStatus = kPrimeHubControl;
+ needPrimeInterrupt = 0;
+ }
+ }
+ }
+ else /* port's status change */
+ {
+ /* process the on-going port or process one new port */
+ if ((s_HubGlobal.hubProcess == NULL) ||
+ ((s_HubGlobal.hubProcess == hubInstance) && (hubInstance->portProcess == 0)) ||
+ ((s_HubGlobal.hubProcess == hubInstance) && (hubInstance->portProcess == portIndex)))
+ {
+ if (hubInstance->controlTransfer == NULL)
+ {
+ s_HubGlobal.hubProcess = hubInstance;
+ hubInstance->portProcess = portIndex;
+ needPrimeInterrupt = 0;
+ USB_HostHubProcessPort(hubInstance);
+ }
+ break; /* process the port change in turn */
+ }
+ }
+ }
+ }
+
+ if (needPrimeInterrupt == 1)
+ {
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+}
+
+void USB_HostHubControlCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
+
+ if (hubInstance->invalid == 1)
+ {
+ return;
+ }
+ if (status != kStatus_USB_Success)
+ {
+ /* if transfer fail, prime a new interrupt in transfer */
+ hubInstance->primeStatus = kPrimeNone;
+ s_HubGlobal.hubProcess = NULL;
+ hubInstance->portProcess = 0;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ return;
+ }
+
+ if (hubInstance->primeStatus == kPrimeHubControl) /* hub related control transfer */
+ {
+ hubInstance->primeStatus = kPrimeNone;
+ USB_HostHubProcess(hubInstance);
+ }
+ else if (hubInstance->primeStatus == kPrimePortControl) /* hub's port related control transfer */
+ {
+ hubInstance->primeStatus = kPrimeNone;
+ USB_HostHubProcessPort(hubInstance);
+ }
+ else
+ {
+ }
+}
+
+void USB_HostHubInterruptInCallback(void *param, uint8_t *data, uint32_t data_len, usb_status_t status)
+{
+ usb_host_hub_instance_t *hubInstance = (usb_host_hub_instance_t *)param;
+
+ if (hubInstance->invalid == 1)
+ {
+ return;
+ }
+ /* interrupt data received */
+ hubInstance->primeStatus = kPrimeNone;
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("hub interrupt in data callback error\r\n");
+#endif
+ /* prime nexe interrupt transfer */
+ if (hubInstance->controlTransfer == NULL)
+ {
+ s_HubGlobal.hubProcess = NULL;
+ hubInstance->portProcess = 0;
+ USB_HostHubGetInterruptStatus(hubInstance);
+ }
+ }
+ else
+ {
+ USB_HostHubProcessData(hubInstance); /* process the interrupt data */
+ }
+}
+
+/*!
+ * @brief host hub callback function.
+ *
+ * This function should be called in the host callback function.
+ *
+ * @param deviceHandle device handle.
+ * @param configurationHandle attached device's configuration descriptor information.
+ * @param event_code callback event code, please reference to enumeration host_event_t.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_NotSupported The configuration don't contain hub interface.
+ */
+usb_status_t USB_HostHubDeviceEvent(usb_device_handle deviceHandle,
+ usb_host_configuration_handle configurationHandle,
+ uint32_t eventCode)
+{
+ usb_host_configuration_t *configuration;
+ usb_host_interface_t *interface;
+ uint8_t interfaceIndex;
+ uint8_t id;
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_class_handle hubClassHandle;
+ usb_host_hub_instance_t *hubInstance;
+ usb_host_hub_instance_t *prevInstance;
+ uint32_t infoValue;
+ usb_osa_status_t osaStatus;
+
+ switch (eventCode)
+ {
+ case kUSB_HostEventAttach:
+ /* judge whether is configurationHandle supported */
+ configuration = (usb_host_configuration_t *)configurationHandle;
+ for (interfaceIndex = 0; interfaceIndex < configuration->interfaceCount; ++interfaceIndex)
+ {
+ interface = &configuration->interfaceList[interfaceIndex];
+ id = interface->interfaceDesc->bInterfaceClass;
+ if (id != USB_HOST_HUB_CLASS_CODE)
+ {
+ continue;
+ }
+ id = interface->interfaceDesc->bInterfaceSubClass;
+ if (id != USB_HOST_HUB_SUBCLASS_CODE_NONE)
+ {
+ continue;
+ }
+ else
+ {
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue);
+ if (infoValue > 5)
+ {
+#ifdef HOST_ECHO
+ usb_echo("Host can support max 5 level hubs\r\n");
+#endif
+ continue;
+ }
+ /* the interface is hub */
+ s_HubDeviceHandle = deviceHandle;
+ s_HubInterfaceHandle = interface;
+ return kStatus_USB_Success;
+ }
+ }
+ status = kStatus_USB_NotSupported;
+ break;
+
+ case kUSB_HostEventEnumerationDone:
+ /* the device enumeration is done */
+ if ((s_HubDeviceHandle != NULL) && (s_HubInterfaceHandle != NULL))
+ {
+ /* print hub information */
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceLevel, &infoValue);
+ usb_echo("hub attached:level=%d ", infoValue);
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
+ usb_echo("address=%d\r\n", infoValue);
+
+ /* initialize hub mutex */
+ if (s_HubGlobal.hubMutex == (usb_osa_mutex_handle)NULL)
+ {
+ osaStatus = USB_OsaMutexCreate(&s_HubGlobal.hubMutex);
+ if (osaStatus != kStatus_USB_OSA_Success)
+ {
+ s_HubGlobal.hubMutex = NULL;
+#ifdef HOST_ECHO
+ usb_echo("hub mutex error\r\n");
+#endif
+ }
+ }
+
+ /* initialize hub class instance */
+ status = USB_HostHubInit(s_HubDeviceHandle, &hubClassHandle);
+ hubInstance = (usb_host_hub_instance_t *)hubClassHandle;
+
+ /* link hub instance to list */
+ USB_HostHubLock();
+ hubInstance->next = s_HubGlobal.hubList;
+ s_HubGlobal.hubList = hubInstance;
+ USB_HostHubUnlock();
+
+ /* set hub instance's interface */
+ if (status == kStatus_USB_Success)
+ {
+ hubInstance->primeStatus = kPrimeHubControl;
+ hubInstance->hubStatus = kHubRunWaitSetInterface;
+ if (USB_HostHubSetInterface(hubClassHandle, s_HubInterfaceHandle, 0, USB_HostHubControlCallback,
+ hubInstance) != kStatus_USB_Success)
+ {
+ hubInstance->hubStatus = kHubRunInvalid;
+ }
+ }
+ }
+ break;
+
+ case kUSB_HostEventDetach:
+ /* the device is detached */
+ hubInstance = NULL;
+
+ /* get device's hub instance handle */
+ USB_HostHubLock();
+ prevInstance = s_HubGlobal.hubList;
+ if (prevInstance->deviceHandle == deviceHandle)
+ {
+ hubInstance = prevInstance;
+ s_HubGlobal.hubList = prevInstance->next;
+ }
+ else
+ {
+ hubInstance = prevInstance->next;
+ while (hubInstance != NULL)
+ {
+ if (hubInstance->deviceHandle == deviceHandle)
+ {
+ prevInstance->next = hubInstance->next;
+ break;
+ }
+ prevInstance = hubInstance;
+ hubInstance = hubInstance->next;
+ }
+ }
+ USB_HostHubUnlock();
+
+ if (hubInstance != NULL)
+ {
+ if (hubInstance == s_HubGlobal.hubProcess)
+ {
+ s_HubGlobal.hubProcess = NULL;
+ }
+ /* print hub information */
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceLevel, &infoValue);
+ usb_echo("hub detached:level=%d ", infoValue);
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
+ usb_echo("address=%d\r\n", infoValue);
+ hubInstance->invalid = 1;
+ /* detach hub ports' devices */
+ for (uint8_t portIndex = 0; portIndex < hubInstance->portCount; ++portIndex)
+ {
+ if ((hubInstance->portList != NULL) && (hubInstance->portList[portIndex].deviceHandle != NULL))
+ {
+ USB_HostDetachDeviceInternal(hubInstance->hostHandle,
+ hubInstance->portList[portIndex].deviceHandle);
+ hubInstance->portList[portIndex].deviceHandle = NULL;
+ }
+ }
+ if (hubInstance->portList != NULL)
+ {
+ USB_OsaMemoryFree(hubInstance->portList);
+ }
+ USB_HostHubDeinit(deviceHandle, hubInstance); /* de-initialize hub instance */
+ }
+
+ /* destory hub mutex if there is no hub instance */
+ if (s_HubGlobal.hubList == NULL)
+ {
+ if (s_HubGlobal.hubMutex != NULL)
+ {
+ USB_OsaMutexDestroy(s_HubGlobal.hubMutex);
+ s_HubGlobal.hubMutex = NULL;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+/*!
+ * @brief remove attached device. called by USB_HostRemoveDevice.
+ *
+ * @param hubNumber the device attached hub.
+ * @param portNumber the device attached port.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostHubRemovePort(uint8_t hubNumber, uint8_t portNumber)
+{
+ usb_host_hub_instance_t *hubInstance;
+ uint32_t infoValue;
+
+ /* get hub number's hub instance handle */
+ hubInstance = (usb_host_hub_instance_t *)s_HubGlobal.hubList;
+ while (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &infoValue);
+ if (infoValue == hubNumber)
+ {
+ break;
+ }
+ hubInstance = hubInstance->next;
+ }
+
+ /* set port's status as default, and reset port */
+ if (hubInstance != NULL)
+ {
+ hubInstance->portList[portNumber - 1].deviceHandle = NULL;
+ hubInstance->portList[portNumber - 1].portStatus = kPortRunInvalid;
+ if (hubInstance->portProcess == portNumber)
+ {
+ hubInstance->portProcess = 0;
+ }
+ USB_HostHubSendPortReset(hubInstance, portNumber);
+ }
+ return kStatus_USB_Error;
+}
+
+/*!
+ * @brief get device's high-speed hub's address.
+ *
+ * @param parent_hub_no device's parent hub's address.
+ *
+ * @return hub number.
+ */
+uint32_t USB_HostHubGetHsHubNumber(uint8_t parentHubNo)
+{
+ usb_host_hub_instance_t *hubInstance = s_HubGlobal.hubList;
+ uint32_t deviceInfo;
+ uint32_t hubNumber;
+
+ /* get parentHubNo's hub instance handle */
+ while (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceInfo);
+ if (parentHubNo == deviceInfo)
+ {
+ break;
+ }
+ hubInstance = hubInstance->next;
+ }
+ if (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceSpeed, &deviceInfo);
+ if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */
+ {
+ hubNumber = parentHubNo;
+ }
+ else /* parent hub is not HS */
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceHSHubNumber,
+ &hubNumber);
+ }
+ return hubNumber;
+ }
+ return 0;
+}
+
+/*!
+ * @brief get device's high-speed hub's port number.
+ *
+ * @param parent_hub_no device's parent hub's address.
+ * @param parent_port_no device's parent port no.
+ *
+ * @return port number.
+ */
+uint32_t USB_HostHubGetHsHubPort(uint8_t parentHubNo, uint8_t parentPortNo)
+{
+ usb_host_hub_instance_t *hubInstance = s_HubGlobal.hubList;
+ uint32_t deviceInfo;
+ uint32_t hubPort;
+
+ /* get parentHubNo's hub instance handle */
+ while (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceInfo);
+ if (parentHubNo == deviceInfo)
+ {
+ break;
+ }
+ hubInstance = hubInstance->next;
+ }
+ if (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceSpeed, &deviceInfo);
+ if (deviceInfo == USB_SPEED_HIGH) /* parent hub is HS */
+ {
+ hubPort = parentPortNo;
+ }
+ else /* parent hub is not HS */
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceHSHubNumber, &hubPort);
+ }
+ return hubPort;
+ }
+ return 0;
+}
+
+/*!
+ * @brief get device's hub total think time.
+ *
+ * @param parent_hub_no device's parent hub's address.
+ *
+ * @return think time value.
+ */
+uint32_t USB_HostHubGetTotalThinkTime(uint8_t parentHubNo)
+{
+ usb_host_hub_instance_t *hubInstance = s_HubGlobal.hubList;
+ uint32_t deviceAddress;
+
+ /* get parentHubNo's hub instance handle */
+ while (hubInstance != NULL)
+ {
+ USB_HostHelperGetPeripheralInformation(hubInstance->deviceHandle, kUSB_HostGetDeviceAddress, &deviceAddress);
+ if (parentHubNo == deviceAddress)
+ {
+ break;
+ }
+ hubInstance = hubInstance->next;
+ }
+ if (hubInstance != NULL)
+ {
+ return hubInstance->totalThinktime;
+ }
+ return 0;
+}
+
+#endif /* USB_HOST_CONFIG_HUB */
diff --git a/usb_1.1.0/host/class/usb_host_hub_app.h b/usb_1.1.0/host/class/usb_host_hub_app.h
new file mode 100644
index 0000000..fd7df5b
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_hub_app.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef _USB_HOST_HUB_APP_H_
+#define _USB_HOST_HUB_APP_H_
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief HUB reset times*/
+#define USB_HOST_HUB_PORT_RESET_TIMES (1)
+
+/*! @brief HUB lock */
+#define USB_HostHubLock() USB_OsaMutexLock(s_HubGlobal.hubMutex)
+/*! @brief HUB unlock */
+#define USB_HostHubUnlock() USB_OsaMutexUnlock(s_HubGlobal.hubMutex)
+
+/*! @brief HUB application global structure */
+typedef struct _usb_host_hub_global
+{
+ usb_host_handle hostHandle; /*!< This HUB list belong to this host*/
+ usb_host_hub_instance_t *hubProcess; /*!< HUB in processing*/
+ usb_host_hub_instance_t *hubList; /*!< host's HUB list*/
+ usb_osa_mutex_handle hubMutex; /*!< HUB mutex*/
+} usb_host_hub_global_t;
+
+/*! @brief HUB application status */
+typedef enum _usb_host_hub_app_status
+{
+ kHubRunIdle = 0, /*!< Idle */
+ kHubRunInvalid, /*!< Invalid state */
+ kHubRunWaitSetInterface, /*!< Wait callback of set interface */
+ kHubRunGetDescriptor7, /*!< Get 7 bytes HUB descriptor */
+ kHubRunGetDescriptor, /*!< Get all HUB descriptor */
+ kHubRunSetPortPower, /*!< Set HUB's port power */
+ kHubRunGetStatusDone, /*!< HUB status changed */
+} usb_host_hub_app_status_t;
+
+/*! @brief HUB port application status */
+typedef enum _usb_host_port_app_status
+{
+ kPortRunIdle = 0, /*!< Idle */
+ kPortRunInvalid, /*!< Invalid state */
+ kPortRunWaitPortChange, /*!< Wait port status change */
+ kPortRunCheckCPortConnection, /*!< Check C_PORT_CONNECTION */
+ kPortRunGetPortConnection, /*!< Get port status data */
+ kPortRunCheckPortConnection, /*!< Check PORT_CONNECTION */
+ kPortRunWaitPortResetDone, /*!< Wait port reset transfer done */
+ kPortRunWaitCPortReset, /*!< Wait C_PORT_RESET */
+ KPortRunCheckCPortReset, /*!< Check C_PORT_RESET */
+ kPortRunResetAgain, /*!< Reset port again */
+ kPortRunPortAttached, /*!< Device is attached on the port */
+ kPortRunCheckPortDetach, /*!< Check port is detached */
+ kPortRunGetConnectionBit, /*!< Get the port status data */
+ kPortRunCheckConnectionBit, /*!< Check PORT_CONNECTION */
+} usb_host_port_app_status_t;
+
+/*! @brief HUB data prime status */
+typedef enum _usb_host_hub_prime_status
+{
+ kPrimeNone = 0, /*!< Don't prime data*/
+ kPrimeHubControl, /*!< Prime HUB control transfer*/
+ kPrimePortControl, /*!< Prime port control transfer*/
+ kPrimeInterrupt, /*!< Prime interrupt transfer*/
+} usb_host_hub_prime_status_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#endif /* USB_HOST_CONFIG_HUB */
+
+#endif /* _USB_HOST_HUB_APP_H_ */
diff --git a/usb_1.1.0/host/class/usb_host_msd.c b/usb_1.1.0/host/class/usb_host_msd.c
new file mode 100644
index 0000000..ecb9706
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_msd.c
@@ -0,0 +1,1155 @@
+/*
+ * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "usb_host_config.h"
+#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD))
+#include "usb_host.h"
+#include "usb_host_msd.h"
+#include "usb_host_hci.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief clear stall transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer transfer.
+ * @param status transfer result status.
+ */
+static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief send clear stall transfer.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param callbackFn callback function.
+ * @param endpoint endpoint address.
+ *
+ * @return An error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance,
+ host_inner_transfer_callback_t callbackFn,
+ uint8_t endpoint);
+
+/*!
+ * @brief mass storage reset three step processes are done.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param status result status.
+ */
+static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status);
+
+/*!
+ * @brief mass storage reset process step 3 callback.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief mass storage reset process step 2 callback.
+ *
+ * @param msdInstance msd instance pointer.
+ * @transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief mass storage reset process step 1 callback.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief mass storage control transfer callback function.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief this function is called when ufi command is done.
+ *
+ * @param msdInstance msd instance pointer.
+ */
+static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status);
+
+/*!
+ * @brief csw transfer callback.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief cbw transfer callback.
+ *
+ * @param msdInstance msd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief data transfer callback.
+ *
+ * @param msdInstance sd instance pointer.
+ * @param transfer transfer
+ * @param status result status.
+ */
+static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief msd open interface.
+ *
+ * @param msdInstance msd instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance);
+
+/*!
+ * @brief msd set interface callback, open pipes.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief msd control transfer common code.
+ *
+ * This function allocate the resource for msd instance.
+ *
+ * @param msdInstance the msd class instance.
+ * @param pipeCallbackFn inner callback function.
+ * @param callbackFn callback function.
+ * @param callbackParam callback parameter.
+ * @param buffer buffer pointer.
+ * @param bufferLength buffer length.
+ * @param requestType request type.
+ * @param requestValue request value.
+ *
+ * @return An error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance,
+ host_inner_transfer_callback_t pipeCallbackFn,
+ transfer_callback_t callbackFn,
+ void *callbackParam,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ uint8_t requestType,
+ uint8_t requestValue);
+
+/*!
+ * @brief command process function, this function is called many time for one command's different state.
+ *
+ * @param msdInstance the msd class instance.
+ *
+ * @return An error code or kStatus_USB_Success.
+ */
+static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static void USB_HostMsdClearHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ if (status != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_TransferCancel);
+ }
+
+ if (msdInstance->commandStatus == kMSD_CommandErrorDone)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */
+ }
+ else
+ {
+ USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
+ }
+}
+
+static usb_status_t USB_HostMsdClearHalt(usb_host_msd_instance_t *msdInstance,
+ host_inner_transfer_callback_t callbackFn,
+ uint8_t endpoint)
+{
+ usb_status_t status;
+ usb_host_transfer_t *transfer;
+
+ /* malloc one transfer */
+ status = USB_HostMallocTransfer(msdInstance->hostHandle, &transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ return status;
+ }
+ /* save the application callback function */
+ msdInstance->controlCallbackFn = NULL;
+ msdInstance->controlCallbackParam = NULL;
+ /* initialize transfer */
+ transfer->callbackFn = callbackFn;
+ transfer->callbackParam = msdInstance;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_CLEAR_FEATURE;
+ transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(endpoint);
+ transfer->setupPacket.wLength = 0;
+ status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer);
+
+ if (status != kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+ }
+ msdInstance->controlTransfer = transfer;
+
+ return status;
+}
+
+static void USB_HostMsdResetDone(usb_host_msd_instance_t *msdInstance, usb_status_t status)
+{
+ if (msdInstance->internalResetRecovery == 1) /* internal mass reset recovery */
+ {
+ msdInstance->internalResetRecovery = 0;
+
+ if ((status != kStatus_USB_Success) || (msdInstance->commandStatus == kMSD_CommandErrorDone))
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error); /* command fail */
+ }
+ else
+ {
+ USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
+ }
+ }
+ else /* user call mass storage reset recovery */
+ {
+ if (msdInstance->controlCallbackFn != NULL)
+ {
+ msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0,
+ status); /* callback to application */
+ }
+ }
+}
+
+static void USB_HostMsdMassResetClearOutCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ msdInstance->controlTransfer = NULL;
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+ USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
+}
+
+static void USB_HostMsdMassResetClearInCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ msdInstance->controlTransfer = NULL;
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ if (msdInstance->outPipe != NULL)
+ {
+ /* continue to process mass storage reset */
+ USB_HostMsdClearHalt(
+ msdInstance, USB_HostMsdMassResetClearOutCallback,
+ (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->outPipe)->endpointAddress));
+ }
+ }
+ else
+ {
+ USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
+ }
+}
+
+static void USB_HostMsdMassResetCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ msdInstance->controlTransfer = NULL;
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+ if (status == kStatus_USB_Success)
+ {
+ if (msdInstance->inPipe != NULL)
+ {
+ /* continue to process mass storage reset */
+ USB_HostMsdClearHalt(msdInstance, USB_HostMsdMassResetClearInCallback,
+ (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress));
+ }
+ }
+ else
+ {
+ USB_HostMsdResetDone(msdInstance, status); /* mass storage reset done */
+ }
+}
+
+static void USB_HostMsdControlCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ msdInstance->controlTransfer = NULL;
+ if (msdInstance->controlCallbackFn != NULL)
+ {
+ msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status); /* callback to application */
+ }
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+}
+
+static void USB_HostMsdCommandDone(usb_host_msd_instance_t *msdInstance, usb_status_t status)
+{
+ if (msdInstance->commandCallbackFn != NULL)
+ {
+ /* callback to application */
+ msdInstance->commandCallbackFn(msdInstance->commandCallbackParam, msdInstance->msdCommand.dataBuffer,
+ msdInstance->msdCommand.dataSofar, status);
+ }
+ msdInstance->commandStatus = kMSD_CommandIdle;
+}
+
+static void USB_HostMsdCswCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ if (status == kStatus_USB_Success)
+ {
+ /* kStatus_USB_Success */
+ if ((transfer->transferSofar == 13) &&
+ (msdInstance->msdCommand.cswBlock.CSWSignature == USB_HOST_MSD_CSW_SIGNATURE))
+ {
+ switch (msdInstance->msdCommand.cswBlock.CSWStatus)
+ {
+ case 0:
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success);
+ break;
+
+ case 1:
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail);
+ break;
+
+ case 2:
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ break;
+
+ default:
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_MSDStatusFail);
+ break;
+ }
+ }
+ else
+ {
+ /* mass reset recovery to end ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ else
+ {
+ if (status == kStatus_USB_TransferStall) /* case 1: stall */
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--; /* retry reduce when error */
+ }
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ /* clear stall to continue the ufi command */
+ if (USB_HostMsdClearHalt(
+ msdInstance, USB_HostMsdClearHaltCallback,
+ (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
+ kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ else
+ {
+ /* mass reset recovery to continue ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
+ {
+ USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
+ }
+ else /* case 3: error */
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--; /* retry reduce when error */
+ }
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
+ }
+ else
+ {
+ /* mass reset recovery to continue ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ }
+}
+
+static void USB_HostMsdCbwCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ if (status == kStatus_USB_Success)
+ {
+ /* kStatus_USB_Success */
+ if (transfer->transferSofar == USB_HOST_UFI_CBW_LENGTH)
+ {
+ msdInstance->commandStatus = kMSD_CommandTransferData;
+ USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
+ }
+ else
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--;
+ }
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
+ }
+ else
+ {
+ /* mass reset recovery to continue ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (status == kStatus_USB_TransferStall) /* case 1: stall */
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--; /* retry reduce when error */
+ }
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ /* clear stall to continue the ufi command */
+ if (USB_HostMsdClearHalt(
+ msdInstance, USB_HostMsdClearHaltCallback,
+ (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
+ kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ else
+ {
+ /* mass reset recovery to continue ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
+ {
+ USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
+ }
+ else /* case 3: error */
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--;
+ }
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ USB_HostMsdProcessCommand(msdInstance); /* retry the last step transaction */
+ }
+ else
+ {
+ /* mass reset recovery to continue ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+ return;
+ }
+}
+
+static void USB_HostMsdDataCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+ uint8_t direction;
+
+ if (status == kStatus_USB_Success)
+ {
+ /* kStatus_USB_Success */
+ msdInstance->msdCommand.dataSofar += transfer->transferSofar;
+ USB_HostMsdProcessCommand(msdInstance); /* continue to process ufi command */
+ }
+ else
+ {
+ if (status == kStatus_USB_TransferStall) /* case 1: stall */
+ {
+ if (msdInstance->msdCommand.retryTime > 0)
+ {
+ msdInstance->msdCommand.retryTime--; /* retry reduce when error */
+ }
+ if (transfer->direction == USB_IN)
+ {
+ direction = USB_REQUEST_TYPE_DIR_IN;
+ }
+ else
+ {
+ direction = USB_REQUEST_TYPE_DIR_OUT;
+ }
+
+ if (msdInstance->msdCommand.retryTime == 0)
+ {
+ msdInstance->commandStatus = kMSD_CommandTransferCSW; /* next step */
+ }
+ /* clear stall to continue the ufi command */
+ if (USB_HostMsdClearHalt(msdInstance, USB_HostMsdClearHaltCallback,
+ (direction | ((usb_host_pipe_t *)msdInstance->inPipe)->endpointAddress)) !=
+ kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ else if (status == kStatus_USB_TransferCancel) /* case 2: cancel */
+ {
+ USB_HostMsdCommandDone(msdInstance, status); /* command cancel */
+ }
+ else /* case 3: error */
+ {
+ /* mass reset recovery to finish ufi command */
+ msdInstance->internalResetRecovery = 1;
+ msdInstance->commandStatus = kMSD_CommandErrorDone;
+ if (USB_HostMsdMassStorageReset(msdInstance, NULL, NULL) != kStatus_USB_Success)
+ {
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Error);
+ }
+ }
+ }
+}
+
+static usb_status_t USB_HostMsdProcessCommand(usb_host_msd_instance_t *msdInstance)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_transfer_t *transfer;
+
+ if (msdInstance->msdCommand.transfer == NULL)
+ {
+ /* malloc one transfer */
+ status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer));
+ if (status != kStatus_USB_Success)
+ {
+ msdInstance->msdCommand.transfer = NULL;
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ }
+ transfer = msdInstance->msdCommand.transfer;
+ switch (msdInstance->commandStatus)
+ {
+ case kMSD_CommandTransferCBW: /* ufi CBW phase */
+ transfer->direction = USB_OUT;
+ transfer->transferBuffer = (uint8_t *)(&(msdInstance->msdCommand.cbwBlock));
+ transfer->transferLength = USB_HOST_UFI_CBW_LENGTH;
+ transfer->callbackFn = USB_HostMsdCbwCallback;
+ transfer->callbackParam = msdInstance;
+ status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("host send error\r\n");
+#endif
+ }
+ break;
+
+ case kMSD_CommandTransferData: /* ufi DATA phase */
+ if (msdInstance->msdCommand.dataBuffer != NULL)
+ {
+ transfer->direction = msdInstance->msdCommand.dataDirection;
+ transfer->transferBuffer = (msdInstance->msdCommand.dataBuffer + msdInstance->msdCommand.dataSofar);
+ transfer->transferLength = (msdInstance->msdCommand.dataLength - msdInstance->msdCommand.dataSofar);
+ transfer->callbackParam = msdInstance;
+ if (msdInstance->msdCommand.dataSofar != msdInstance->msdCommand.dataLength)
+ {
+ if (transfer->direction == USB_OUT)
+ {
+ transfer->callbackFn = USB_HostMsdDataCallback;
+ status = USB_HostSend(msdInstance->hostHandle, msdInstance->outPipe, transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("host send error\r\n");
+#endif
+ }
+ }
+ else
+ {
+ transfer->callbackFn = USB_HostMsdDataCallback;
+ status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("host recv error\r\n");
+#endif
+ }
+ }
+ break;
+ }
+ else
+ {
+ /* don't break */
+ }
+ }
+ else
+ {
+ /* don't break */
+ }
+ case kMSD_CommandTransferCSW: /* ufi CSW phase */
+ transfer->direction = USB_IN;
+ transfer->transferBuffer = (uint8_t *)&msdInstance->msdCommand.cswBlock;
+ transfer->transferLength = sizeof(usb_host_csw_t);
+ transfer->callbackFn = USB_HostMsdCswCallback;
+ transfer->callbackParam = msdInstance;
+ status = USB_HostRecv(msdInstance->hostHandle, msdInstance->inPipe, transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("host recv error\r\n");
+#endif
+ }
+ break;
+
+ case kMSD_CommandDone:
+ USB_HostMsdCommandDone(msdInstance, kStatus_USB_Success);
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+
+/*!
+ * @brief all ufi function calls this api.
+ *
+ * This function implements the common ufi commands.
+ *
+ * @param classHandle the class msd handle.
+ * @param buffer buffer pointer.
+ * @param bufferLength buffer length.
+ * @param callbackFn callback function.
+ * @param callbackParam callback parameter.
+ * @param direction command direction.
+ * @param byteValues ufi command fields value.
+ *
+ * @return An error code or kStatus_USB_Success.
+ */
+usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam,
+ uint8_t direction,
+ uint8_t byteValues[10])
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
+ usb_host_cbw_t *cbwPointer = &(msdInstance->msdCommand.cbwBlock);
+ uint8_t index = 0;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (msdInstance->commandStatus != kMSD_CommandIdle)
+ {
+ return kStatus_USB_Busy;
+ }
+
+ /* save the application callback function */
+ msdInstance->commandCallbackFn = callbackFn;
+ msdInstance->commandCallbackParam = callbackParam;
+
+ /* initialize CBWCB fields */
+ for (index = 0; index < USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH; ++index)
+ {
+ cbwPointer->CBWCB[index] = byteValues[index];
+ }
+
+ /* initialize CBW fields */
+ cbwPointer->CBWDataTransferLength = USB_LONG_TO_LITTLE_ENDIAN(bufferLength);
+ cbwPointer->CBWFlags = direction;
+ cbwPointer->CBWLun = (byteValues[1] >> USB_HOST_UFI_LOGICAL_UNIT_POSITION);
+ cbwPointer->CBWCBLength = USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH;
+
+ msdInstance->commandStatus = kMSD_CommandTransferCBW;
+ if (direction == USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN)
+ {
+ msdInstance->msdCommand.dataDirection = USB_IN;
+ }
+ else
+ {
+ msdInstance->msdCommand.dataDirection = USB_OUT;
+ }
+ msdInstance->msdCommand.dataBuffer = buffer;
+
+ msdInstance->msdCommand.dataLength = bufferLength;
+ msdInstance->msdCommand.dataSofar = 0;
+ msdInstance->msdCommand.retryTime = USB_HOST_MSD_RETRY_MAX_TIME;
+
+ return USB_HostMsdProcessCommand(msdInstance); /* start to process ufi command */
+}
+
+static usb_status_t USB_HostMsdOpenInterface(usb_host_msd_instance_t *msdInstance)
+{
+ usb_status_t status;
+ uint8_t epIndex = 0;
+ usb_host_pipe_init_t pipeInit;
+ usb_descriptor_endpoint_t *epDesc = NULL;
+ usb_host_interface_t *interfacePointer;
+
+ if (msdInstance->inPipe != NULL) /* close bulk in pipe if the pipe is open */
+ {
+ status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ msdInstance->inPipe = NULL;
+ }
+ if (msdInstance->outPipe != NULL) /* close bulk out pipe if the pipe is open */
+ {
+ status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ msdInstance->outPipe = NULL;
+ }
+
+ /* open interface pipes */
+ interfacePointer = (usb_host_interface_t *)msdInstance->interfaceHandle;
+ for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
+ {
+ epDesc = interfacePointer->epList[epIndex].epDesc;
+ if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
+ USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
+ ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
+ {
+ pipeInit.devInstance = msdInstance->deviceHandle;
+ pipeInit.pipeType = USB_ENDPOINT_BULK;
+ pipeInit.direction = USB_IN;
+ pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipeInit.interval = epDesc->bInterval;
+ pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->inPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
+#endif
+ return status;
+ }
+ }
+ else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
+ USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
+ ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
+ {
+ pipeInit.devInstance = msdInstance->deviceHandle;
+ pipeInit.pipeType = USB_ENDPOINT_BULK;
+ pipeInit.direction = USB_OUT;
+ pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipeInit.interval = epDesc->bInterval;
+ pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ status = USB_HostOpenPipe(msdInstance->hostHandle, &msdInstance->outPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_host_hid_set_interface fail to open pipe\r\n");
+#endif
+ return status;
+ }
+ }
+ else
+ {
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+static void USB_HostMsdSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)param;
+
+ msdInstance->controlTransfer = NULL;
+ if (status == kStatus_USB_Success)
+ {
+ status = USB_HostMsdOpenInterface(msdInstance); /* msd open interface */
+ }
+
+ if (msdInstance->controlCallbackFn != NULL)
+ {
+ msdInstance->controlCallbackFn(msdInstance->controlCallbackParam, NULL, 0,
+ status); /* callback to application */
+ }
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+}
+
+usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
+{
+ uint32_t infoValue;
+ usb_status_t status;
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)USB_OsaMemoryAllocate(
+ sizeof(usb_host_msd_instance_t)); /* malloc msd class instance */
+
+ if (msdInstance == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ /* initialize msd instance */
+ msdInstance->deviceHandle = deviceHandle;
+ msdInstance->interfaceHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue);
+ msdInstance->hostHandle = (usb_host_handle)infoValue;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue);
+ msdInstance->controlPipe = (usb_host_pipe_handle)infoValue;
+
+ msdInstance->msdCommand.cbwBlock.CBWSignature = USB_LONG_TO_LITTLE_ENDIAN(USB_HOST_MSD_CBW_SIGNATURE);
+ status = USB_HostMallocTransfer(msdInstance->hostHandle, &(msdInstance->msdCommand.transfer));
+ if (status != kStatus_USB_Success)
+ {
+ msdInstance->msdCommand.transfer = NULL;
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ }
+
+ *classHandle = msdInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_status_t status = kStatus_USB_Error;
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ status = USB_HostOpenDeviceInterface(msdInstance->deviceHandle,
+ interfaceHandle); /* notify host driver the interface is open */
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+ msdInstance->interfaceHandle = interfaceHandle;
+
+ /* cancel transfers */
+ if (msdInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+ if (msdInstance->outPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+
+ if (alternateSetting == 0) /* open interface directly */
+ {
+ if (callbackFn != NULL)
+ {
+ status = USB_HostMsdOpenInterface(msdInstance);
+ callbackFn(callbackParam, NULL, 0, status);
+ }
+ }
+ else /* send setup transfer */
+ {
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ msdInstance->controlCallbackFn = callbackFn;
+ msdInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->callbackFn = USB_HostMsdSetInterfaceCallback;
+ transfer->callbackParam = msdInstance;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_INTERFACE;
+ transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(
+ ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
+ transfer->setupPacket.wLength = 0;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ status = USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ msdInstance->controlTransfer = transfer;
+ }
+ else
+ {
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+ }
+ }
+
+ return status;
+}
+
+usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
+ usb_status_t status;
+
+ if (classHandle != NULL)
+ {
+ if (msdInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->inPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->inPipe); /* close pipe */
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ }
+ if (msdInstance->outPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->outPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(msdInstance->hostHandle, msdInstance->outPipe); /* close pipe */
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ }
+ if ((msdInstance->controlPipe != NULL) &&
+ (msdInstance->controlTransfer != NULL)) /* cancel control transfer if there is on-going control transfer */
+ {
+ status =
+ USB_HostCancelTransfer(msdInstance->hostHandle, msdInstance->controlPipe, msdInstance->controlTransfer);
+ }
+ if (msdInstance->msdCommand.transfer)
+ {
+ USB_HostFreeTransfer(msdInstance->hostHandle, msdInstance->msdCommand.transfer);
+ }
+ USB_HostCloseDeviceInterface(deviceHandle,
+ msdInstance->interfaceHandle); /* notify host driver the interface is closed */
+ USB_OsaMemoryFree(msdInstance);
+ }
+ else
+ {
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostMsdControl(usb_host_msd_instance_t *msdInstance,
+ host_inner_transfer_callback_t pipeCallbackFn,
+ transfer_callback_t callbackFn,
+ void *callbackParam,
+ uint8_t *buffer,
+ uint16_t bufferLength,
+ uint8_t requestType,
+ uint8_t requestValue)
+{
+ usb_host_transfer_t *transfer;
+
+ if (msdInstance == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(msdInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ msdInstance->controlCallbackFn = callbackFn;
+ msdInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = pipeCallbackFn;
+ transfer->callbackParam = msdInstance;
+
+ transfer->setupPacket.bmRequestType = requestType;
+ transfer->setupPacket.bRequest = requestValue;
+ transfer->setupPacket.wValue = 0x0000;
+ transfer->setupPacket.wIndex =
+ ((usb_host_interface_t *)msdInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber;
+ transfer->setupPacket.wLength = bufferLength;
+
+ if (USB_HostSendSetup(msdInstance->hostHandle, msdInstance->controlPipe, transfer) !=
+ kStatus_USB_Success) /* call host driver api */
+ {
+ USB_HostFreeTransfer(msdInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ msdInstance->controlTransfer = transfer;
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
+
+ return USB_HostMsdControl(msdInstance, USB_HostMsdMassResetCallback, callbackFn, callbackParam, NULL, 0,
+ (USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE),
+ USB_HOST_HID_MASS_STORAGE_RESET);
+}
+
+usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle,
+ uint8_t *logicalUnitNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_msd_instance_t *msdInstance = (usb_host_msd_instance_t *)classHandle;
+
+ return USB_HostMsdControl(
+ msdInstance, USB_HostMsdControlCallback, callbackFn, callbackParam, logicalUnitNumber, 1,
+ (USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE),
+ USB_HOST_HID_GET_MAX_LUN);
+}
+
+#endif /* USB_HOST_CONFIG_MSD */
diff --git a/usb_1.1.0/host/class/usb_host_msd.h b/usb_1.1.0/host/class/usb_host_msd.h
new file mode 100644
index 0000000..b062d9a
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_msd.h
@@ -0,0 +1,872 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef _USB_HOST_MSD_H_
+#define _USB_HOST_MSD_H_
+
+/*******************************************************************************
+ * MSD class private structure, enumeration, macro
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* CBW and CSW Macros */
+#define USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT (0x00U)
+#define USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN (0x80U)
+#define USB_HOST_MSD_CBW_SIGNATURE (0x43425355U)
+#define USB_HOST_MSD_CSW_SIGNATURE (0x53425355U)
+
+/* UFI data bit macro */
+#define USB_HOST_UFI_BLOCK_DATA_VALID_LENGTH (10U)
+#define USB_HOST_UFI_LOGICAL_UNIT_POSITION (5U)
+#define USB_HOST_UFI_CBW_LENGTH (31U)
+#define USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT (6U)
+#define USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT (0U)
+#define USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT (1U)
+#define USB_HOST_UFI_START_STOP_UNIT_START_SHIFT (0U)
+#define USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT (2U)
+
+/*******************************************************************************
+ * MSD class public structure, enumeration, macro, function
+ ******************************************************************************/
+/*!
+ * @addtogroup usb_host_msc_drv
+ * @{
+ */
+
+/*! @brief retry time when transfer fail, when all the retries fail the transfer callback with error status */
+#define USB_HOST_MSD_RETRY_MAX_TIME (1U)
+/*! @brief mass storage block size */
+#define USB_HOST_MSD_BLOCK_SIZE (512U)
+
+/*! @brief MSD class code */
+#define USB_HOST_MSD_CLASS_CODE (8U)
+/*! @brief MSD sub-class code */
+#define USB_HOST_MSD_SUBCLASS_CODE_UFI (4U)
+/*! @brief MSD sub-class code */
+#define USB_HOST_MSD_SUBCLASS_CODE_SCSI (6U)
+/*! @brief MSD protocol code */
+#define USB_HOST_MSD_PROTOCOL_BULK (0x50U)
+
+/*! @brief MSD class-specific request (mass storage reset) */
+#define USB_HOST_HID_MASS_STORAGE_RESET (0xFFU)
+/*! @brief MSD class-specific request (get maximum logical unit number) */
+#define USB_HOST_HID_GET_MAX_LUN (0xFEU)
+
+/*! @brief UFI command process status */
+typedef enum _usb_host_msd_command_status
+{
+ kMSD_CommandIdle = 0,
+ kMSD_CommandTransferCBW,
+ kMSD_CommandTransferData,
+ kMSD_CommandTransferCSW,
+ kMSD_CommandDone,
+ kMSD_CommandCancel,
+ kMSD_CommandErrorDone,
+} usb_host_msd_command_status_t;
+
+/*! @brief MSC Bulk-Only command block wrapper (CBW) */
+typedef struct _usb_host_cbw
+{
+ uint32_t CBWSignature; /*!< Signature that helps identify this data packet as a CBW. The signature field shall
+ contain the value 43425355h (little endian), indicating a CBW */
+ uint32_t
+ CBWTag; /*!< A Command Block Tag sent by the host. The device shall echo the contents of this field back to the
+ host in the dCSWTag field of the associated CSW */
+ uint32_t CBWDataTransferLength; /*!< The number of bytes of data that the host expects to transfer on the Bulk-In or
+ Bulk-Out endpoint during the execution of this command */
+ uint8_t CBWFlags; /*!<
+ Bit 7 Direction - the device shall ignore this bit if the dCBWDataTransferLength field is
+ zero, otherwise:
+ 0 = Data-Out from host to the device,
+ 1 = Data-In from the device to the host.
+ Bit 6 Obsolete. The host shall set this bit to zero.
+ Bits 5..0 Reserved - the host shall set these bits to zero.
+ */
+ uint8_t CBWLun; /*!< The device Logical Unit Number (LUN) to which the command block is being sent */
+ uint8_t CBWCBLength; /*!< The valid length of the CBWCB in bytes. This defines the valid length of the command
+ block. The only legal values are 1 through 16 (01h through 10h).*/
+ uint8_t CBWCB[16]; /*!< The command block to be executed by the device*/
+} usb_host_cbw_t;
+
+/*! @brief MSC Bulk-Only command status wrapper (CSW) */
+typedef struct _usb_host_csw
+{
+ uint32_t CSWSignature; /*!< Signature that helps identify this data packet as a CSW. The signature field shall
+ contain the value 53425355h (little endian), indicating CSW.*/
+ uint32_t CSWTag; /*!< The device shall set this field to the value received in the dCBWTag of the associated CBW*/
+ uint32_t CSWDataResidue; /*!< the difference between the amount of data expected as stated in the
+ dCBWDataTransferLength and the actual amount of relevant data processed by the device.*/
+ uint8_t CSWStatus; /*!<
+ bCSWStatus indicates the success or failure of the command.
+ 00h - Command passed.
+ 01h - Command Failed.
+ 02h - Phase error.
+ others - Reserved.
+ */
+} usb_host_csw_t;
+
+/*! @brief MSC UFI command information structure */
+typedef struct _usb_host_msd_command
+{
+ usb_host_cbw_t cbwBlock; /*!< CBW data block*/
+ usb_host_csw_t cswBlock; /*!< CSW data block*/
+ uint8_t *dataBuffer; /*!< Data buffer pointer*/
+ uint32_t dataLength; /*!< Data buffer length*/
+ uint32_t dataSofar; /*!< Successful transfer data length*/
+ usb_host_transfer_t *transfer; /*!< The transfer is used for processing the UFI command*/
+ uint8_t retryTime; /*!< The UFI command residual retry time, when it reduce to zero the UFI command fail */
+ uint8_t dataDirection; /*!< The data direction, its value is USB_OUT or USB_IN*/
+} usb_host_msd_command_t;
+
+/*! @brief MSD instance structure, MSD usb_host_class_handle pointer to this structure */
+typedef struct _usb_host_msd_instance
+{
+ usb_host_handle hostHandle; /*!< This instance's related host handle*/
+ usb_device_handle deviceHandle; /*!< This instance's related device handle*/
+ usb_host_interface_handle interfaceHandle; /*!< This instance's related interface handle*/
+ usb_host_pipe_handle controlPipe; /*!< This instance's related device control pipe*/
+ usb_host_pipe_handle outPipe; /*!< MSD bulk out pipe*/
+ usb_host_pipe_handle inPipe; /*!< MSD bulk in pipe*/
+ transfer_callback_t commandCallbackFn; /*!< MSD UFI command callback function pointer*/
+ void *commandCallbackParam; /*!< MSD UFI command callback parameter*/
+ transfer_callback_t controlCallbackFn; /*!< MSD control transfer callback function pointer*/
+ void *controlCallbackParam; /*!< MSD control transfer callback parameter*/
+ usb_host_transfer_t *controlTransfer; /*!< Ongoing control transfer*/
+ usb_host_msd_command_t msdCommand; /*!< Ongoing MSD UFI command information*/
+ uint8_t commandStatus; /*!< UFI command process status, see command_status_t*/
+ uint8_t internalResetRecovery; /*!< 1 - class driver internal mass storage reset recovery is on-going; 0 -
+ application call USB_HostMsdMassStorageReset to reset or there is no reset*/
+} usb_host_msd_instance_t;
+
+/*! @brief UFI standard sense data structure */
+typedef struct _usb_host_ufi_sense_data
+{
+ uint8_t errorCode; /*!< This field shall contain a value of 70h to indicate current errors*/
+ uint8_t reserved1; /*!< Reserved field*/
+ uint8_t senseKey; /*!< Provide a hierarchy of error or command result information*/
+ uint8_t information[4]; /*!< This field is command-specific; it is typically used by some commands to return a
+ logical block address denoting where an error occurred*/
+ uint8_t additionalSenseLength; /*!< The UFI device sets the value of this field to ten, to indicate that ten more
+ bytes of sense data follow this field*/
+ uint8_t reserved2[4]; /*!< Reserved field*/
+ uint8_t additionalSenseCode; /*!< Provide a hierarchy of error or command result information*/
+ uint8_t additionalSenseCodeQualifier; /*!< Provide a hierarchy of error or command result information*/
+ uint8_t reserved3[4]; /*!< Reserved field*/
+} usb_host_ufi_sense_data_t;
+
+/*! @brief UFI standard inquiry data structure */
+typedef struct _usb_host_ufi_inquiry_data
+{
+ uint8_t peripheralDeviceType; /*!< Identifies the device currently connected to the requested logical unit*/
+ uint8_t removableMediaBit; /*!< This shall be set to one to indicate removable media*/
+ uint8_t version; /*!< Version*/
+ uint8_t responseDataFormat; /*!< A value of 01h shall be used for UFI device*/
+ uint8_t additionalLength; /*!< Specify the length in bytes of the parameters*/
+ uint8_t reserved1[3]; /*!< Reserved field*/
+ uint8_t vendorInformation[8]; /*!< Contains 8 bytes of ASCII data identifying the vendor of the product*/
+ uint8_t productIdentification[16]; /*!< Contains 16 bytes of ASCII data as defined by the vendor*/
+ uint8_t productRevisionLevel[4]; /*!< Contains 4 bytes of ASCII data as defined by the vendor*/
+} usb_host_ufi_inquiry_data_t;
+
+/*! @brief UFI read capacity data structure */
+typedef struct _usb_host_ufi_read_capacity
+{
+ uint8_t lastLogicalBlockAddress[4]; /*!< The logical block number*/
+ uint8_t blockLengthInBytes[4]; /*!< Block size*/
+} usb_host_ufi_read_capacity_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @name USB host MSD class APIs
+ * @{
+ */
+
+/*!
+ * @brief Initializes the MSD instance.
+ *
+ * This function allocates the resources for the MSD instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[out] classHandle Return class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+extern usb_status_t USB_HostMsdInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief Sets the interface.
+ *
+ * This function binds the interface with the MSD instance.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceHandle The interface handle.
+ * @param[in] alternateSetting The alternate setting value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Success Callback return status, the command succeeded.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostMsdSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Deinitializes the MSD instance.
+ *
+ * This function frees the resource for the MSD instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[in] classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is de-initialized successfully.
+ */
+extern usb_status_t USB_HostMsdDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Mass storage reset.
+ *
+ * This function implements the mass storage reset request.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostMsdMassStorageReset(usb_host_class_handle classHandle,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Gets the maximum logical unit number.
+ *
+ * This function implements the get maximum LUN request.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[out] logicalUnitNumber Return logical unit number value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdGetMaxLun(usb_host_class_handle classHandle,
+ uint8_t *logicalUnitNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage read (10).
+ *
+ * This function implements the UFI READ(10) command. This command requests that the UFI
+ * device transfer data to the host.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] blockNumber Read block number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage read (12).
+ *
+ * This function implements the UFI READ(12) command and requests that the UFI
+ * device transfer data to the host.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] blockNumber Read block number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage write (10).
+ *
+ * This function implements the UFI WRITE(10) command and requests that the UFI device
+ * write the data transferred by the host to the medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[in] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] blockNumber Write block number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage write (12).
+ *
+ * This function implements the UFI WRITE(12) command and requests that the UFI device
+ * write the data transferred by the host to the medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[in] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] blockNumber Write block number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage read capacity.
+ *
+ * This function implements the UFI READ CAPACITY command and allows the host to request
+ * capacities of the currently installed medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage test unit ready.
+ *
+ * This function implements the UFI TEST UNIT READY command and
+ * checks if the UFI device is ready.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief mass storage request sense.
+ *
+ * This function implements the UFI REQUEST SENSE command, this command instructs
+ * the UFI device to transfer sense data to the host for the specified logical unit.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage mode select.
+ *
+ * This function implements the UFI MODE SELECT command and allows the host
+ * to specify medium or device parameters to the UFI device.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage mode sense.
+ *
+ * This function implements the UFI MODE SENSE command and allows the UFI
+ * device to report medium or device parameters to the host.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] pageControl The page control field specifies the type of mode parameters to return.
+ * @param[in] pageCode Buffer pointer.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t pageControl,
+ uint8_t pageCode,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage inquiry.
+ *
+ * This function implements the UFI INQUIRY command and requests that information regarding
+ * parameters of the UFI device itself be sent to the host.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage read format capacities.
+ *
+ * This function implements the UFI READ FORMAT CAPACITIES command and allows the host to request
+ * a list of the possible capacities that can be formatted on the currently installed medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[out] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage format unit.
+ *
+ * This function implements the UFI FORMAT UNIT command and the host sends this command to physically format one
+ * track of a diskette according to the selected options.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] trackNumber This specifies which track is to be formatted.
+ * @param[in] interLeave This specifies the interleave that shall be used for formatting.
+ * @param[in] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t trackNumber,
+ uint16_t interLeave,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage prevents/allows a medium removal.
+ *
+ * This function implements the UFI PREVENT-ALLOW MEDIUM REMOVAL command and notifies the FUI device
+ * to enable or disable the removal of the medium in the logical unit.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] prevent Prevent or allow
+ * - 0: enable (allow) the removal of the medium
+ * - 1: disable (prevent) removal of the medium
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t prevent,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage write and verify.
+ *
+ * This function implements the UFI WRITE AND VERIFY command and requests that the UFI device
+ * writes the data transferred by the host to the medium, then verifies the data on the medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[in] buffer Buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] blockNumber Write and verify block number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage start stop unit.
+ *
+ * This function implements the UFI START-STOP UNIT command and instructs the UFI device
+ * to enable or disable media access operations .
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] loadEject A Load Eject (LoEj) bit of zero requests that no eject action be performed. A LoEj bit of
+ * one, with the
+ * Start bit cleared to zero, which instructs the UFI device to eject the media.
+ * @param[in] start A Start bit of one instructs the UFI device to enable media access operations. A Start bit
+ * of zero instructs the UFI device to disable media access operations.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t loadEject,
+ uint8_t start,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage verify.
+ *
+ * This function implements the UFI VERIFY command and requests that the UFI device
+ * verify the data on the medium.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[in] verificationLength The data length that need to be verified.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint16_t verificationLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage rezero.
+ *
+ * This function implements the UFI REZERO UNIT command. This command positions the head of
+ * the drive to the cylinder 0.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage seek(10).
+ *
+ * This function implements the UFI SEEK(10) command and requests that the UFI device
+ * seek to the specified Logical Block Address.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] blockAddress The start block address.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Mass storage send diagnostic.
+ *
+ * This function implements the UFI SEND DIAGNOSTIC command. This command requests the UFI device
+ * to do a reset or perform a self-test.
+ *
+ * @param[in] classHandle The class MSD handle.
+ * @param[in] logicalUnit Logical unit number.
+ * @param[in] selfTest 0 = perform special diagnostic test; 1 = perform default self-test.
+ * @param[in] callbackFn This callback is called after this command completes.
+ * @param[in] 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 The previous command is executing or there is no idle transfer.
+ * @retval kStatus_USB_Error Send transfer fail. See the USB_HostSend/USB_HostRecv.
+ * @retval kStatus_USB_Success Callback return status, the command succeed.
+ * @retval kStatus_USB_MSDStatusFail Callback return status, the CSW status indicate this command fail.
+ * @retval kStatus_USB_Error Callback return status, the command fail.
+ */
+extern usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t selfTest,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_MSD_H_ */
diff --git a/usb_1.1.0/host/class/usb_host_msd_ufi.c b/usb_1.1.0/host/class/usb_host_msd_ufi.c
new file mode 100644
index 0000000..0e47e79
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_msd_ufi.c
@@ -0,0 +1,473 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "usb_host_config.h"
+#if ((defined USB_HOST_CONFIG_MSD) && (USB_HOST_CONFIG_MSD))
+#include "usb_host.h"
+#include "usb_host_msd.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/* UFI command code */
+#define UFI_FORMAT_UNIT (0x04U)
+#define UFI_INQUIRY (0x12U)
+#define UFI_START_STOP (0x1BU)
+#define UFI_MODE_SELECT (0x55U)
+#define UFI_MODE_SENSE (0x5AU)
+#define UFI_MEDIUM_REMOVAL (0x1EU)
+#define UFI_READ10 (0x28U)
+#define UFI_READ12 (0xA8U)
+#define UFI_READ_CAPACITY (0x25U)
+#define UFI_READ_FORMAT_CAPACITY (0x23U)
+#define UFI_REQUEST_SENSE (0x03U)
+#define UFI_REZERO_UINT (0x01U)
+#define UFI_SEEK (0x2BU)
+#define UFI_SEND_DIAGNOSTIC (0x1DU)
+#define UFI_TEST_UNIT_READY (0x00U)
+#define UFI_VERIFY (0x2FU)
+#define UFI_WRITE10 (0x2AU)
+#define UFI_WRITE12 (0xAAU)
+#define UFI_WRITE_VERIFY (0x2EU)
+
+#define GET_BYTE_FROM_LE_LONG(b, n) \
+ ((uint8_t)((USB_LONG_TO_LITTLE_ENDIAN(b)) >> (n * 8))) /* get the byte from the long value */
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+extern usb_status_t USB_HostMsdCommand(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam,
+ uint8_t direction,
+ uint8_t byteValues[10]);
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+usb_status_t USB_HostMsdRead10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_READ10,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(blockNumber, 1),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdRead12(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_READ12,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 3),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 2),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 1),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdWrite10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_WRITE10,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(blockNumber, 1),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
+}
+
+usb_status_t USB_HostMsdWrite12(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_WRITE12,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 3),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 2),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 1),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 0)};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
+}
+
+usb_status_t USB_HostMsdReadCapacity(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_READ_CAPACITY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdTestUnitReady(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_TEST_UNIT_READY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdRequestSense(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_REQUEST_SENSE,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ (uint8_t)bufferLength,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdModeSelect(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_MODE_SELECT,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(bufferLength, 1),
+ GET_BYTE_FROM_LE_LONG(bufferLength, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
+}
+
+usb_status_t USB_HostMsdModeSense(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t pageControl,
+ uint8_t pageCode,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_MODE_SENSE, (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ (uint8_t)(((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CONTROL_SHIFT) |
+ ((uint32_t)pageCode << USB_HOST_UFI_MODE_SENSE_PAGE_CODE_SHIFT)),
+ 0x00, 0x00, 0x00, 0x00, GET_BYTE_FROM_LE_LONG(bufferLength, 1),
+ GET_BYTE_FROM_LE_LONG(bufferLength, 0), 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdInquiry(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_INQUIRY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ (uint8_t)bufferLength,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdReadFormatCapacities(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_READ_FORMAT_CAPACITY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(bufferLength, 1),
+ GET_BYTE_FROM_LE_LONG(bufferLength, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_IN, ufiBytes);
+}
+
+usb_status_t USB_HostMsdFormatUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t trackNumber,
+ uint16_t interLeave,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_FORMAT_UNIT,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ trackNumber,
+ GET_BYTE_FROM_LE_LONG(interLeave, 1),
+ GET_BYTE_FROM_LE_LONG(interLeave, 0),
+ 0x00,
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(bufferLength, 1),
+ GET_BYTE_FROM_LE_LONG(bufferLength, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
+}
+
+usb_status_t USB_HostMsdPreventAllowRemoval(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t prevent,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_MEDIUM_REMOVAL,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ prevent,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdWriteAndVerify(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ uint32_t blockNumber,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_WRITE_VERIFY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(blockNumber, 1),
+ GET_BYTE_FROM_LE_LONG(blockNumber, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, buffer, bufferLength, callbackFn, callbackParam,
+ USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT, ufiBytes);
+}
+
+usb_status_t USB_HostMsdStartStopUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t loadEject,
+ uint8_t start,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_START_STOP, (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION), 0x00, 0x00,
+ (uint8_t)(((uint32_t)loadEject << USB_HOST_UFI_START_STOP_UNIT_LOEJ_SHIFT) |
+ ((uint32_t)start << USB_HOST_UFI_START_STOP_UNIT_START_SHIFT)),
+ 0x00, 0x00, 0x00, 0x00, 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdVerify(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ uint16_t verificationLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_VERIFY,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ 0x00,
+ GET_BYTE_FROM_LE_LONG(verificationLength, 1),
+ GET_BYTE_FROM_LE_LONG(verificationLength, 0),
+ 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdRezeroUnit(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_REZERO_UINT,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdSeek10(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint32_t blockAddress,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_SEEK,
+ (uint8_t)(logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 3),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 2),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 1),
+ GET_BYTE_FROM_LE_LONG(blockAddress, 0),
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+usb_status_t USB_HostMsdSendDiagnostic(usb_host_class_handle classHandle,
+ uint8_t logicalUnit,
+ uint8_t selfTest,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ uint8_t ufiBytes[] = {UFI_REZERO_UINT,
+ (uint8_t)(((uint32_t)logicalUnit << USB_HOST_UFI_LOGICAL_UNIT_POSITION) |
+ ((uint32_t)selfTest << USB_HOST_UFI_SEND_DIAGNOSTIC_SELF_TEST_SHIFT)),
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ return USB_HostMsdCommand(classHandle, NULL, 0, callbackFn, callbackParam, USB_HOST_MSD_CBW_FLAGS_DIRECTION_OUT,
+ ufiBytes);
+}
+
+#endif /* USB_HOST_CONFIG_MSD */
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
diff --git a/usb_1.1.0/host/class/usb_host_phdc.h b/usb_1.1.0/host/class/usb_host_phdc.h
new file mode 100644
index 0000000..4b62b6b
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_phdc.h
@@ -0,0 +1,329 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+#ifndef __USB_HOST_PHDC_H__
+#define __USB_HOST_PHDC_H__
+
+/*******************************************************************************
+ * PHDC class public structure, enumeration, macro, function
+ ******************************************************************************/
+/*!
+ * @addtogroup usb_host_phdc_drv
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief PHDC class code */
+#define USB_HOST_PHDC_CLASS_CODE (0x0FU)
+/*! @brief PHDC sub class code */
+#define USB_HOST_PHDC_SUBCLASS_CODE (0x00U)
+/*! @brief PHDC protocol */
+#define USB_HOST_PHDC_PROTOCOL (0x00U)
+/*! @brief PHDC get status request */
+#define USB_HOST_PHDC_GET_STATUS_REQUEST (0x00U)
+/*! @brief PHDC set feature request */
+#define USB_HOST_PHDC_SET_FEATURE_REQUEST (0x03U)
+/*! @brief PHDC clear feature request */
+#define USB_HOST_PHDC_CLEAR_FEATURE_REQUEST (0x01U)
+/*! @brief PHDC meta-data feature */
+#define USB_HOST_PHDC_FEATURE_METADATA (0x01U)
+/*! @brief PHDC QoS information encoding feature */
+#define USB_HOST_PHDC_QOS_ENCODING_VERSION (0x01U)
+
+/*! @brief meta-data message preamble signature size */
+#define USB_HOST_PHDC_MESSAGE_PREAMBLE_SIGNATURE_SIZE (0x10U)
+
+/*! @brief PHDC class function descriptor type */
+#define USB_HOST_PHDC_CLASSFUNCTION_DESCRIPTOR (0x20U)
+/*! @brief PHDC QoS descriptor type */
+#define USB_HOST_PHDC_QOS_DESCRIPTOR (0x21U)
+/*! @brief PHDC function extension descriptor type */
+#define USB_HOST_PHDC_11073PHD_FUNCTION_DESCRIPTOR (0x30U)
+/*! @brief PHDC meta-data descriptor type */
+#define USB_HOST_PHDC_METADATA_DESCRIPTOR (0x22U)
+
+/*! @brief PHDC class function descriptor structure as defined by the PHDC class specification */
+typedef struct _usb_host_phdc_class_function_desciptor
+{
+ uint8_t bLength; /*!< Class function descriptor length */
+ uint8_t bDescriptortype; /*!< PHDC_CLASSFUNCTION_DESCRIPTOR type */
+ uint8_t bPhdcDataCode; /*!< Data/Messaging format code */
+ uint8_t bmCapability; /*!< If bit 0 is 1 the meta-data message preamble is implemented and 0 if it is not */
+} usb_host_phdc_class_function_desciptor_t;
+
+/*! @brief Function extension descriptor (device specialization) structure as defined by the PHDC class specification.
+ */
+typedef struct _usb_host_phdc_function_extension_descriptor
+{
+ uint8_t bLength; /*!< Function extension descriptor length */
+ uint8_t bDescriptortype; /*!< PHDC_CLASSFUNCTION_DESCRIPTOR type */
+ uint8_t bReserved; /*!< Reserved for future use */
+ uint8_t bNumDevSpecs; /*!< Number of wDevSpecializations */
+ uint16_t *wDevSpecializations; /*!< Variable length list that defines the device specialization */
+} usb_host_phdc_function_extension_descriptor_t;
+
+/*! @brief QoS descriptor structure as defined by the PHDC class specification. */
+typedef struct _usb_host_phdc_qos_descriptor
+{
+ uint8_t bLength; /*!< QoS descriptor length */
+ uint8_t bDescriptortype; /*!< PHDC_QOS_DESCRIPTOR type */
+ uint8_t bQosEncodingVersion; /*!< Version of QoS information encoding */
+ uint8_t bmLatencyReliability; /*!< Latency/reliability bin for the QoS data */
+} usb_host_phdc_qos_descriptor_t;
+
+/*! @brief Metadata descriptor structure as defined by the PHDC class specification. */
+typedef struct _usb_host_phdc_metadata_descriptor
+{
+ uint8_t bLength; /*!< Metadata descriptor length */
+ uint8_t bDescriptortype; /*!< Descriptor type */
+ uint8_t *bOpaqueData; /*!< Opaque metadata */
+} usb_host_phdc_metadata_descriptor_t;
+
+/*! @brief Metadata message preamble structure as defined by the PHDC class specification. */
+typedef struct _usb_host_phdc_metadata_preamble
+{
+ uint8_t
+ aSignature[USB_HOST_PHDC_MESSAGE_PREAMBLE_SIGNATURE_SIZE]; /*!< Constant used to give preamble verifiability */
+ uint8_t bNumberTransfers; /*!< Count of following transfer to which the QoS setting applies */
+ uint8_t bQosEncodingVersion; /*!< Version of QoS information encoding */
+ uint8_t bmLatencyReliability; /*!< See latency/reliability bin for the QoS data */
+ uint8_t bOpaqueDataSize; /*!< Opaque QoS data or meta-data size */
+ uint8_t *bOpaqueData; /*!< Opaque metadata */
+} usb_host_phdc_metadata_preamble_t;
+
+/*! @brief PHDC instance structure */
+typedef struct _usb_host_phdc_instance
+{
+ usb_host_handle hostHandle; /*!< The host handle */
+ usb_device_handle deviceHandle; /*!< The device handle */
+ usb_host_interface_handle interfaceHandle; /*!< The interface handle */
+ usb_host_pipe_handle controlPipe; /*!< The control pipe */
+ usb_host_pipe_handle interruptPipe; /*!< The interrupt pipe */
+ usb_host_pipe_handle bulkInPipe; /*!< The bulk in pipe */
+ usb_host_pipe_handle bulkOutPipe; /*!< The bulk out pipe */
+ transfer_callback_t inCallbackFn; /*!< The callback function is called when the PHDC receives complete */
+ void *inCallbackParam; /*!< The first parameter of the in callback function */
+ transfer_callback_t outCallbackFn; /*!< The callback function is called when the PHDC sends complete */
+ void *outCallbackParam; /*!< The first parameter of the out callback function */
+ transfer_callback_t controlCallbackFn; /*!< The control callback function */
+ void *controlCallbackParam; /*!< The first parameter of the control callback function */
+ usb_host_transfer_t *controlTransfer; /*!< The control transfer pointer */
+
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+ uint8_t *stallDataBuffer; /*!< keep the data buffer for stall transfer's data*/
+ uint32_t stallDataLength; /*!< keep the data length for stall transfer's data*/
+#endif
+
+ usb_host_ep_t interruptInEndpointInformation; /*!< The interrupt in information */
+ usb_host_ep_t bulkInEndpointInformation; /*!< The bulk in information */
+ usb_host_ep_t bulkOutEndpointInformation; /*!< The bulk out information */
+ uint8_t isMessagePreambleEnabled; /*!< The flag is used to check the message preamble feature is enabled or not */
+ uint8_t numberTransferBulkOut; /*!< The number of transfer that follow Meta-data Message Preamble */
+ uint8_t numberTransferBulkIn; /*!< The number of transfer that follow Meta-data Message Preamble */
+} usb_host_phdc_instance_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host PHDC class APIs
+ * @{
+ */
+
+/*!
+ * @brief Initializes 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.
+ */
+extern usb_status_t USB_HostPhdcInit(usb_host_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief Sets an 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostPhdcSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Deinitializes the PHDC instance.
+ *
+ * This function frees the resource for the PHDC instance.
+ *
+ * @param deviceHandle The device handle.
+ * @param classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is deinitialized successfully.
+ */
+extern usb_status_t USB_HostPhdcDeinit(usb_host_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Receives data.
+ *
+ * This function implements the 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. See the USB_HostRecv.
+ */
+extern 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);
+
+/*!
+ * @brief Sends data.
+ *
+ * This function implements the 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostPhdcSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief PHDC sends the control request.
+ *
+ * @param classHandle The class handle.
+ * @param request 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostPhdcSendControlRequest(usb_host_class_handle classHandle,
+ uint8_t request,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief PHDC set and clear feature endpoint halt request.
+ *
+ * @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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostPhdcSetClearFeatureEndpointHalt(usb_host_class_handle classHandle,
+ uint8_t request,
+ void *param,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief USB_HostPhdcGetEndpointInformation.
+ * This function returns the PHDC endpoint information structure, which contains an endpoint
+ * descriptor and an 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);
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_PHDC_H_ */
diff --git a/usb_1.1.0/host/class/usb_host_printer.c b/usb_1.1.0/host/class/usb_host_printer.c
new file mode 100644
index 0000000..5a10038
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_printer.c
@@ -0,0 +1,775 @@
+/*
+ * Copyright (c) 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_PRINTER) && (USB_HOST_CONFIG_PRINTER))
+#include "usb_host.h"
+#include "usb_host_printer.h"
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief printer in pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostPrinterInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief printer out pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostPrinterOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief printer control pipe transfer callback.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostPrinterControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief printer open interface. It is called when set interface request success or open alternate setting 0 interface.
+ *
+ * @param printerInstance printer instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostPrinterOpenInterface(usb_host_printer_instance_t *printerInstance);
+
+/*!
+ * @brief printer set interface callback, open pipes.
+ *
+ * @param param callback parameter.
+ * @param transfer callback transfer.
+ * @param status transfer status.
+ */
+static void USB_HostPrinterSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief printer send control transfer common code.
+ *
+ * @param classHandle the class handle.
+ * @param requestType setup packet request type.
+ * @param request setup packet request value.
+ * @param wvalue setup packet wValue.
+ * @param windex setup packet wIndex.
+ * @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.
+ */
+static usb_status_t USB_HostPrinterControl(usb_host_printer_instance_t *printerInstance,
+ uint8_t requestType,
+ uint8_t request,
+ uint16_t wvalue,
+ uint16_t windex,
+ uint16_t wlength,
+ uint8_t *data,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+static void USB_HostPrinterClearInHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
+
+ if (printerInstance->inCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->inCallbackFn(printerInstance->outCallbackParam, printerInstance->stallDataBuffer,
+ printerInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+static void USB_HostPrinterClearOutHaltCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
+
+ if (printerInstance->outCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->outCallbackFn(printerInstance->outCallbackParam, printerInstance->stallDataBuffer,
+ printerInstance->stallDataLength, kStatus_USB_TransferStall);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+static void USB_HostPrinterClearHalt(usb_host_printer_instance_t *printerInstance,
+ 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(printerInstance->hostHandle, &transfer);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate transfer error\r\n");
+#endif
+ return status;
+ }
+ printerInstance->stallDataBuffer = stallTransfer->transferBuffer;
+ printerInstance->stallDataLength = stallTransfer->transferSofar;
+ /* save the application callback function */
+ printerInstance->controlCallbackFn = NULL;
+ printerInstance->controlCallbackParam = NULL;
+ /* initialize transfer */
+ transfer->callbackFn = callbackFn;
+ transfer->callbackParam = printerInstance;
+ 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(printerInstance->hostHandle, printerInstance->controlPipe, transfer);
+
+ if (status != kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ }
+ printerInstance->controlTransfer = transfer;
+
+ return status;
+}
+#endif
+
+static void USB_HostPrinterInPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_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_HostPrinterClearHalt(
+ printerInstance, transfer, USB_HostPrinterClearInHaltCallback,
+ (USB_REQUEST_TYPE_DIR_IN | ((usb_host_pipe_t *)printerInstance->inPipe)->endpointAddress)) ==
+ kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+
+ if (printerInstance->inCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->inCallbackFn(printerInstance->inCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+static void USB_HostPrinterOutPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_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_HostPrinterClearHalt(
+ printerInstance, transfer, USB_HostPrinterClearOutHaltCallback,
+ (USB_REQUEST_TYPE_DIR_OUT | ((usb_host_pipe_t *)printerInstance->outPipe)->endpointAddress)) ==
+ kStatus_USB_Success)
+ {
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ return;
+ }
+ }
+#endif
+ if (printerInstance->outCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->outCallbackFn(printerInstance->outCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+static void USB_HostPrinterControlPipeCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
+
+ printerInstance->controlTransfer = NULL;
+ if (printerInstance->controlCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->controlCallbackFn(printerInstance->controlCallbackParam, transfer->transferBuffer,
+ transfer->transferSofar, status);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+static usb_status_t USB_HostPrinterOpenInterface(usb_host_printer_instance_t *printerInstance)
+{
+ usb_status_t status;
+ uint8_t epIndex = 0;
+ usb_host_pipe_init_t pipeInit;
+ usb_descriptor_endpoint_t *epDesc = NULL;
+ usb_host_interface_t *interfacePointer;
+
+ if (printerInstance->inPipe != NULL)
+ {
+ status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->inPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ printerInstance->inPipe = NULL;
+ }
+ if (printerInstance->outPipe != NULL) /* close interrupt out pipe if it is open */
+ {
+ status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->outPipe);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ printerInstance->outPipe = NULL;
+ }
+
+ /* open interface pipes */
+ interfacePointer = (usb_host_interface_t *)printerInstance->interfaceHandle;
+ for (epIndex = 0; epIndex < interfacePointer->epCount; ++epIndex)
+ {
+ epDesc = interfacePointer->epList[epIndex].epDesc;
+ if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
+ USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) &&
+ ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
+ {
+ pipeInit.devInstance = printerInstance->deviceHandle;
+ pipeInit.pipeType = USB_ENDPOINT_BULK;
+ pipeInit.direction = USB_IN;
+ pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipeInit.interval = epDesc->bInterval;
+ pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ printerInstance->inPacketSize = pipeInit.maxPacketSize;
+
+ status = USB_HostOpenPipe(printerInstance->hostHandle, &printerInstance->inPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("USB_HostPrinterSetInterface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ }
+ else if (((epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) ==
+ USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) &&
+ ((epDesc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_BULK))
+ {
+ pipeInit.devInstance = printerInstance->deviceHandle;
+ pipeInit.pipeType = USB_ENDPOINT_BULK;
+ pipeInit.direction = USB_OUT;
+ pipeInit.endpointAddress = (epDesc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK);
+ pipeInit.interval = epDesc->bInterval;
+ pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK);
+ pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(epDesc->wMaxPacketSize) &
+ USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK);
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+
+ printerInstance->outPacketSize = pipeInit.maxPacketSize;
+
+ status = USB_HostOpenPipe(printerInstance->hostHandle, &printerInstance->outPipe, &pipeInit);
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("USB_HostPrinterSetInterface fail to open pipe\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ }
+ else
+ {
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+static void USB_HostPrinterSetInterfaceCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)param;
+
+ printerInstance->controlTransfer = NULL;
+ if (status == kStatus_USB_Success)
+ {
+ status = USB_HostPrinterOpenInterface(printerInstance); /* printer open interface */
+ }
+
+ if (printerInstance->controlCallbackFn != NULL)
+ {
+ /* callback to application */
+ printerInstance->controlCallbackFn(printerInstance->controlCallbackParam, NULL, 0, status);
+ }
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+}
+
+usb_status_t USB_HostPrinterInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle)
+{
+ uint32_t infoValue;
+ /* malloc printer class instance */
+ usb_host_printer_instance_t *printerInstance =
+ (usb_host_printer_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_printer_instance_t));
+
+ if (printerInstance == NULL)
+ {
+ return kStatus_USB_AllocFail;
+ }
+
+ /* initialize printer instance */
+ printerInstance->deviceHandle = deviceHandle;
+ printerInstance->interfaceHandle = NULL;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetHostHandle, &infoValue);
+ printerInstance->hostHandle = (usb_host_handle)infoValue;
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceControlPipe, &infoValue);
+ printerInstance->controlPipe = (usb_host_pipe_handle)infoValue;
+
+ *classHandle = printerInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostPrinterSetInterface(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_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ /* notify host driver the interface is open */
+ status = USB_HostOpenDeviceInterface(printerInstance->deviceHandle, interfaceHandle);
+ if (status != kStatus_USB_Success)
+ {
+ return status;
+ }
+ printerInstance->interfaceHandle = interfaceHandle;
+
+ /* cancel transfers */
+ if (printerInstance->inPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->inPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+ if (printerInstance->outPipe != NULL)
+ {
+ status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->outPipe, NULL);
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when cancel pipe\r\n");
+#endif
+ }
+ }
+
+ if (alternateSetting == 0) /* open interface directly */
+ {
+ if (callbackFn != NULL)
+ {
+ status = USB_HostPrinterOpenInterface(printerInstance);
+ callbackFn(callbackParam, NULL, 0, status);
+ }
+ }
+ else /* send setup transfer */
+ {
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(printerInstance->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 */
+ printerInstance->controlCallbackFn = callbackFn;
+ printerInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->callbackFn = USB_HostPrinterSetInterfaceCallback;
+ transfer->callbackParam = printerInstance;
+ 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 *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting);
+ transfer->setupPacket.wLength = 0;
+ transfer->transferBuffer = NULL;
+ transfer->transferLength = 0;
+ status = USB_HostSendSetup(printerInstance->hostHandle, printerInstance->controlPipe, transfer);
+
+ if (status == kStatus_USB_Success)
+ {
+ printerInstance->controlTransfer = transfer;
+ }
+ else
+ {
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ }
+ }
+
+ return status;
+}
+
+usb_status_t USB_HostPrinterDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle)
+{
+ usb_status_t status;
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (classHandle != NULL) /* class instance has initialized */
+ {
+ if (printerInstance->inPipe != NULL)
+ {
+ status =
+ USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->inPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->inPipe); /* close pipe */
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ printerInstance->inPipe = NULL;
+ }
+ if (printerInstance->outPipe != NULL)
+ {
+ status =
+ USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->outPipe, NULL); /* cancel pipe */
+ status = USB_HostClosePipe(printerInstance->hostHandle, printerInstance->outPipe); /* close pipe */
+
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ printerInstance->outPipe = NULL;
+ }
+ if ((printerInstance->controlPipe != NULL) &&
+ (printerInstance->controlTransfer !=
+ NULL)) /* cancel control transfer if there is on-going control transfer */
+ {
+ status = USB_HostCancelTransfer(printerInstance->hostHandle, printerInstance->controlPipe,
+ printerInstance->controlTransfer);
+ }
+ USB_HostCloseDeviceInterface(deviceHandle,
+ printerInstance->interfaceHandle); /* notify host driver the interface is closed */
+ USB_OsaMemoryFree(printerInstance);
+ }
+ else
+ {
+ USB_HostCloseDeviceInterface(deviceHandle, NULL);
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostPrinterRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (printerInstance->inPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ printerInstance->inCallbackFn = callbackFn;
+ printerInstance->inCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostPrinterInPipeCallback;
+ transfer->callbackParam = printerInstance;
+
+ /* call host driver api */
+ if (USB_HostRecv(printerInstance->hostHandle, printerInstance->inPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("fail to USB_HostRecv\r\n");
+#endif
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+uint16_t USB_HostPrinterGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction)
+{
+ usb_host_printer_instance_t *phdcInstance = (usb_host_printer_instance_t *)classHandle;
+ if (classHandle == NULL)
+ {
+ return 0;
+ }
+
+ if (pipeType == USB_ENDPOINT_INTERRUPT)
+ {
+ if (direction == USB_IN)
+ {
+ return phdcInstance->inPacketSize;
+ }
+ else
+ {
+ return phdcInstance->outPacketSize;
+ }
+ }
+
+ return 0;
+}
+
+usb_status_t USB_HostPrinterSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+ usb_host_transfer_t *transfer;
+
+ if (classHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (printerInstance->outPipe == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* malloc one transfer */
+ if (USB_HostMallocTransfer(printerInstance->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 */
+ printerInstance->outCallbackFn = callbackFn;
+ printerInstance->outCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLength;
+ transfer->callbackFn = USB_HostPrinterOutPipeCallback;
+ transfer->callbackParam = printerInstance;
+
+ /* call host driver api */
+ if (USB_HostSend(printerInstance->hostHandle, printerInstance->outPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("fail to USB_HostSend\r\n");
+#endif
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+static usb_status_t USB_HostPrinterControl(usb_host_printer_instance_t *printerInstance,
+ uint8_t requestType,
+ uint8_t request,
+ uint16_t wvalue,
+ uint16_t windex,
+ uint16_t wlength,
+ uint8_t *data,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_transfer_t *transfer;
+
+ if (printerInstance == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (USB_HostMallocTransfer(printerInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ /* save the application callback function */
+ printerInstance->controlCallbackFn = callbackFn;
+ printerInstance->controlCallbackParam = callbackParam;
+ /* initialize transfer */
+ transfer->transferBuffer = data;
+ transfer->transferLength = wlength;
+ transfer->callbackFn = USB_HostPrinterControlPipeCallback;
+ transfer->callbackParam = printerInstance;
+ transfer->setupPacket.bmRequestType = requestType;
+ transfer->setupPacket.bRequest = request;
+ transfer->setupPacket.wValue = wvalue;
+ transfer->setupPacket.wIndex = windex;
+ transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength);
+
+ /* call host driver api */
+ if (USB_HostSendSetup(printerInstance->hostHandle, printerInstance->controlPipe, transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("fail for USB_HostSendSetup\r\n");
+#endif
+ USB_HostFreeTransfer(printerInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ printerInstance->controlTransfer = transfer;
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostPrinterGetDeviceId(usb_host_class_handle classHandle,
+ uint8_t interfaceIndex,
+ uint8_t alternateSetting,
+ uint8_t *buffer,
+ uint32_t length,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+ uint32_t infoValue;
+
+ USB_HostHelperGetPeripheralInformation(printerInstance->deviceHandle, kUSB_HostGetDeviceConfigIndex, &infoValue);
+
+ return USB_HostPrinterControl(
+ printerInstance, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_PRINTER_GET_DEVICE_ID, (uint16_t)infoValue,
+ (uint16_t)((uint16_t)((uint16_t)interfaceIndex << 8U) | alternateSetting), length, buffer, callbackFn,
+ callbackParam);
+}
+
+usb_status_t USB_HostPrinterGetPortStatus(usb_host_class_handle classHandle,
+ uint8_t *portStatus,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+
+ return USB_HostPrinterControl(
+ printerInstance, USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_PRINTER_GET_PORT_STATUS, 0,
+ (uint16_t)(((usb_host_interface_t *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber), 1,
+ portStatus, callbackFn, callbackParam);
+}
+
+usb_status_t USB_HostPrinterSoftReset(usb_host_class_handle classHandle,
+ transfer_callback_t callbackFn,
+ void *callbackParam)
+{
+ usb_host_printer_instance_t *printerInstance = (usb_host_printer_instance_t *)classHandle;
+
+ return USB_HostPrinterControl(
+ printerInstance, USB_REQUEST_TYPE_TYPE_CLASS | USB_REQUEST_TYPE_RECIPIENT_INTERFACE,
+ USB_HOST_PRINTER_SOFT_RESET, 0,
+ (uint16_t)(((usb_host_interface_t *)printerInstance->interfaceHandle)->interfaceDesc->bInterfaceNumber), 0,
+ NULL, callbackFn, callbackParam);
+}
+
+#endif /* USB_HOST_CONFIG_PRINTER */
diff --git a/usb_1.1.0/host/class/usb_host_printer.h b/usb_1.1.0/host/class/usb_host_printer.h
new file mode 100644
index 0000000..371ea80
--- /dev/null
+++ b/usb_1.1.0/host/class/usb_host_printer.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 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.
+ */
+
+#ifndef __USB_HOST_PRINTER_H__
+#define __USB_HOST_PRINTER_H__
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*!
+ * @addtogroup usb_host_printer_drv
+ * @{
+ */
+
+/*! @brief Printer class code */
+#define USB_HOST_PRINTER_CLASS_CODE (7U)
+/*! @brief Printer sub-class code */
+#define USB_HOST_PRINTER_SUBCLASS_CODE (1U)
+/*! @brief Printer class protocol code (Unidirectional interface) */
+#define USB_HOST_PRINTER_PROTOCOL_UNIDIRECTION (1U)
+/*! @brief Printer class protocol code (Bi-directional interface) */
+#define USB_HOST_PRINTER_PROTOCOL_BIDIRECTION (2U)
+/*! @brief Printer class protocol code (IEEEĀ® 1284.4 compatible bi-directional interface) */
+#define USB_HOST_PRINTER_PROTOCOL_IEEE1284 (3U)
+
+/*! @brief Printer class-specific request (GET_DEVICE_ID) */
+#define USB_HOST_PRINTER_GET_DEVICE_ID (0)
+/*! @brief Printer class-specific request (GET_PORT_STATUS) */
+#define USB_HOST_PRINTER_GET_PORT_STATUS (1)
+/*! @brief Printer class-specific request (SOFT_RESET) */
+#define USB_HOST_PRINTER_SOFT_RESET (2)
+
+/*! @brief Paper empty bit mask for GET_PORT_STATUS */
+#define USB_HOST_PRINTER_PORT_STATUS_PAPER_EMPTRY_MASK (0x20U)
+/*! @brief Select bit mask for GET_PORT_STATUS */
+#define USB_HOST_PRINTER_PORT_STATUS_SELECT_MASK (0x10U)
+/*! @brief Error bit mask for GET_PORT_STATUS */
+#define USB_HOST_PRINTER_PORT_STATUS_NOT_ERROR_MASK (0x08U)
+
+/*! @brief Printer instance structure and printer usb_host_class_handle pointer to this structure */
+typedef struct _usb_host_printer_instance
+{
+ usb_host_handle hostHandle; /*!< This instance's related host handle*/
+ usb_device_handle deviceHandle; /*!< This instance's related device handle*/
+ usb_host_interface_handle interfaceHandle; /*!< This instance's related interface handle*/
+ usb_host_pipe_handle controlPipe; /*!< This instance's related device control pipe*/
+ usb_host_pipe_handle inPipe; /*!< Printer bulk in pipe*/
+ usb_host_pipe_handle outPipe; /*!< Printer bulk out pipe*/
+ transfer_callback_t inCallbackFn; /*!< Printer bulk in transfer callback function pointer*/
+ void *inCallbackParam; /*!< Printer bulk in transfer callback parameter*/
+ transfer_callback_t outCallbackFn; /*!< Printer bulk out transfer callback function pointer*/
+ void *outCallbackParam; /*!< Printer bulk out transfer callback parameter*/
+ transfer_callback_t controlCallbackFn; /*!< Printer control transfer callback function pointer*/
+ void *controlCallbackParam; /*!< Printer control transfer callback parameter*/
+ usb_host_transfer_t *controlTransfer; /*!< Ongoing control transfer*/
+#if ((defined USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL) && USB_HOST_CONFIG_CLASS_AUTO_CLEAR_STALL)
+ uint8_t *stallDataBuffer;
+ uint32_t stallDataLength;
+#endif
+
+ uint16_t inPacketSize; /*!< Printer bulk in maximum packet size*/
+ uint16_t outPacketSize; /*!< Printer bulk out maximum packet size*/
+} usb_host_printer_instance_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host printer class APIs
+ * @{
+ */
+
+/*!
+ * @brief Initializes the printer instance.
+ *
+ * This function allocate the resource for the printer instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[out] classHandle Return class handle.
+ *
+ * @retval kStatus_USB_Success The device is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocate memory fail.
+ */
+extern usb_status_t USB_HostPrinterInit(usb_device_handle deviceHandle, usb_host_class_handle *classHandle);
+
+/*!
+ * @brief Sets the interface.
+ *
+ * This function binds the interface with the printer instance.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceHandle The interface handle.
+ * @param[in] alternateSetting The alternate setting value.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSendSetup.
+ * @retval kStatus_USB_Busy Callback return status, there is no idle pipe.
+ * @retval kStatus_USB_TransferStall Callback return status, the transfer is stalled by the device.
+ * @retval kStatus_USB_Error Callback return status, open pipe fail. See the USB_HostOpenPipe.
+ */
+extern usb_status_t USB_HostPrinterSetInterface(usb_host_class_handle classHandle,
+ usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief De-initializes the the printer instance.
+ *
+ * This function frees the resources for the printer instance.
+ *
+ * @param[in] deviceHandle The device handle.
+ * @param[in] classHandle The class handle.
+ *
+ * @retval kStatus_USB_Success The device is de-initialized successfully.
+ */
+extern usb_status_t USB_HostPrinterDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle);
+
+/*!
+ * @brief Gets the pipe maximum packet size.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] pipeType Its value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
+ * USB_ENDPOINT_INTERRUPT.
+ * See the usb_spec.h
+ * @param[in] direction Pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval Maximum Packet size.
+ */
+extern uint16_t USB_HostPrinterGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction);
+
+/*!
+ * @brief Receives data.
+ *
+ * This function implements the printer receiving data.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[out] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostRecv.
+ */
+extern usb_status_t USB_HostPrinterRecv(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Sends data.
+ *
+ * This function implements the printer sending data.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] buffer The buffer pointer.
+ * @param[in] bufferLength The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] 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. See the USB_HostSend.
+ */
+extern usb_status_t USB_HostPrinterSend(usb_host_class_handle classHandle,
+ uint8_t *buffer,
+ uint32_t bufferLength,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Gets the pipe maximum packet size.
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] pipeType Its value is USB_ENDPOINT_CONTROL, USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK or
+ * USB_ENDPOINT_INTERRUPT. See the usb_spec.h
+ * @param[in] direction Pipe direction.
+ *
+ * @retval 0 The classHandle is NULL.
+ * @retval Maximum Packet size.
+ */
+extern uint16_t USB_HostPrinterGetPacketsize(usb_host_class_handle classHandle, uint8_t pipeType, uint8_t direction);
+
+/*!
+ * @brief Printer get device ID.
+ *
+ * This function implements the printer class-specific request (GET_DEVICE_ID).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] interfaceIndex Interface index.
+ * @param[in] alternateSetting Get the alternateSetting's device ID.
+ * @param[out] buffer The buffer pointer.
+ * @param[in] length The buffer length.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostPrinterGetDeviceId(usb_host_class_handle classHandle,
+ uint8_t interfaceIndex,
+ uint8_t alternateSetting,
+ uint8_t *buffer,
+ uint32_t length,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Printer get port status.
+ *
+ * This function implements the printer class-specific request (GET_PORT_STATUS).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] portStatus Port status buffer.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostPrinterGetPortStatus(usb_host_class_handle classHandle,
+ uint8_t *portStatus,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+
+/*!
+ * @brief Printer soft reset.
+ *
+ * This function implements the printer class-specific request (SOFT_RESET).
+ *
+ * @param[in] classHandle The class handle.
+ * @param[in] portStatus Port status buffer.
+ * @param[in] callbackFn This callback is called after this function completes.
+ * @param[in] callbackParam The first parameter in the callback function.
+ *
+ * @retval kStatus_USB_Success Request successful.
+ * @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. See the USB_HostSendSetup.
+ */
+extern usb_status_t USB_HostPrinterSoftReset(usb_host_class_handle classHandle,
+ transfer_callback_t callbackFn,
+ void *callbackParam);
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* __USB_HOST_PRINTER_H__ */