summaryrefslogtreecommitdiff
path: root/usb_1.1.0/host
diff options
context:
space:
mode:
Diffstat (limited to 'usb_1.1.0/host')
-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
-rw-r--r--usb_1.1.0/host/usb_host.h569
-rw-r--r--usb_1.1.0/host/usb_host_devices.c1345
-rw-r--r--usb_1.1.0/host/usb_host_devices.h178
-rw-r--r--usb_1.1.0/host/usb_host_framework.c377
-rw-r--r--usb_1.1.0/host/usb_host_framework.h107
-rw-r--r--usb_1.1.0/host/usb_host_hci.c754
-rw-r--r--usb_1.1.0/host/usb_host_hci.h118
-rw-r--r--usb_1.1.0/host/usb_host_khci.c1886
-rw-r--r--usb_1.1.0/host/usb_host_khci.h328
26 files changed, 17583 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__ */
diff --git a/usb_1.1.0/host/usb_host.h b/usb_1.1.0/host/usb_host.h
new file mode 100644
index 0000000..6237b21
--- /dev/null
+++ b/usb_1.1.0/host/usb_host.h
@@ -0,0 +1,569 @@
+/*
+ * 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_H_
+#define _USB_HOST_H_
+
+#include "usb.h"
+#include "usb_misc.h"
+#include "usb_spec.h"
+#include "usb_host_framework.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+struct _usb_host_transfer; /* for cross reference */
+
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+
+/*! @brief USB host class handle type define */
+typedef void *usb_host_class_handle;
+
+/*! @brief USB host controller handle type define */
+typedef void *usb_host_controller_handle;
+
+/*! @brief USB host configuration handle type define */
+typedef void *usb_host_configuration_handle;
+
+/*! @brief USB host interface handle type define */
+typedef void *usb_host_interface_handle;
+
+/*! @brief USB host pipe handle type define */
+typedef void *usb_host_pipe_handle;
+
+/*! @brief Event codes for device attach/detach */
+typedef enum _usb_host_event
+{
+ kUSB_HostEventAttach = 1U, /*!< Device is attached */
+ kUSB_HostEventDetach, /*!< Device is detached */
+ kUSB_HostEventEnumerationDone, /*!< Device's enumeration is done and the device is supported */
+ kUSB_HostEventNotSupported /*!< Device's enumeration is done and the device is not supported */
+} usb_host_event_t;
+
+/*! @brief USB host device information code */
+typedef enum _usb_host_dev_info
+{
+ kUSB_HostGetDeviceAddress = 1U, /*!< Device's address */
+ kUSB_HostGetDeviceHubNumber, /*!< Device's first hub address */
+ kUSB_HostGetDevicePortNumber, /*!< Device's first hub port number */
+ kUSB_HostGetDeviceSpeed, /*!< Device's speed */
+ kUSB_HostGetDeviceHSHubNumber, /*!< Device's first high-speed hub address */
+ kUSB_HostGetDeviceHSHubPort, /*!< Device's first high-speed hub number */
+ kUSB_HostGetDeviceLevel, /*!< Device's hub level */
+ kUSB_HostGetHostHandle, /*!< Device's host handle */
+ kUSB_HostGetDeviceControlPipe, /*!< Device's control pipe handle */
+ kUSB_HostGetDevicePID, /*!< Device's PID */
+ kUSB_HostGetDeviceVID, /*!< Device's VID */
+ kUSB_HostGetHubThinkTime, /*!< Device's hub total think time */
+ kUSB_HostGetDeviceConfigIndex, /*!< Device's running zero-based config index */
+} usb_host_dev_info_t;
+
+/*!
+ * @brief Host callback function typedef.
+ *
+ * This callback function is used to notify application device attach/detach event.
+ * This callback pointer is passed when initializing the host.
+ *
+ * @param deviceHandle The device handle, which indicates the attached device.
+ * @param configurationHandle The configuration handle contains the attached device's configuration information.
+ * @param event_code The callback event code; See the enumeration host_event_t.
+ *
+ * @return A USB error code or kStatus_USB_Success.
+ * @retval kStatus_USB_Success Application handles the attached device successfully.
+ * @retval kStatus_USB_NotSupported Application don't support the attached device.
+ * @retval kStatus_USB_Error Application handles the attached device falsely.
+ */
+typedef usb_status_t (*host_callback_t)(usb_device_handle deviceHandle,
+ usb_host_configuration_handle configurationHandle,
+ uint32_t eventCode);
+
+/*!
+ * @brief Transfer callback function typedef.
+ *
+ * This callback function is used to notify the upper layer the result of the transfer.
+ * This callback pointer is passed when calling the send/receive APIs.
+ *
+ * @param param The parameter pointer, which is passed when calling the send/receive APIs.
+ * @param data The data buffer pointer.
+ * @param data_len The result data length.
+ * @param status A USB error code or kStatus_USB_Success.
+ */
+typedef void (*transfer_callback_t)(void *param, uint8_t *data, uint32_t dataLen, usb_status_t status);
+
+/*!
+ * @brief Host stack inner transfer callback function typedef.
+ *
+ * This callback function is used to notify the upper layer the result of a transfer.
+ * This callback pointer is passed when initializing the structure usb_host_transfer_t.
+ *
+ * @param param The parameter pointer, which is passed when calling the send/receive APIs.
+ * @param transfer The transfer information; See the structure usb_host_transfer_t.
+ * @param status A USB error code or kStatus_USB_Success.
+ */
+typedef void (*host_inner_transfer_callback_t)(void *param, struct _usb_host_transfer *transfer, usb_status_t status);
+
+/*! @brief USB host endpoint information structure */
+typedef struct _usb_host_ep
+{
+ usb_descriptor_endpoint_t *epDesc; /*!< Endpoint descriptor pointer*/
+ uint8_t *epExtension; /*!< Endpoint extended descriptor pointer*/
+ uint16_t epExtensionLength; /*!< Extended descriptor length*/
+} usb_host_ep_t;
+
+/*! @brief USB host interface information structure */
+typedef struct _usb_host_interface
+{
+ usb_host_ep_t epList[USB_HOST_CONFIG_INTERFACE_MAX_EP]; /*!< Endpoint array*/
+ usb_descriptor_interface_t *interfaceDesc; /*!< Interface descriptor pointer*/
+ uint8_t *interfaceExtension; /*!< Interface extended descriptor pointer*/
+ uint16_t interfaceExtensionLength; /*!< Extended descriptor length*/
+ uint8_t interfaceIndex; /*!< The interface index*/
+ uint8_t alternateSettingNumber; /*!< The interface alternate setting value*/
+ uint8_t epCount; /*!< Interface's endpoint number*/
+} usb_host_interface_t;
+
+/*! @brief USB host configuration information structure */
+typedef struct _usb_host_configuration
+{
+ usb_host_interface_t interfaceList[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interface array*/
+ usb_descriptor_configuration_t *configurationDesc; /*!< Configuration descriptor pointer*/
+ uint8_t *configurationExtension; /*!< Configuration extended descriptor pointer*/
+ uint16_t configurationExtensionLength; /*!< Extended descriptor length*/
+ uint8_t interfaceCount; /*!< The configuration's interface number*/
+} usb_host_configuration_t;
+
+/*! @brief USB host pipe common structure */
+typedef struct _usb_host_pipe
+{
+ struct _usb_host_pipe *next; /*!< Link the idle pipes*/
+ usb_device_handle deviceHandle; /*!< This pipe's device's handle*/
+ uint16_t currentCount; /*!< For KHCI transfer*/
+ uint16_t nakCount; /*!< Maximum NAK count*/
+ uint16_t maxPacketSize; /*!< Maximum packet size*/
+ uint16_t interval; /*!< FS/LS: frame unit; HS: micro-frame unit*/
+ uint8_t open; /*!< 0 - closed, 1 - open*/
+ uint8_t nextdata01; /*!< Data toggle*/
+ uint8_t endpointAddress; /*!< Endpoint address*/
+ uint8_t direction; /*!< Pipe direction*/
+ uint8_t pipeType; /*!< Pipe type, for example USB_ENDPOINT_BULK*/
+ uint8_t numberPerUframe; /*!< Transaction number per micro-frame*/
+} usb_host_pipe_t;
+
+/*! @brief USB host transfer structure */
+typedef struct _usb_host_transfer
+{
+ struct _usb_host_transfer *next; /*!< The next transfer structure*/
+#if USB_HOST_CONFIG_EHCI
+ uint32_t ehciUnitHead; /*!< QTD/ITD/SITD head for this transfer*/
+ uint32_t ehciUnitTail; /*!< QTD/ITD/SITD tail for this transfer*/
+#endif
+ uint8_t *transferBuffer; /*!< Transfer data buffer*/
+ uint32_t transferLength; /*!< Transfer data length*/
+ uint32_t transferSofar; /*!< Have transferred length*/
+ host_inner_transfer_callback_t callbackFn; /*!< Transfer callback function*/
+ void *callbackParam; /*!< Transfer callback parameter*/
+ usb_host_pipe_t *transferPipe; /*!< Transfer pipe pointer*/
+ usb_setup_struct_t setupPacket; /*!< Set up packet buffer*/
+ uint8_t direction; /*!< Transfer direction; its values are USB_OUT or USB_IN*/
+ uint8_t setupStatus; /*!< Set up the transfer status*/
+#if USB_HOST_CONFIG_KHCI
+ int32_t transferResult; /*!< KHCI transfer result */
+ uint32_t frame; /*!< KHCI transfer frame number */
+ uint16_t nakTimeout; /*!< KHCI transfer NAK timeout */
+ uint16_t retry; /*!< KHCI transfer retry */
+#endif
+} usb_host_transfer_t;
+
+/*! @brief USB host pipe information structure for opening pipe */
+typedef struct _usb_host_pipe_init
+{
+ void *devInstance; /*!< Device instance handle*/
+ uint16_t nakCount; /*!< Maximum NAK retry count. MUST be zero for interrupt*/
+ uint16_t maxPacketSize; /*!< Pipe's maximum packet size*/
+ uint8_t interval; /*!< Pipe's interval*/
+ uint8_t endpointAddress; /*!< Endpoint address*/
+ uint8_t direction; /*!< Endpoint direction*/
+ uint8_t pipeType; /*!< Endpoint type, the value is USB_ENDPOINT_INTERRUPT, USB_ENDPOINT_CONTROL,
+ USB_ENDPOINT_ISOCHRONOUS, USB_ENDPOINT_BULK*/
+ uint8_t numberPerUframe; /*!< Transaction number for each micro-frame*/
+} usb_host_pipe_init_t;
+
+/*! @brief Cancel transfer parameter structure */
+typedef struct _usb_host_cancel_param
+{
+ usb_host_pipe_handle pipeHandle; /*!< Cancelling pipe handle*/
+ usb_host_transfer_t *transfer; /*!< Cancelling transfer*/
+} usb_host_cancel_param_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*!
+ * @name USB host APIs Part 1
+ * The following APIs are recommended for application use.
+ * @{
+ */
+
+/*!
+ * @brief Initializes the USB host stack.
+ *
+ * This function initializes the USB host module specified by the controllerId.
+ *
+ * @param[in] controllerId The controller ID of the USB IP. See the enumeration usb_controller_index_t.
+ * @param[out] hostHandle Returns the host handle.
+ * @param[in] callbackFn Host callback function notifies device attach/detach.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle The host_handle_ptr is a NULL pointer.
+ * @retval kStatus_USB_ControllerNotFound Cannot find the controller according to the controller ID.
+ * @retval kStatus_USB_AllocFail Allocation memory fail.
+ * @retval kStatus_USB_Error Host mutex create fail; KHCI/EHCI mutex or KHCI/EHCI event create fail,
+ * or, KHCI/EHCI IP initialize fail.
+ */
+extern usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn);
+
+/*!
+ * @brief Deinitializes the USB host stack.
+ *
+ * This function deinitializes the USB host module specified by the hostHandle.
+ *
+ * @param[in] hostHandle The host handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer.
+ * @retval kStatus_USB_Error Controller deinitialization fail.
+ */
+extern usb_status_t USB_HostDeinit(usb_host_handle hostHandle);
+
+/*!
+ * @brief Gets the device information.
+ *
+ * This function gets the device information.
+ *
+ * @param[in] deviceHandle Removing device handle.
+ * @param[in] infoCode See the enumeration host_dev_info_t.
+ * @param[out] infoValue Return the information value.
+ *
+ * @retval kStatus_USB_Success Close successfully.
+ * @retval kStatus_USB_InvalidParameter The deviceHandle or info_value is a NULL pointer.
+ * @retval kStatus_USB_Error The info_code is not the host_dev_info_t value.
+ */
+extern usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
+ uint32_t infoCode,
+ uint32_t *infoValue);
+
+/*!
+ * @brief Parses the alternate interface descriptor.
+ *
+ * This function parses the alternate interface descriptor and returns an interface information through the structure
+ * usb_host_interface_t.
+ *
+ * @param[in] interfaceHandle The whole interface handle.
+ * @param[in] alternateSetting Alternate setting value.
+ * @param[out] interface Return interface information.
+ *
+ * @retval kStatus_USB_Success Close successfully.
+ * @retval kStatus_USB_InvalidHandle The interfaceHandle is a NULL pointer.
+ * @retval kStatus_USB_InvalidParameter The alternateSetting is 0.
+ * @retval kStatus_USB_Error The interface descriptor is wrong.
+ */
+extern usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ usb_host_interface_t *interface);
+
+/*!
+ * @brief Removes the attached device.
+ *
+ * This function removes the attached device.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] deviceHandle Removing device handle.
+ *
+ * @retval kStatus_USB_Success Remove successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or deviceHandle is a NULL pointer.
+ * @retval kStatus_USB_InvalidParameter The deviceHandle instance don't belong to hostHandle instance.
+ */
+extern usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief KHCI task function.
+ *
+ * The function is used to handle the KHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostKhciTaskFunction(void *hostHandle);
+
+/*!
+ * @brief EHCI task function.
+ *
+ * The function is used to handle the EHCI controller message.
+ * In the bare metal environment, this function should be called periodically in the main function.
+ * In the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostEhciTaskFunction(void *hostHandle);
+
+/*!
+ * @brief Device KHCI ISR function.
+ *
+ * The function is the KHCI interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostKhciIsrFunction(void *hostHandle);
+
+/*!
+ * @brief Device EHCI ISR function.
+ *
+ * The function is the EHCI interrupt service routine.
+ *
+ * @param[in] hostHandle The host handle.
+ */
+extern void USB_HostEhciIsrFunction(void *hostHandle);
+/*! @}*/
+
+/*!
+ * @name USB host APIs Part 2.
+ * The following APIs are not recommended for application use. They are mainly used in the class driver.
+ * @{
+ */
+
+/*!
+ * @brief Opens the USB host pipe.
+ *
+ * This function opens a pipe according to the pipe_init_ptr parameter.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[out] pipeHandle The pipe handle pointer used to return the pipe handle.
+ * @param[in] pipeInit Used to initialize the pipe.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or pipe_handle_ptr is a NULL pointer.
+ * @retval kStatus_USB_Error There is no idle pipe.
+ * Or, there is no idle QH for EHCI.
+ * Or, bandwidth allocate fail for EHCI.
+ */
+extern usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle,
+ usb_host_pipe_handle *pipeHandle,
+ usb_host_pipe_init_t *pipeInit);
+
+/*!
+ * @brief Closes the USB host pipe.
+ *
+ * This function closes a pipe and frees the related resources.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] pipeHandle The closing pipe handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or pipeHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle);
+
+/*!
+ * @brief Sends data to a pipe.
+ *
+ * This function requests to send the transfer to the specified pipe.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] pipeHandle The sending pipe handle.
+ * @param[in] transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Send successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostSend(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Sends a setup transfer to the pipe.
+ *
+ * This function request to send the setup transfer to the specified pipe.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] pipeHandle The sending pipe handle.
+ * @param[in] transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Send successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostSendSetup(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Receives the data from the pipe.
+ *
+ * This function requests to receive the transfer from the specified pipe.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] pipeHandle The receiving pipe handle.
+ * @param[in] transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Receive successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle, pipeHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI.
+ */
+extern usb_status_t USB_HostRecv(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Cancel the pipe's transfers.
+ *
+ * This function cancels all pipe's transfers when the parameter transfer is NULL or cancels the transfers altogether.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] pipeHandle The receiving pipe handle.
+ * @param[in] transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Cancel successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or pipeHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Allocates a transfer resource.
+ *
+ * This function allocates a transfer. This transfer is used to pass data information to a low level stack.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[out] transfer Return the transfer.
+ *
+ * @retval kStatus_USB_Success Allocate successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or transfer is a NULL pointer.
+ * @retval kStatus_USB_Error There is no idle transfer.
+ */
+extern usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfer_t **transfer);
+
+/*!
+ * @brief Frees a transfer resource.
+ *
+ * This function frees a transfer. This transfer is used to pass data information to a low level stack.
+ *
+ * @param[in] hostHandle The host handle.
+ * @param[in] transfer Release the transfer.
+ *
+ * @retval kStatus_USB_Success Free successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle or transfer is a NULL pointer.
+ */
+extern usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Requests the USB standard request.
+ *
+ * This function sends the USB standard request packet.
+ *
+ * @param[in] deviceHandle The device handle for control transfer.
+ * @param[in] usbRequest A USB standard request code. Se the usb_spec.h.
+ * @param[in] transfer The used transfer.
+ * @param[in] param The parameter structure is different for different request, see
+ * usb_host_framework.h.
+ *
+ * @retval kStatus_USB_Success Send successfully.
+ * @retval kStatus_USB_InvalidHandle The deviceHandle is a NULL pointer.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ * @retval kStatus_USB_Error There is no idle QTD/ITD/SITD for EHCI,
+ * Or, the request is not standard request.
+ */
+extern usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle,
+ uint8_t usbRequest,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief Opens the interface.
+ *
+ * This function opens the interface. It is used to notify the host driver the interface is used by APP or class driver.
+ *
+ * @param[in] deviceHandle Removing device handle.
+ * @param[in] interfaceHandle Opening interface handle.
+ *
+ * @retval kStatus_USB_Success Open successfully.
+ * @retval kStatus_USB_InvalidHandle The deviceHandle or interfaceHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle,
+ usb_host_interface_handle interfaceHandle);
+
+/*!
+ * @brief Closes an interface.
+ *
+ * This function opens an interface. It is used to notify the host driver the interface is not used by APP or class
+ * driver.
+ *
+ * @param[in] deviceHandle Removing device handle.
+ * @param[in] interfaceHandle Opening interface handle.
+ *
+ * @retval kStatus_USB_Success Close successfully.
+ * @retval kStatus_USB_InvalidHandle The deviceHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle,
+ usb_host_interface_handle interfaceHandle);
+
+/*!
+ * @brief Gets a host stack version function.
+ *
+ * The function is used to get the host stack version.
+ *
+ * @param[out] version The version structure pointer to keep the host stack version.
+ *
+ */
+extern void USB_HostGetVersion(uint32_t *version);
+
+/*! @}*/
+
+#ifdef __cplusplus
+}
+#endif
+
+/*! @}*/
+
+#endif /* _USB_HOST_H_ */
diff --git a/usb_1.1.0/host/usb_host_devices.c b/usb_1.1.0/host/usb_host_devices.c
new file mode 100644
index 0000000..f4ec31b
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_devices.c
@@ -0,0 +1,1345 @@
+/*
+ * 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"
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+#include "usb_host_hub.h"
+#endif /* USB_HOST_CONFIG_HUB */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*!
+ * @brief enumeration transfer callback function.
+ *
+ * @param param callback parameter.
+ * @param transfer the transfer.
+ * @param status transfer result status.
+ */
+static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status);
+
+/*!
+ * @brief process the new step state.
+ *
+ * @param deviceInstance device instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief process the previous step transfer result.
+ *
+ * @param deviceInstance device instance pointer.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief notify the application event, the callback is registered when initializing host.
+ *
+ * @param deviceInstance device instance pointer.
+ * @param eventCode event code.
+ *
+ * @return kStatus_USB_Success or error codes
+ */
+static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode);
+
+/*!
+ * @brief allocate one address.
+ *
+ * @param hostInstance host instance pointer.
+ *
+ * @return address, 0 is invalid.
+ */
+static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance);
+
+/*!
+ * @brief release one address.
+ *
+ * @param hostInstance host instance pointer.
+ * @param address releasing address.
+ */
+static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address);
+
+/*!
+ * @brief release device resource.
+ *
+ * @param hostInstance host instance pointer.
+ * @param deviceInstance device instance pointer.
+ */
+static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance,
+ usb_host_device_instance_t *deviceInstance);
+
+/*!
+ * @brief parse device configuration descriptor.
+ *
+ * @param deviceHandle device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle deviceHandle);
+
+/*!
+ * @brief remove device instance from host device list.
+ *
+ * @param hostHandle host instance handle.
+ * @param deviceHandle device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief control the bus.
+ *
+ * This function control the host bus.
+ *
+ * @param[in] hostHandle the host handle.
+ * @param[in] controlType the control code, please reference to bus_event_t.
+ *
+ * @retval kStatus_USB_Success control successfully.
+ * @retval kStatus_USB_InvalidHandle The hostHandle is a NULL pointer.
+ */
+static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType);
+
+extern usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+extern usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+extern usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ uint8_t *buffer,
+ uint32_t bufferLen);
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+
+extern usb_status_t USB_HostHubDeviceEvent(usb_device_handle deviceHandle,
+ usb_host_configuration_handle configurationHandle,
+ uint32_t eventCode);
+
+extern uint32_t USB_HostHubGetHsHubNumber(uint8_t parentHubNo);
+
+extern uint32_t USB_HostHubGetHsHubPort(uint8_t parentHubNo, uint8_t parentPortNo);
+
+extern usb_status_t USB_HostHubRemovePort(uint8_t hubNumber, uint8_t portNumber);
+
+#endif
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+extern usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST];
+
+/*! @brief enumeration step process array */
+static const usb_host_enum_process_entry_t s_EnumEntries[] = \
+{
+ /* kStatus_dev_initial */
+ {
+ 0, 0, NULL,
+ },
+ /* kStatus_DEV_GetDes8 */
+ {
+ kStatus_DEV_SetAddress, kStatus_DEV_GetDes8, USB_HostProcessCallback,
+ },
+ /* kStatus_DEV_SetAddress */
+ {
+ kStatus_DEV_GetDes, kStatus_DEV_SetAddress, USB_HostProcessCallback,
+ },
+ /* kStatus_DEV_GetDes */
+ {
+ kStatus_DEV_GetCfg9, kStatus_DEV_GetDes, NULL,
+ },
+ /* kStatus_DEV_GetCfg9 */
+ {
+ kStatus_DEV_GetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback,
+ },
+ /* kStatus_DEV_GetCfg */
+ {
+ kStatus_DEV_SetCfg, kStatus_DEV_GetCfg9, USB_HostProcessCallback,
+ },
+ /* kStatus_DEV_SetCfg */
+ {
+ kStatus_DEV_EnumDone, kStatus_DEV_SetCfg, NULL,
+ },
+};
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+static void USB_HostEnumerationTransferCallback(void *param, usb_host_transfer_t *transfer, usb_status_t status)
+{
+ uint8_t nextStep = 0;
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)param;
+
+ USB_HostFreeTransfer(deviceInstance->hostHandle, transfer); /* free transfer */
+
+ if (status == kStatus_USB_Success)
+ {
+ nextStep = 1;
+ }
+ else if (status == kStatus_USB_TransferStall)
+ {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ usb_echo("no response from device\r\n");
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+ if (deviceInstance->stallRetries > 0) /* retry same transfer when stall */
+ {
+ deviceInstance->stallRetries--;
+ }
+ else /* process next state when all retries stall */
+ {
+ nextStep = 1;
+ }
+ }
+ else if (status == kStatus_USB_TransferCancel)
+ {
+ return;
+ }
+ else
+ {
+ if (deviceInstance->enumRetries > 0) /* next whole retry */
+ {
+ deviceInstance->enumRetries--;
+ deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ deviceInstance->configurationValue = 0;
+ deviceInstance->state = kStatus_DEV_GetDes8;
+ }
+ else
+ {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ usb_echo("Device No Response\r\n");
+#endif
+ return;
+ }
+ }
+
+ if (nextStep == 1)
+ {
+ deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ if (s_EnumEntries[deviceInstance->state - 1].process == NULL)
+ {
+ deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState; /* next state */
+ }
+ else
+ {
+ status = s_EnumEntries[deviceInstance->state - 1].process(
+ deviceInstance); /* process the previous state result */
+ if (status == kStatus_USB_Success) /* process success */
+ {
+ deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].successState;
+ }
+ else if (status == kStatus_USB_Retry) /* need retry */
+ {
+ deviceInstance->state = s_EnumEntries[deviceInstance->state - 1].retryState;
+ }
+ else if (status == kStatus_USB_NotSupported) /* device don't suport by the application */
+ {
+ return; /* unrecoverable fail */
+ }
+ else /* process error, next retry */
+ {
+ if (deviceInstance->enumRetries > 0) /* next whole retry */
+ {
+ deviceInstance->enumRetries--;
+ deviceInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ deviceInstance->configurationValue = 0;
+ deviceInstance->state = kStatus_DEV_GetDes8;
+ }
+ else
+ {
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+ usb_echo("Device No Response\r\n");
+#endif
+ return; /* unrecoverable fail */
+ }
+ }
+ }
+ }
+
+ if (USB_HostProcessState(deviceInstance) != kStatus_USB_Success) /* process the new state */
+ {
+#ifdef HOST_ECHO
+ usb_echo("enumation setup error\r\n");
+#endif
+ return;
+ }
+}
+
+static usb_status_t USB_HostProcessState(usb_host_device_instance_t *deviceInstance)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_process_descriptor_param_t getDescriptorParam;
+ usb_host_transfer_t *transfer;
+
+ /* malloc transfer */
+ if (deviceInstance->state != kStatus_DEV_EnumDone)
+ {
+ if (USB_HostMallocTransfer(deviceInstance->hostHandle, &transfer) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error to get transfer\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ transfer->callbackFn = USB_HostEnumerationTransferCallback;
+ transfer->callbackParam = deviceInstance;
+
+ /* reset transfer fields */
+ transfer->setupPacket.bmRequestType = 0x00;
+ transfer->setupPacket.wIndex = 0;
+ transfer->setupPacket.wLength = 0;
+ transfer->setupPacket.wValue = 0;
+ }
+
+ switch (deviceInstance->state)
+ {
+ case kStatus_DEV_GetDes8:
+ case kStatus_DEV_GetDes: /* get descriptor state */
+ getDescriptorParam.descriptorLength = sizeof(usb_descriptor_device_t);
+ if (deviceInstance->state == kStatus_DEV_GetDes8)
+ {
+ getDescriptorParam.descriptorLength = 8;
+ }
+ getDescriptorParam.descriptorBuffer = (uint8_t *)&deviceInstance->deviceDescriptor;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_DEVICE;
+ getDescriptorParam.descriptorIndex = 0;
+ getDescriptorParam.languageId = 0;
+
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+ case kStatus_DEV_SetAddress: /* set address state */
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_ADDRESS;
+ status = USB_HostStandardSetAddress(deviceInstance, transfer, &deviceInstance->allocatedAddress);
+ break;
+
+ case kStatus_DEV_GetCfg9: /* get 9 bytes configuration state */
+ getDescriptorParam.descriptorBuffer = deviceInstance->enumBuffer;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+ getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+ getDescriptorParam.descriptorLength = 9;
+ getDescriptorParam.languageId = 0;
+
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+
+ case kStatus_DEV_GetCfg: /* get configuration state */
+ getDescriptorParam.descriptorBuffer = deviceInstance->configurationDesc;
+ getDescriptorParam.descriptorType = USB_DESCRIPTOR_TYPE_CONFIGURE;
+ getDescriptorParam.descriptorIndex = deviceInstance->configurationValue;
+ getDescriptorParam.descriptorLength = deviceInstance->configurationLen;
+ getDescriptorParam.languageId = 0;
+
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_GET_DESCRIPTOR;
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, &getDescriptorParam);
+ break;
+
+ case kStatus_DEV_SetCfg: /* set configuration state */
+ transfer->setupPacket.wValue =
+ USB_SHORT_TO_LITTLE_ENDIAN(deviceInstance->configuration.configurationDesc->bConfigurationValue);
+ transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_CONFIGURATION;
+ status = USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+ break;
+
+ case kStatus_DEV_EnumDone: /* enumeration done state */
+ status = USB_HostNotifyDevice(deviceInstance,
+ kUSB_HostEventEnumerationDone); /* notify device enumeration done */
+ if (status == kStatus_USB_Success)
+ {
+ deviceInstance->state = kStatus_DEV_AppUsed;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+static usb_status_t USB_HostProcessCallback(usb_host_device_instance_t *deviceInstance)
+{
+ usb_host_pipe_t *pipe = (usb_host_pipe_t *)deviceInstance->controlPipe;
+ usb_status_t status = kStatus_USB_Success;
+ usb_descriptor_configuration_t *configureDesc;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+
+ switch (deviceInstance->state)
+ {
+ case kStatus_DEV_GetDes8: /* process get 8 bytes descriptor result */
+ pipe->maxPacketSize = deviceInstance->deviceDescriptor.bMaxPacketSize0;
+ hostInstance->controllerTable->controllerIoctl(
+ hostInstance->controllerHandle, kUSB_HostUpdateControlPacketSize, deviceInstance->controlPipe);
+ break;
+
+ case kStatus_DEV_SetAddress: /* process set address result */
+ deviceInstance->setAddress = deviceInstance->allocatedAddress;
+ hostInstance->controllerTable->controllerIoctl(
+ hostInstance->controllerHandle, kUSB_HostUpdateControlEndpointAddress, deviceInstance->controlPipe);
+ break;
+
+ case kStatus_DEV_GetDes: /* process set address result */
+ /* NULL */
+ break;
+
+ case kStatus_DEV_GetCfg9: /* process get 9 bytes configuration result */
+ configureDesc = (usb_descriptor_configuration_t *)&deviceInstance->enumBuffer[0];
+
+ deviceInstance->configurationLen = USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(configureDesc->wTotalLength);
+ if (deviceInstance->configurationDesc != NULL)
+ {
+ USB_OsaMemoryFree(deviceInstance->configurationDesc);
+ deviceInstance->configurationDesc = NULL;
+ }
+ /* for KHCI, the start address and the length should be 4 byte align */
+ if ((deviceInstance->configurationLen & 0x03) != 0)
+ {
+ deviceInstance->configurationDesc =
+ (uint8_t *)USB_OsaMemoryAllocate((deviceInstance->configurationLen & 0xFFFFFFFCu) + 4);
+ }
+ else
+ {
+ deviceInstance->configurationDesc = (uint8_t *)USB_OsaMemoryAllocate(deviceInstance->configurationLen);
+ }
+ if (deviceInstance->configurationDesc == NULL)
+ {
+ return kStatus_USB_Error;
+ }
+ break;
+
+ case kStatus_DEV_GetCfg: /* process get cofiguration result */
+ if (((usb_descriptor_configuration_t *)deviceInstance->configurationDesc)->bMaxPower >
+ USB_HOST_CONFIG_MAX_POWER)
+ {
+ return kStatus_USB_Error;
+ }
+ deviceInstance->configurationValue++;
+ if (USB_HostParseDeviceConfigurationDescriptor(deviceInstance) !=
+ kStatus_USB_Success) /* parse configuration descriptor */
+ {
+ return kStatus_USB_Error;
+ }
+
+ status = USB_HostNotifyDevice(deviceInstance, kUSB_HostEventAttach);
+
+ if (status != kStatus_USB_Success)
+ {
+ /* next configuration */
+ if (deviceInstance->configurationValue < deviceInstance->deviceDescriptor.bNumConfigurations)
+ {
+ return kStatus_USB_Retry;
+ }
+ else
+ {
+ USB_HostNotifyDevice(deviceInstance,
+ kUSB_HostEventNotSupported); /* notify application device is not supported */
+ return kStatus_USB_NotSupported;
+ }
+ }
+ break;
+
+ case kStatus_DEV_SetCfg:
+ /* NULL */
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
+
+static usb_status_t USB_HostNotifyDevice(usb_host_device_instance_t *deviceInstance, uint32_t eventCode)
+{
+ usb_host_instance_t *hostInstance;
+ usb_status_t status1 = kStatus_USB_Error;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ usb_status_t status2 = kStatus_USB_Error;
+ uint8_t haveHub;
+ uint8_t haveNoHub;
+ uint8_t interfaceIndex;
+#endif /* USB_HOST_CONFIG_HUB */
+
+ if (deviceInstance == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ haveHub = 0;
+ haveNoHub = 0;
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (((usb_descriptor_interface_t *)deviceInstance->configuration.interfaceList[interfaceIndex].interfaceDesc)
+ ->bInterfaceClass == USB_HOST_HUB_CLASS_CODE)
+ {
+ haveHub = 1;
+ }
+ else
+ {
+ haveNoHub = 1;
+ }
+ }
+
+ if ((haveNoHub == 1) && (hostInstance->deviceCallback != NULL))
+ {
+ status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration,
+ eventCode); /* notify application event */
+ }
+ if (haveHub)
+ {
+ status2 =
+ USB_HostHubDeviceEvent(deviceInstance, &deviceInstance->configuration, eventCode); /* notify hub event */
+ }
+
+ if ((status1 == kStatus_USB_Success) || (status2 == kStatus_USB_Success)) /* the device is supported */
+ {
+ return kStatus_USB_Success;
+ }
+ else if (eventCode == kUSB_HostEventAttach) /* attach event */
+ {
+ status1 = kStatus_USB_NotSupported;
+ }
+ else
+ {
+ status1 = kStatus_USB_Error;
+ }
+#else
+ if (hostInstance->deviceCallback != NULL)
+ {
+ status1 = hostInstance->deviceCallback(deviceInstance, &deviceInstance->configuration,
+ eventCode); /* call host callback function */
+ }
+#endif
+ return status1;
+}
+
+static uint8_t USB_HostAllocateDeviceAddress(usb_host_instance_t *hostInstance)
+{
+ uint8_t address = 0;
+ uint8_t addressIndex;
+ uint8_t addressBitIndex;
+ for (addressIndex = 0; addressIndex < 8; ++addressIndex) /* find the idle address postion byte */
+ {
+ if (hostInstance->addressBitMap[addressIndex] != 0xFF)
+ {
+ break;
+ }
+ }
+ if (addressIndex < 8)
+ {
+ for (addressBitIndex = 0; addressBitIndex < 8; ++addressBitIndex) /* find the idle address position bit */
+ {
+ if (!(hostInstance->addressBitMap[addressIndex] & (0x01u << addressBitIndex)))
+ {
+ hostInstance->addressBitMap[addressIndex] |= (0x01u << addressBitIndex); /* set the allocated bit */
+ address = addressIndex * 8 + addressBitIndex + 1; /* the address minimum is 1 */
+ break;
+ }
+ }
+ }
+ return address;
+}
+
+static void USB_HostReleaseDeviceAddress(usb_host_instance_t *hostInstance, uint8_t address)
+{
+ USB_HostLock();
+ hostInstance->addressBitMap[(uint32_t)(address - 1) >> 3] &=
+ (~(0x01u << (((uint32_t)address - 1) & 0x07U))); /* reset the allocated bit */
+ USB_HostUnlock();
+}
+
+static usb_status_t USB_HostRemoveDeviceInstance(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *currentInstance;
+ usb_host_device_instance_t *prevInstance;
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* search and remove device instance */
+ prevInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ if (prevInstance == deviceHandle)
+ {
+ hostInstance->deviceList = prevInstance->next;
+ return kStatus_USB_Success;
+ }
+ else
+ {
+ currentInstance = prevInstance->next;
+ }
+
+ while (currentInstance != NULL)
+ {
+ if (currentInstance == deviceHandle)
+ {
+ prevInstance->next = currentInstance->next;
+ return kStatus_USB_Success;
+ }
+ prevInstance = currentInstance;
+ currentInstance = currentInstance->next;
+ }
+
+ return kStatus_USB_Success;
+}
+
+static void USB_HostReleaseDeviceResource(usb_host_instance_t *hostInstance, usb_host_device_instance_t *deviceInstance)
+{
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ uint8_t level = 0;
+#endif
+ /* release device's address */
+ if (deviceInstance->setAddress != 0)
+ {
+ USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->setAddress);
+ }
+ else
+ {
+ if (deviceInstance->allocatedAddress != 0)
+ {
+ USB_HostReleaseDeviceAddress(hostInstance, deviceInstance->allocatedAddress);
+ }
+ }
+
+ /* close control pipe */
+ if (deviceInstance->controlPipe != NULL)
+ {
+ USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+ if (USB_HostClosePipe(hostInstance, deviceInstance->controlPipe) != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error when close pipe\r\n");
+#endif
+ }
+ deviceInstance->controlPipe = NULL;
+ }
+
+ /* free configuration buffer */
+ if (deviceInstance->configurationDesc != NULL)
+ {
+ USB_OsaMemoryFree(deviceInstance->configurationDesc);
+ }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ level = deviceInstance->level;
+#endif
+
+ /* free device instance buffer */
+ USB_OsaMemoryFree(deviceInstance);
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ /* enable controller attach if root hub */
+ if (level == 1)
+ {
+ USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach);
+ }
+#else
+ /* enable controller attach */
+ USB_HostControlBus(hostInstance, kUSB_HostBusEnableAttach);
+#endif
+}
+
+static usb_status_t USB_HostParseDeviceConfigurationDescriptor(usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ uint32_t endPos;
+ usb_descriptor_union_t *unionDes;
+ usb_host_interface_t *interfaceParse = NULL;
+ usb_host_ep_t *epParse;
+ uint8_t *buffer;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ buffer = (uint8_t *)&deviceInstance->configuration;
+ /* clear the previous parse result, note: end_pos means buffer index here*/
+ for (endPos = 0; endPos < sizeof(usb_host_configuration_t); endPos++)
+ {
+ buffer[endPos] = 0;
+ }
+ for (endPos = 0; endPos < USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE; ++endPos)
+ {
+ deviceInstance->interfaceStatus[endPos] = 0;
+ }
+
+ /* parse configuration descriptor */
+ unionDes = (usb_descriptor_union_t *)deviceInstance->configurationDesc;
+ endPos = (uint32_t)(deviceInstance->configurationDesc + deviceInstance->configurationLen);
+
+ if ((unionDes->common.bLength == USB_DESCRIPTOR_LENGTH_CONFIGURE) &&
+ (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_CONFIGURE))
+ {
+ /* configuration descriptor */
+ deviceInstance->configuration.configurationDesc = (usb_descriptor_configuration_t *)unionDes;
+ deviceInstance->configuration.configurationExtensionLength = 0;
+ deviceInstance->configuration.configurationExtension = NULL;
+ deviceInstance->configuration.interfaceCount = 0;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE)
+ {
+ if (deviceInstance->configuration.configurationExtension == NULL)
+ {
+ deviceInstance->configuration.configurationExtension = (uint8_t *)unionDes;
+ }
+ if ((unionDes->common.bDescriptorType == 0x00) ||
+ (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ deviceInstance->configuration.configurationExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* interface descriptor */
+ deviceInstance->configuration.interfaceCount = 0;
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE)
+ {
+ if (unionDes->interface.bAlternateSetting == 0x00)
+ {
+ if (deviceInstance->configuration.interfaceCount >= USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE)
+ {
+#ifdef HOST_ECHO
+ usb_echo(
+ "Unsupported Device attached\r\n too many interfaces in one configuration, please increase "
+ "the USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE value\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ interfaceParse =
+ &deviceInstance->configuration.interfaceList[deviceInstance->configuration.interfaceCount];
+ deviceInstance->configuration.interfaceCount++;
+ interfaceParse->alternateSettingNumber = 0;
+ interfaceParse->epCount = 0;
+ interfaceParse->interfaceDesc = &unionDes->interface;
+ interfaceParse->interfaceExtensionLength = 0;
+ interfaceParse->interfaceExtension = NULL;
+ interfaceParse->interfaceIndex = unionDes->interface.bInterfaceNumber;
+ if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ interfaceParse->interfaceExtension = (uint8_t *)unionDes;
+ while ((uint32_t)unionDes < endPos)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+ if ((unionDes->common.bDescriptorType == 0x00) ||
+ (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* endpoint descriptor */
+ if (interfaceParse->interfaceDesc->bNumEndpoints != 0)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+ (interfaceParse->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP))
+ {
+#ifdef HOST_ECHO
+ usb_echo("interface descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ for (; interfaceParse->epCount < interfaceParse->interfaceDesc->bNumEndpoints;
+ (interfaceParse->epCount)++)
+ {
+ if (((uint32_t)unionDes >= endPos) ||
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+#ifdef HOST_ECHO
+ usb_echo("endpoint descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ epParse = (usb_host_ep_t *)&interfaceParse->epList[interfaceParse->epCount];
+ epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes;
+ epParse->epExtensionLength = 0;
+ epParse->epExtension = NULL;
+ if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ epParse->epExtension = (uint8_t *)unionDes;
+ while ((uint32_t)unionDes < endPos)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ if ((unionDes->common.bDescriptorType == 0x00) ||
+ (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ epParse->epExtensionLength += unionDes->common.bLength;
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes =
+ (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ if (interfaceParse == NULL)
+ {
+ return kStatus_USB_Error; /* in normal situation this cannot reach */
+ }
+ interfaceParse->alternateSettingNumber++;
+ if (unionDes->common.bLength == 0x00) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ while ((uint32_t)unionDes < endPos)
+ {
+ if (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE)
+ {
+ if ((unionDes->common.bDescriptorType == 0x00) ||
+ (unionDes->common.bLength == 0x00)) /* the descriptor data is wrong */
+ {
+ return kStatus_USB_Error;
+ }
+ interfaceParse->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ return kStatus_USB_Error;
+ }
+ }
+ }
+
+ for (endPos = 0; endPos < deviceInstance->configuration.interfaceCount; ++endPos)
+ {
+ deviceInstance->interfaceStatus[endPos] = kStatus_interface_Attached;
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
+ uint8_t speed,
+ uint8_t hubNumber,
+ uint8_t portNumber,
+ uint8_t level,
+ usb_device_handle *deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *newInstance;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ usb_host_device_instance_t *currentInstance;
+#endif
+ uint8_t address;
+ usb_host_pipe_init_t pipeInit;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+/* check whether is the device attached? */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ currentInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ while (currentInstance != NULL)
+ {
+ if ((currentInstance->hubNumber == hubNumber) && (currentInstance->portNumber == portNumber))
+ {
+ *deviceHandle = NULL;
+#ifdef HOST_ECHO
+ usb_echo("device has attached\r\n");
+#endif
+ return kStatus_USB_Busy;
+ }
+ else
+ {
+ currentInstance = currentInstance->next;
+ }
+ }
+#else
+ if (hostInstance->deviceList != NULL)
+ {
+ *deviceHandle = NULL;
+ usb_echo("device has attached\r\n");
+ return kStatus_USB_Busy;
+ }
+#endif
+
+ /* Allocate new device instance */
+ newInstance = (usb_host_device_instance_t *)USB_OsaMemoryAllocate(sizeof(usb_host_device_instance_t));
+ if (newInstance == NULL)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate dev instance fail\r\n");
+#endif
+ return kStatus_USB_AllocFail;
+ }
+
+ /* new instance fields init */
+ newInstance->hostHandle = hostHandle;
+ newInstance->speed = speed;
+ newInstance->stallRetries = USB_HOST_CONFIG_ENUMERATION_MAX_STALL_RETRIES;
+ newInstance->enumRetries = USB_HOST_CONFIG_ENUMERATION_MAX_RETRIES;
+ newInstance->setAddress = 0;
+ newInstance->deviceAttachState = kStatus_device_Attached;
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ newInstance->hubNumber = hubNumber;
+ newInstance->portNumber = portNumber;
+ newInstance->level = level;
+
+ if ((speed != USB_SPEED_HIGH) && (level > 1))
+ {
+ newInstance->hsHubNumber = USB_HostHubGetHsHubNumber(hubNumber);
+ newInstance->hsHubPort = USB_HostHubGetHsHubPort(hubNumber, portNumber);
+ }
+ else
+ {
+ newInstance->hsHubNumber = hubNumber;
+ newInstance->hsHubPort = portNumber;
+ }
+#endif /* USB_HOST_CONFIG_HUB */
+
+ USB_HostLock();
+ /* allocate address && insert to the dev list */
+ address = USB_HostAllocateDeviceAddress(hostInstance);
+ if (address == 0)
+ {
+#ifdef HOST_ECHO
+ usb_echo("allocate address fail\r\n");
+#endif
+ USB_HostUnlock();
+ USB_OsaMemoryFree(newInstance);
+ return kStatus_USB_Error;
+ }
+ newInstance->allocatedAddress = address;
+
+ newInstance->next = (usb_host_device_instance_t *)hostInstance->deviceList;
+ hostInstance->deviceList = newInstance;
+ newInstance->state = kStatus_DEV_Initial;
+ USB_HostUnlock();
+
+ /* open control pipe */
+ pipeInit.devInstance = newInstance;
+ pipeInit.pipeType = USB_ENDPOINT_CONTROL;
+ pipeInit.direction = 0;
+ pipeInit.endpointAddress = 0;
+ pipeInit.interval = 0;
+ pipeInit.maxPacketSize = 8;
+ pipeInit.numberPerUframe = 0;
+ pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK;
+ if (USB_HostOpenPipe(hostHandle, &newInstance->controlPipe, &pipeInit) != kStatus_USB_Success)
+ {
+ /* don't need release resource, resource is released when detach */
+ *deviceHandle = newInstance;
+ return kStatus_USB_Error;
+ }
+
+ /* start enumeration */
+ newInstance->state = kStatus_DEV_GetDes8;
+ USB_HostProcessState(newInstance); /* process enumeration state machine */
+
+ *deviceHandle = newInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber)
+{
+ usb_host_device_instance_t *deviceInstance;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ USB_HostLock();
+/* search for device instance handle */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ while (deviceInstance != NULL)
+ {
+ if ((deviceInstance->hubNumber == hubNumber) && (deviceInstance->portNumber == portNumber))
+ {
+ break;
+ }
+ deviceInstance = deviceInstance->next;
+ }
+#else
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+#endif
+ USB_HostUnlock();
+ if (deviceInstance != NULL)
+ {
+ return USB_HostDetachDeviceInternal(hostHandle, deviceInstance); /* device instance detach */
+ }
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ deviceInstance->deviceAttachState = kStatus_device_Detached; /* mark the device is detached from host */
+
+ if (deviceInstance->state >= kStatus_DEV_Initial) /* device instance is valid */
+ {
+ /* detach internally */
+ if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeration is not done */
+ {
+ if (deviceInstance->controlPipe != NULL)
+ {
+ USB_HostCancelTransfer(hostInstance, deviceInstance->controlPipe, NULL);
+ }
+
+ /* remove device instance from host */
+ USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ USB_HostReleaseDeviceResource(hostInstance, deviceInstance);
+ }
+ else /* enumeration has be done and notifed application */
+ {
+ USB_HostNotifyDevice(deviceInstance, kUSB_HostEventDetach); /* notify application device detach */
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle)
+{
+ return deviceHandle ? ((usb_host_device_instance_t *)deviceHandle)->deviceAttachState : 0x0;
+}
+
+usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_device_instance_t *searchDev;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+ /* search for the device */
+ searchDev = (usb_host_device_instance_t *)((usb_host_instance_t *)hostHandle)->deviceList;
+ while ((searchDev != NULL) && ((usb_device_handle)searchDev != deviceHandle))
+ {
+ searchDev = searchDev->next;
+ }
+
+ if (searchDev)
+ {
+ return kStatus_USB_Success;
+ }
+ return kStatus_USB_Error;
+}
+
+static usb_status_t USB_HostControlBus(usb_host_handle hostHandle, uint8_t controlType)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostBusControl,
+ &controlType);
+
+ return status;
+}
+
+usb_status_t USB_HostOpenDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = NULL;
+ uint8_t interfaceIndex;
+ uint8_t index = 0;
+
+ if ((deviceHandle == NULL) || (interfaceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+ USB_HostLock();
+ /* check host_instance valid? */
+ for (; index < USB_HOST_CONFIG_MAX_HOST; ++index)
+ {
+ if ((g_UsbHostInstance[index].occupied == 1) &&
+ ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+ {
+ break;
+ }
+ }
+ if (index >= USB_HOST_CONFIG_MAX_HOST)
+ {
+ USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* check deviceHandle valid? */
+ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+ {
+ USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* search interface and set the interface as opened */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+ {
+ deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Opened;
+ break;
+ }
+ }
+ USB_HostUnlock();
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostCloseDeviceInterface(usb_device_handle deviceHandle, usb_host_interface_handle interfaceHandle)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = NULL;
+ uint8_t interfaceIndex;
+ uint8_t removeLabel = 1;
+ uint8_t index = 0;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+ USB_HostLock();
+ /* check host_instance valid? */
+ for (; index < USB_HOST_CONFIG_MAX_HOST; ++index)
+ {
+ if ((g_UsbHostInstance[index].occupied == 1) &&
+ ((usb_host_instance_t *)(&g_UsbHostInstance[index]) == (hostInstance)))
+ {
+ break;
+ }
+ }
+ if (index >= USB_HOST_CONFIG_MAX_HOST)
+ {
+ USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ /* check deviceHandle valid? */
+ if (USB_HostValidateDevice(hostInstance, deviceHandle) != kStatus_USB_Success)
+ {
+ USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+
+ if (interfaceHandle != NULL)
+ {
+ /* search interface and set the interface as detached */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (&deviceInstance->configuration.interfaceList[interfaceIndex] == interfaceHandle)
+ {
+ deviceInstance->interfaceStatus[interfaceIndex] = kStatus_interface_Detached;
+ break;
+ }
+ }
+ }
+
+ if (deviceInstance->deviceAttachState == kStatus_device_Detached) /* device is removed from host */
+ {
+ removeLabel = 1;
+ /* check all the interfaces of the device are not opened */
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount; ++interfaceIndex)
+ {
+ if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened)
+ {
+ removeLabel = 0;
+ break;
+ }
+ }
+ if (removeLabel == 1)
+ {
+ /* remove device instance from host */
+ USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ }
+ USB_HostUnlock();
+
+ if (removeLabel == 1)
+ {
+ USB_HostReleaseDeviceResource((usb_host_instance_t *)deviceInstance->hostHandle,
+ deviceInstance); /* release device resource */
+ }
+ }
+ else
+ {
+ USB_HostUnlock();
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostRemoveDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ uint8_t interfaceIndex = 0;
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ uint8_t level = 0;
+ uint8_t devHubNo;
+ uint8_t devPortNo;
+#endif
+
+ if ((hostHandle == NULL) || (deviceHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ if (deviceInstance->hostHandle != hostHandle)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ if (USB_HostValidateDevice(hostInstance, deviceInstance) == kStatus_USB_Success) /* device is valid */
+ {
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ devHubNo = deviceInstance->hubNumber;
+ devPortNo = deviceInstance->portNumber;
+ level = deviceInstance->level;
+#endif
+
+ deviceInstance->deviceAttachState = kStatus_device_Detached;
+ if (deviceInstance->state >= kStatus_DEV_Initial) /* device is valid */
+ {
+ if (deviceInstance->state < kStatus_DEV_AppUsed) /* enumeraion is not done or application don't use */
+ {
+ /* detach internally */
+ USB_HostDetachDeviceInternal(hostHandle, deviceHandle);
+ }
+ else /* application use the device */
+ {
+ for (interfaceIndex = 0; interfaceIndex < deviceInstance->configuration.interfaceCount;
+ ++interfaceIndex)
+ {
+ if (deviceInstance->interfaceStatus[interfaceIndex] == kStatus_interface_Opened)
+ {
+#ifdef HOST_ECHO
+ usb_echo("error: there is class instance that is not deinited\r\n");
+#endif
+ break;
+ }
+ }
+ /* remove device instance from host */
+ USB_HostRemoveDeviceInstance(hostInstance, deviceInstance);
+ USB_HostReleaseDeviceResource(hostInstance, deviceInstance); /* release resource */
+ }
+ }
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ if (level == 1)
+ {
+ USB_HostControlBus(hostHandle, kUSB_HostBusReset); /* reset controller port */
+ USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */
+ }
+ else
+ {
+ USB_HostHubRemovePort(devHubNo, devPortNo); /* reset hub port */
+ }
+#else
+ USB_HostControlBus(hostHandle, kUSB_HostBusReset); /* reset controller port */
+ USB_HostControlBus(hostHandle, kUSB_HostBusRestart); /* restart controller port */
+#endif /* USB_HOST_CONFIG_HUB */
+ }
+
+ return kStatus_USB_Success;
+}
diff --git a/usb_1.1.0/host/usb_host_devices.h b/usb_1.1.0/host/usb_host_devices.h
new file mode 100644
index 0000000..6dd0f31
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_devices.h
@@ -0,0 +1,178 @@
+/*
+ * 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_DEV_MNG_H_
+#define _USB_HOST_DEV_MNG_H_
+
+#include "usb_host.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+/*! @brief States of device instances enumeration */
+typedef enum _usb_host_device_enumeration_status
+{
+ kStatus_DEV_Notinit = 0, /*!< Device is invalid */
+ kStatus_DEV_Initial, /*!< Device has been processed by host driver */
+ kStatus_DEV_GetDes8, /*!< Enumeration process: get 8 bytes' device descriptor */
+ kStatus_DEV_SetAddress, /*!< Enumeration process: set device address */
+ kStatus_DEV_GetDes, /*!< Enumeration process: get device descriptor */
+ kStatus_DEV_GetCfg9, /*!< Enumeration process: get 9 bytes' configuration descriptor */
+ kStatus_DEV_GetCfg, /*!< Enumeration process: get configuration descriptor */
+ kStatus_DEV_SetCfg, /*!< Enumeration process: set configuration */
+ kStatus_DEV_EnumDone, /*!< Enumeration is done */
+ kStatus_DEV_AppUsed, /*!< This device has been used by application */
+} usb_host_device_enumeration_status_t;
+
+/*! @brief States of device's interface */
+typedef enum _usb_host_interface_state
+{
+ kStatus_interface_Attached = 1, /*!< Interface's default status */
+ kStatus_interface_Opened, /*!< Interface is used by application */
+ kStatus_interface_Detached, /*!< Interface is not used by application */
+} usb_host_interface_state_t;
+
+/*! @brief States of device */
+typedef enum _usb_host_device_state
+{
+ kStatus_device_Detached = 0, /*!< Device is used by application */
+ kStatus_device_Attached, /*!< Device's default status */
+} usb_host_device_state_t;
+
+/*! @brief Device instance */
+typedef struct _usb_host_device_instance
+{
+ struct _usb_host_device_instance *next; /*!< Next device, or NULL */
+ usb_host_handle hostHandle; /*!< Host handle */
+ usb_host_configuration_t configuration; /*!< Parsed configuration information for the device */
+ usb_descriptor_device_t deviceDescriptor; /*!< Standard device descriptor */
+ usb_host_pipe_handle controlPipe; /*!< Device's control pipe */
+ uint8_t *configurationDesc; /*!< Configuration descriptor pointer */
+ uint16_t configurationLen; /*!< Configuration descriptor length */
+ uint16_t configurationValue; /*!< Configuration index */
+ uint8_t interfaceStatus[USB_HOST_CONFIG_CONFIGURATION_MAX_INTERFACE]; /*!< Interfaces' status, please reference to
+ #usb_host_interface_state_t */
+ uint8_t enumBuffer[9]; /*!< Buffer for enumeration */
+ uint8_t state; /*!< Device state for enumeration */
+ uint8_t enumRetries; /*!< Re-enumeration when error in control transfer */
+ uint8_t stallRetries; /*!< Re-transfer when stall */
+ uint8_t speed; /*!< Device speed */
+ uint8_t allocatedAddress; /*!< Temporary address for the device. When set address request succeeds, setAddress is
+ a value, 1 - 127 */
+ uint8_t setAddress; /*!< The address has been set to the device successfully, 1 - 127 */
+ uint8_t deviceAttachState; /*!< See the usb_host_device_state_t */
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ /* hub related */
+ uint8_t hubNumber; /*!< Device's first connected hub address (root hub = 0) */
+ uint8_t portNumber; /*!< Device's first connected hub's port no (1 - 8) */
+ uint8_t hsHubNumber; /*!< Device's first connected high-speed hub's address (1 - 8) */
+ uint8_t hsHubPort; /*!< Device's first connected high-speed hub's port no (1 - 8) */
+ uint8_t level; /*!< Device's level (root device = 0) */
+#endif
+} usb_host_device_instance_t;
+
+typedef struct _usb_host_enum_process_entry
+{
+ uint8_t successState; /*!< When the last step is successful, the next state value */
+ uint8_t retryState; /*!< When the last step need retry, the next state value */
+ usb_status_t (*process)(usb_host_device_instance_t *deviceInstance); /*!< When the last step transfer is done, the
+ function is used to process the transfer
+ data */
+} usb_host_enum_process_entry_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+/*!
+ * @brief Calls this function when device attach.
+ *
+ * @param hostHandle Host instance handle.
+ * @param speed Device speed.
+ * @param hubNumber Device hub no. root device's hub no. is 0.
+ * @param portNumber Device port no. root device's port no. is 0.
+ * @param level Device level. root device's level is 1.
+ * @param deviceHandle Return device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostAttachDevice(usb_host_handle hostHandle,
+ uint8_t speed,
+ uint8_t hubNumber,
+ uint8_t portNumber,
+ uint8_t level,
+ usb_device_handle *deviceHandle);
+
+/*!
+ * @brief Call this function when device detaches.
+ *
+ * @param hostHandle Host instance handle.
+ * @param hubNumber Device hub no. root device's hub no. is 0.
+ * @param portNumber Device port no. root device's port no. is 0.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostDetachDevice(usb_host_handle hostHandle, uint8_t hubNumber, uint8_t portNumber);
+
+/*!
+ * @brief Call this function when device detaches.
+ *
+ * @param hostHandle Host instance handle.
+ * @param deviceHandle Device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostDetachDeviceInternal(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*!
+ * @brief Gets the the device attach/detach state.
+ *
+ * @param deviceHandle Device handle.
+ *
+ * @return 0x01 - attached; 0x00 - detached.
+ */
+extern uint8_t USB_HostGetDeviceAttachState(usb_device_handle deviceHandle);
+
+/*!
+ * @brief Determine whether the device is attached.
+ *
+ * @param hostHandle Host instance pointer.
+ * @param deviceHandle Device handle.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+extern usb_status_t USB_HostValidateDevice(usb_host_handle hostHandle, usb_device_handle deviceHandle);
+
+/*! @}*/
+#endif /* _USB_HOST_DEV_MNG_H_ */
diff --git a/usb_1.1.0/host/usb_host_framework.c b/usb_1.1.0/host/usb_host_framework.c
new file mode 100644
index 0000000..438f0f3
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_framework.c
@@ -0,0 +1,377 @@
+/*
+ * 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"
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*!
+ * @brief standard control transfer common code.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param buffer data buffer pointer.
+ * @param bufferLen data length.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ uint8_t *buffer,
+ uint32_t bufferLen);
+
+/*!
+ * @brief standard get status implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard set/clear feature implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard set address implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard set/get descriptor implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard get interface implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard set interface implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*!
+ * @brief standard sync frame implementation.
+ *
+ * @param deviceInstance device instance handle.
+ * @param transfer transfer.
+ * @param param parameter.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param);
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+usb_status_t USB_HostCh9RequestCommon(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ uint8_t *buffer,
+ uint32_t bufferLen)
+{
+ /* initialize transfer */
+ transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(bufferLen);
+ transfer->transferBuffer = buffer;
+ transfer->transferLength = bufferLen;
+
+ if (USB_HostSendSetup(deviceInstance->hostHandle, deviceInstance->controlPipe, transfer) !=
+ kStatus_USB_Success) /* send setup transfer */
+ {
+#ifdef HOST_ECHO
+ usb_echo("failt for USB_HostSendSetup\r\n");
+#endif
+ USB_HostFreeTransfer(deviceInstance->hostHandle, transfer);
+ return kStatus_USB_Error;
+ }
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostStandardGetStatus(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_get_status_param_t *statusParam;
+
+ /* initialize transfer */
+ statusParam = (usb_host_get_status_param_t *)param;
+ transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_DIR_IN | USB_REQUEST_TYPE_TYPE_STANDARD;
+ if (statusParam->requestType == kRequestDevice)
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE;
+ }
+ else if (statusParam->requestType == kRequestInterface)
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
+ }
+ else
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
+ }
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(statusParam->interfaceOrEndpoint);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, statusParam->statusBuffer, 2);
+}
+
+usb_status_t USB_HostStandardSetClearFeature(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_process_feature_param_t *featureParam;
+
+ /* initialize transfer */
+ featureParam = (usb_host_process_feature_param_t *)param;
+ if (featureParam->requestType == kRequestDevice)
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_DEVICE;
+ }
+ else if (featureParam->requestType == kRequestInterface)
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
+ }
+ else
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
+ }
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->featureSelector);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(featureParam->interfaceOrEndpoint);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+}
+
+usb_status_t USB_HostStandardSetAddress(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ uint8_t address;
+
+ /* initialize transfer */
+ address = *(uint8_t *)param;
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(address);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+}
+
+usb_status_t USB_HostStandardSetGetDescriptor(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_process_descriptor_param_t *descriptorParam;
+
+ /* initialize transfer */
+ descriptorParam = (usb_host_process_descriptor_param_t *)param;
+ transfer->setupPacket.wValue =
+ ((uint16_t)((uint16_t)descriptorParam->descriptorType << 8) | descriptorParam->descriptorIndex);
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(descriptorParam->languageId);
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, descriptorParam->descriptorBuffer,
+ descriptorParam->descriptorLength);
+}
+
+usb_status_t USB_HostStandardGetInterface(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_get_interface_param_t *interfaceParam;
+
+ /* initialize transfer */
+ interfaceParam = (usb_host_get_interface_param_t *)param;
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(interfaceParam->interface);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, interfaceParam->alternateInterfaceBuffer, 1);
+}
+
+usb_status_t USB_HostStandardSetInterface(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_set_interface_param_t *setParam;
+
+ /* initialize transfer */
+ setParam = (usb_host_set_interface_param_t *)param;
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_INTERFACE;
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(setParam->interface);
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(setParam->alternateSetting);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, NULL, 0);
+}
+
+usb_status_t USB_HostStandardSyncFrame(usb_host_device_instance_t *deviceInstance,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_synch_frame_param_t *frameParam;
+
+ /* initialize transfer */
+ frameParam = (usb_host_synch_frame_param_t *)param;
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_RECIPIENT_ENDPOINT;
+ transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(frameParam->endpoint);
+
+ return USB_HostCh9RequestCommon(deviceInstance, transfer, frameParam->frameNumberBuffer, 2);
+}
+
+usb_status_t USB_HostRequestControl(usb_device_handle deviceHandle,
+ uint8_t usbRequest,
+ usb_host_transfer_t *transfer,
+ void *param)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_status_t status = kStatus_USB_Error;
+
+ if (deviceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* reset transfer fields */
+ transfer->setupPacket.bmRequestType = 0x00;
+ transfer->setupPacket.bRequest = usbRequest;
+ transfer->setupPacket.wIndex = 0;
+ transfer->setupPacket.wLength = 0;
+ transfer->setupPacket.wValue = 0;
+
+ switch (usbRequest)
+ {
+ case USB_REQUEST_STANDARD_GET_STATUS: /* standard get status request */
+ status = USB_HostStandardGetStatus(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_CLEAR_FEATURE: /* standard clear status request */
+ case USB_REQUEST_STANDARD_SET_FEATURE: /* standard set feature request */
+ status = USB_HostStandardSetClearFeature(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_SET_ADDRESS: /* standard set address request */
+ status = USB_HostStandardSetAddress(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_GET_DESCRIPTOR: /* standard get descriptor request */
+ case USB_REQUEST_STANDARD_SET_DESCRIPTOR: /* standard set descriptor request */
+ if (usbRequest == USB_REQUEST_STANDARD_GET_DESCRIPTOR)
+ {
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ }
+ status = USB_HostStandardSetGetDescriptor(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_GET_CONFIGURATION: /* standard get configuration descriptor request */
+ transfer->setupPacket.bmRequestType |= USB_REQUEST_TYPE_DIR_IN;
+ status =
+ USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, (uint8_t *)param, 1);
+ break;
+
+ case USB_REQUEST_STANDARD_SET_CONFIGURATION: /* standard set configuration request */
+ transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(*((uint8_t *)param));
+ status = USB_HostCh9RequestCommon((usb_host_device_instance_t *)deviceHandle, transfer, NULL, 0);
+ break;
+
+ case USB_REQUEST_STANDARD_GET_INTERFACE: /* standard get interface request */
+ status = USB_HostStandardGetInterface(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_SET_INTERFACE: /* standard set interface request */
+ status = USB_HostStandardSetInterface(deviceInstance, transfer, param);
+ break;
+
+ case USB_REQUEST_STANDARD_SYNCH_FRAME: /* standard synch frame request */
+ status = USB_HostStandardSyncFrame(deviceInstance, transfer, param);
+ break;
+
+ default:
+ break;
+ }
+
+ return status;
+}
diff --git a/usb_1.1.0/host/usb_host_framework.h b/usb_1.1.0/host/usb_host_framework.h
new file mode 100644
index 0000000..aeca251
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_framework.h
@@ -0,0 +1,107 @@
+/*
+ * 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_CH9_H_
+#define _USB_HOST_CH9_H_
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+
+/*! @brief Request type */
+typedef enum _usb_host_request_type
+{
+ kRequestDevice = 1U, /*!< Control request object is device */
+ kRequestInterface, /*!< Control request object is interface */
+ kRequestEndpoint, /*!< Control request object is endpoint */
+} usb_host_request_type_t;
+
+/*! @brief For USB_REQUEST_STANDARD_CLEAR_FEATURE and USB_REQUEST_STANDARD_SET_FEATURE */
+typedef struct _usb_host_process_feature_param
+{
+ uint8_t requestType; /*!< See the #usb_host_request_type_t */
+ uint8_t featureSelector; /*!< Set/cleared feature */
+ uint8_t interfaceOrEndpoint; /*!< Interface or end pointer */
+} usb_host_process_feature_param_t;
+
+/*! @brief For USB_REQUEST_STANDARD_GET_DESCRIPTOR and USB_REQUEST_STANDARD_SET_DESCRIPTOR */
+typedef struct _usb_host_process_descriptor_param
+{
+ uint8_t descriptorType; /*!< See the usb_spec.h, such as the USB_DESCRIPTOR_TYPE_DEVICE */
+ uint8_t descriptorIndex; /*!< The descriptor index is used to select a specific descriptor (only for configuration
+ and string descriptors) when several descriptors of the same type are implemented in a
+ device */
+ uint8_t languageId; /*!< It specifies the language ID for string descriptors or is reset to zero for other
+ descriptors */
+ uint8_t *descriptorBuffer; /*!< Buffer pointer */
+ uint16_t descriptorLength; /*!< Buffer data length */
+} usb_host_process_descriptor_param_t;
+
+/*! @brief For USB_REQUEST_STANDARD_GET_INTERFACE */
+typedef struct _usb_host_get_interface_param
+{
+ uint8_t interface; /*!< Interface number */
+ uint8_t *alternateInterfaceBuffer; /*!< Save the transfer result */
+} usb_host_get_interface_param_t;
+
+/*! @brief For USB_REQUEST_STANDARD_GET_STATUS */
+typedef struct _usb_host_get_status_param
+{
+ uint8_t requestType; /*!< See the #usb_host_request_type_t */
+ uint8_t interfaceOrEndpoint; /*!< Interface number or the end pointer number */
+ uint8_t *statusBuffer; /*!< Save the transfer result */
+} usb_host_get_status_param_t;
+
+/*! @brief For USB_REQUEST_STANDARD_SET_INTERFACE */
+typedef struct _usb_host_set_interface_param
+{
+ uint8_t alternateSetting; /*!< Alternate setting value */
+ uint8_t interface; /*!< Interface number */
+} usb_host_set_interface_param_t;
+
+/*! @brief For USB_REQUEST_STANDARD_SYNCH_FRAME */
+typedef struct _usb_host_synch_frame_param
+{
+ uint8_t endpoint; /*!< Endpoint number */
+ uint8_t *frameNumberBuffer; /*!< Frame number data buffer */
+} usb_host_synch_frame_param_t;
+
+/*! @}*/
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#endif /* _USB_HOST_CH9_H_ */
diff --git a/usb_1.1.0/host/usb_host_hci.c b/usb_1.1.0/host/usb_host_hci.c
new file mode 100644
index 0000000..f50af20
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_hci.c
@@ -0,0 +1,754 @@
+/*
+ * 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"
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "usb_host_devices.h"
+#include "fsl_device_registers.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+extern uint32_t USB_HostHubGetTotalThinkTime(uint8_t parentHubNo);
+
+/*!
+ * @brief get the idle host instance.
+ *
+ * @return host instance pointer.
+ */
+static usb_host_instance_t *USB_HostGetInstance(void);
+
+/*!
+ * @brief release host instance.
+ *
+ * @param hostInstance host instance pointer.
+ */
+static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance);
+
+/*!
+ * @brief get the khci/ehci interface.
+ *
+ * @param controllerId controller id.
+ * @param controllerTable return controller interface structure.
+ */
+static void USB_HostGetControllerInterface(uint8_t controllerId,
+ const usb_host_controller_interface_t **controllerTable);
+
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+extern void USB_HostEhciTestModeInit(usb_device_handle devHandle);
+#endif /* USB_HOST_CONFIG_COMPLIANCE_TEST */
+#endif /* USB_HOST_CONFIG_EHCI */
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief USB host instance resource */
+usb_host_instance_t g_UsbHostInstance[USB_HOST_CONFIG_MAX_HOST];
+
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+#include "usb_host_ehci.h"
+static const usb_host_controller_interface_t s_EhciInterface = \
+{
+ USB_HostEhciCreate, USB_HostEhciDestory, USB_HostEhciOpenPipe, USB_HostEhciClosePipe,
+ USB_HostEhciWritePipe, USB_HostEhciReadpipe, USB_HostEhciIoctl,
+};
+#endif /* USB_HOST_CONFIG_EHCI */
+
+#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
+#include "usb_host_khci.h"
+static const usb_host_controller_interface_t s_KhciInterface = \
+{
+ USB_HostKhciCreate, USB_HostKhciDestory, USB_HostKhciOpenPipe, USB_HostKhciClosePipe,
+ USB_HostKhciWritePipe, USB_HostKhciReadpipe, USB_HostKciIoctl,
+};
+#endif /* USB_HOST_CONFIG_KHCI */
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+#if ((defined USB_HOST_CONFIG_COMPLIANCE_TEST) && (USB_HOST_CONFIG_COMPLIANCE_TEST))
+/*FUNCTION*----------------------------------------------------------------
+*
+* Function Name : usb_test_mode_init
+* Returned Value : None
+* Comments :
+* This function is called by common class to initialize the class driver. It
+* is called in response to a select interface call by application
+*
+*END*--------------------------------------------------------------------*/
+usb_status_t USB_HostTestModeInit(usb_device_handle deviceHandle)
+{
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)deviceInstance->hostHandle;
+#endif
+ uint32_t productId;
+ uint32_t vendorId;
+
+ usb_echo("usb host test init\r\n");
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDevicePID, &productId);
+ USB_HostHelperGetPeripheralInformation(deviceHandle, kUSB_HostGetDeviceVID, &vendorId);
+ usb_echo(" vendor id :0x%x product id:0x%x \r\n", vendorId, productId);
+
+ if ((productId != 0x0200U) && (productId != 0x0101) && (productId != 0x0102) && (productId != 0x0103) &&
+ (productId != 0x0104) && (productId != 0x0105) && (productId != 0x0106) && (productId != 0x0107) &&
+ (productId != 0x0108))
+ {
+ usb_echo("Unsupported Device\r\n");
+ }
+
+ if (productId == 0x0200U)
+ {
+ usb_echo("PET test device attached\r\n");
+ }
+ else
+ {
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+ if (hostInstance->controllerTable == &s_EhciInterface)
+ {
+ USB_HostEhciTestModeInit(deviceHandle);
+ }
+#endif
+ }
+
+ return kStatus_USB_Success;
+}
+#endif
+
+static usb_host_instance_t *USB_HostGetInstance(void)
+{
+ uint8_t i = 0;
+ USB_OSA_SR_ALLOC();
+ USB_OSA_ENTER_CRITICAL();
+ for (; i < USB_HOST_CONFIG_MAX_HOST; i++)
+ {
+ if (g_UsbHostInstance[i].occupied != 1)
+ {
+ uint8_t *buffer = (uint8_t *)&g_UsbHostInstance[i];
+ for (uint32_t j = 0U; j < sizeof(usb_host_instance_t); j++)
+ {
+ buffer[j] = 0x00U;
+ }
+ g_UsbHostInstance[i].occupied = 1;
+ USB_OSA_EXIT_CRITICAL();
+ return &g_UsbHostInstance[i];
+ }
+ }
+ USB_OSA_EXIT_CRITICAL();
+ return NULL;
+}
+
+static void USB_HostReleaseInstance(usb_host_instance_t *hostInstance)
+{
+ USB_OSA_SR_ALLOC();
+ USB_OSA_ENTER_CRITICAL();
+ hostInstance->occupied = 0;
+ USB_OSA_EXIT_CRITICAL();
+}
+
+static void USB_HostGetControllerInterface(uint8_t controllerId,
+ const usb_host_controller_interface_t **controllerTable)
+{
+#if ((defined USB_HOST_CONFIG_KHCI) && (USB_HOST_CONFIG_KHCI))
+ if (controllerId == kUSB_ControllerKhci0)
+ {
+ *controllerTable = &s_KhciInterface;
+ }
+#endif /* USB_HOST_CONFIG_KHCI */
+
+#if ((defined USB_HOST_CONFIG_EHCI) && (USB_HOST_CONFIG_EHCI))
+ if (controllerId == kUSB_ControllerEhci0)
+ {
+ *controllerTable = &s_EhciInterface;
+ }
+#endif /* USB_HOST_CONFIG_EHCI */
+}
+
+usb_status_t USB_HostInit(uint8_t controllerId, usb_host_handle *hostHandle, host_callback_t callbackFn)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = NULL;
+ usb_host_transfer_t *transferPrev = NULL;
+ uint8_t i = 0;
+
+ hostInstance = USB_HostGetInstance(); /* get one host instance */
+ if (hostInstance == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* get khci/ehci API table */
+ USB_HostGetControllerInterface(controllerId, &hostInstance->controllerTable);
+ if (hostInstance->controllerTable == NULL)
+ {
+ USB_HostReleaseInstance(hostInstance);
+ return kStatus_USB_ControllerNotFound;
+ }
+
+ /* judge the controller interface one time at here */
+ if ((hostInstance->controllerTable->controllerCreate == NULL) ||
+ (hostInstance->controllerTable->controllerDestory == NULL) ||
+ (hostInstance->controllerTable->controllerOpenPipe == NULL) ||
+ (hostInstance->controllerTable->controllerClosePipe == NULL) ||
+ (hostInstance->controllerTable->controllerWritePipe == NULL) ||
+ (hostInstance->controllerTable->controllerReadPipe == NULL) ||
+ (hostInstance->controllerTable->controllerIoctl == NULL))
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* HOST instance init*/
+ hostInstance->controllerId = controllerId;
+ hostInstance->deviceCallback = callbackFn;
+ hostInstance->deviceList = NULL;
+ if (kStatus_USB_OSA_Success != USB_OsaMutexCreate(&hostInstance->hostMutex))
+ {
+ USB_HostReleaseInstance(hostInstance);
+#ifdef HOST_ECHO
+ usb_echo("host init: create host mutex fail\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+ /* initialize transfer list */
+
+ hostInstance->transferHead = &hostInstance->transferList[0];
+ transferPrev = hostInstance->transferHead;
+ for (i = 1; i < USB_HOST_CONFIG_MAX_TRANSFERS; ++i)
+ {
+ transferPrev->next = &hostInstance->transferList[i];
+ transferPrev = transferPrev->next;
+ }
+
+ /* controller create */
+ status =
+ hostInstance->controllerTable->controllerCreate(controllerId, hostInstance, &(hostInstance->controllerHandle));
+ if ((status != kStatus_USB_Success) || (hostInstance->controllerHandle == NULL))
+ {
+ USB_OsaMutexDestroy(hostInstance->hostMutex);
+ USB_HostReleaseInstance(hostInstance);
+#ifdef HOST_ECHO
+ usb_echo("host init: controller init fail\r\n");
+#endif
+ return kStatus_USB_Error;
+ }
+
+ *hostHandle = hostInstance;
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostDeinit(usb_host_handle hostHandle)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_device_instance_t *deviceInstance = NULL;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* device list detach */
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ while (deviceInstance != NULL)
+ {
+ deviceInstance = (usb_host_device_instance_t *)hostInstance->deviceList;
+ USB_HostDetachDeviceInternal(hostHandle, deviceInstance);
+ }
+
+ /* controller instance destory */
+ status = hostInstance->controllerTable->controllerDestory(hostInstance->controllerHandle);
+ hostInstance->controllerHandle = NULL;
+ if (status != kStatus_USB_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("host controller destory fail\r\n");
+#endif
+ }
+
+ /* resource release */
+ if (hostInstance->hostMutex)
+ {
+ USB_OsaMutexDestroy(hostInstance->hostMutex);
+ hostInstance->hostMutex = NULL;
+ }
+ USB_HostReleaseInstance(hostInstance);
+
+ return status;
+}
+
+usb_status_t USB_HostOpenPipe(usb_host_handle hostHandle,
+ usb_host_pipe_handle *pipeHandle,
+ usb_host_pipe_init_t *pipeInit)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (pipeInit == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* call controller open pipe interface */
+ status = hostInstance->controllerTable->controllerOpenPipe(hostInstance->controllerHandle, pipeHandle, pipeInit);
+
+ return status;
+}
+
+usb_status_t USB_HostClosePipe(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (pipeHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* call controller close pipe interface */
+ status = hostInstance->controllerTable->controllerClosePipe(hostInstance->controllerHandle, pipeHandle);
+
+ return status;
+}
+
+usb_status_t USB_HostSend(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* initialize transfer */
+ transfer->transferSofar = 0;
+ transfer->direction = USB_OUT;
+
+ USB_HostLock(); /* This api can be called by host task and app task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+ if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+ {
+ USB_HostUnlock();
+ return status;
+ }
+#endif
+/* call controller write pipe interface */
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+ if (transfer->transferLength > 0)
+ {
+ USB_CacheFlushLines((void *)transfer->transferBuffer, transfer->transferLength);
+ }
+#endif
+ status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+ USB_HostUnlock();
+ return status;
+}
+
+usb_status_t USB_HostSendSetup(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* initialize transfer */
+ transfer->transferSofar = 0;
+ transfer->next = NULL;
+ transfer->setupStatus = 0;
+ if ((transfer->setupPacket.bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_IN)
+ {
+ transfer->direction = USB_IN;
+ }
+ else
+ {
+ transfer->direction = USB_OUT;
+ }
+
+ USB_HostLock(); /* This API can be called by host task and application task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+ if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+ {
+ USB_HostUnlock();
+ return status;
+ }
+#endif
+/* call controller write pipe interface */
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+ if (transfer->transferLength > 0)
+ {
+ USB_CacheFlushLines((void *)transfer->transferBuffer, transfer->transferLength);
+ }
+#endif
+ status = hostInstance->controllerTable->controllerWritePipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+ USB_HostUnlock();
+ return status;
+}
+
+usb_status_t USB_HostRecv(usb_host_handle hostHandle, usb_host_pipe_handle pipeHandle, usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (pipeHandle == NULL) || (transfer == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* initialize transfer */
+ transfer->transferSofar = 0;
+ transfer->direction = USB_IN;
+
+ USB_HostLock(); /* This API can be called by host task and application task */
+/* keep this code: in normal situation application will guarantee the device is attached when call send/receive function
+ */
+#if 0
+ if ((USB_HostValidateDevice(pipe_ptr->deviceHandle) != kStatus_USB_Success) || (!(USB_HostGetDeviceAttachState(pipe_ptr->deviceHandle))))
+ {
+ USB_HostUnlock();
+ return status;
+ }
+#endif
+
+#if ((defined USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE) && (USB_HOST_CONFIG_BUFFER_PROPERTY_CACHEABLE))
+ if (transfer->transferLength > 0)
+ {
+ USB_CacheInvalidateLines((void *)transfer->transferBuffer, transfer->transferLength);
+ }
+#endif
+ status = hostInstance->controllerTable->controllerReadPipe(hostInstance->controllerHandle, pipeHandle, transfer);
+
+ USB_HostUnlock();
+ return status;
+}
+
+usb_status_t USB_HostCancelTransfer(usb_host_handle hostHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+ usb_host_cancel_param_t cancelParam;
+
+ if ((hostHandle == NULL) || (pipeHandle == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* initialize cancel parameter */
+ cancelParam.pipeHandle = pipeHandle;
+ cancelParam.transfer = transfer;
+
+ /* USB_HostLock(); This api can be called by host task and app task */
+ status = hostInstance->controllerTable->controllerIoctl(hostInstance->controllerHandle, kUSB_HostCancelTransfer,
+ &cancelParam);
+ /* USB_HostUnlock(); */
+
+ return status;
+}
+
+usb_status_t USB_HostMallocTransfer(usb_host_handle hostHandle, usb_host_transfer_t **transfer)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if ((hostHandle == NULL) || (transfer == NULL))
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ /* get one from the transfer_head */
+ USB_HostLock();
+ if (hostInstance->transferHead != NULL)
+ {
+ *transfer = hostInstance->transferHead;
+ hostInstance->transferHead = hostInstance->transferHead->next;
+ USB_HostUnlock();
+ return kStatus_USB_Success;
+ }
+ else
+ {
+ *transfer = NULL;
+ USB_HostUnlock();
+ return kStatus_USB_Error;
+ }
+}
+
+usb_status_t USB_HostFreeTransfer(usb_host_handle hostHandle, usb_host_transfer_t *transfer)
+{
+ usb_host_instance_t *hostInstance = (usb_host_instance_t *)hostHandle;
+
+ if (hostHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+ if (transfer == NULL)
+ {
+ return kStatus_USB_Success;
+ }
+
+ /* release one to the transfer_head */
+ USB_HostLock();
+ transfer->next = hostInstance->transferHead;
+ hostInstance->transferHead = transfer;
+ USB_HostUnlock();
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHelperGetPeripheralInformation(usb_device_handle deviceHandle,
+ uint32_t infoCode,
+ uint32_t *infoValue)
+{
+ usb_host_device_instance_t *deviceInstance = (usb_host_device_instance_t *)deviceHandle;
+ if ((deviceHandle == NULL) || (infoValue == NULL))
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ switch (infoCode)
+ {
+ case kUSB_HostGetDeviceAddress: /* device address */
+ *infoValue = (uint32_t)deviceInstance->setAddress;
+ break;
+
+ case kUSB_HostGetDeviceControlPipe: /* device control pipe */
+ *infoValue = (uint32_t)deviceInstance->controlPipe;
+ break;
+
+ case kUSB_HostGetHostHandle: /* device host handle */
+ *infoValue = (uint32_t)deviceInstance->hostHandle;
+ break;
+
+#if ((defined USB_HOST_CONFIG_HUB) && (USB_HOST_CONFIG_HUB))
+ case kUSB_HostGetDeviceHubNumber: /* device hub address */
+ *infoValue = (uint32_t)deviceInstance->hubNumber;
+ break;
+
+ case kUSB_HostGetDevicePortNumber: /* device port no */
+ *infoValue = (uint32_t)deviceInstance->portNumber;
+ break;
+
+ case kUSB_HostGetDeviceLevel: /* device level */
+ *infoValue = (uint32_t)deviceInstance->level;
+ break;
+
+ case kUSB_HostGetDeviceHSHubNumber: /* device high-speed hub address */
+ *infoValue = (uint32_t)deviceInstance->hsHubNumber;
+ break;
+
+ case kUSB_HostGetDeviceHSHubPort: /* device high-speed hub port no */
+ *infoValue = (uint32_t)deviceInstance->hsHubPort;
+ break;
+
+ case kUSB_HostGetHubThinkTime: /* device hub think time */
+ *infoValue = USB_HostHubGetTotalThinkTime(deviceInstance->hubNumber);
+ break;
+#else
+ case kUSB_HostGetDeviceHubNumber: /* device hub address */
+ case kUSB_HostGetDevicePortNumber: /* device port no */
+ case kUSB_HostGetDeviceHSHubNumber: /* device high-speed hub address */
+ case kUSB_HostGetDeviceHSHubPort: /* device high-speed hub port no */
+ case kUSB_HostGetHubThinkTime: /* device hub think time */
+ *infoValue = 0;
+ break;
+ case kUSB_HostGetDeviceLevel: /* device level */
+ *infoValue = 1;
+ break;
+#endif /* USB_HOST_CONFIG_HUB */
+
+ case kUSB_HostGetDeviceSpeed: /* device speed */
+ *infoValue = (uint32_t)deviceInstance->speed;
+ break;
+
+ case kUSB_HostGetDevicePID: /* device pid */
+ *infoValue = (uint32_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(deviceInstance->deviceDescriptor.idProduct);
+ break;
+
+ case kUSB_HostGetDeviceVID: /* device vid */
+ *infoValue = (uint32_t)USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(deviceInstance->deviceDescriptor.idVendor);
+ break;
+
+ case kUSB_HostGetDeviceConfigIndex: /* device config index */
+ *infoValue = (uint32_t)deviceInstance->configurationValue - 1U;
+ break;
+
+ default:
+ return kStatus_USB_Error;
+ }
+
+ return kStatus_USB_Success;
+}
+
+usb_status_t USB_HostHelperParseAlternateSetting(usb_host_interface_handle interfaceHandle,
+ uint8_t alternateSetting,
+ usb_host_interface_t *interface)
+{
+ uint32_t endPosition;
+ usb_descriptor_union_t *unionDes;
+ usb_host_ep_t *epParse;
+
+ if (interfaceHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ if (alternateSetting == 0)
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ /* parse configuration descriptor */
+ /* interface extend descriptor start */
+ unionDes = (usb_descriptor_union_t *)(((usb_host_interface_t *)interfaceHandle)->interfaceExtension);
+ /* interface extend descriptor end */
+ endPosition = (uint32_t)unionDes + ((usb_host_interface_t *)interfaceHandle)->interfaceExtensionLength;
+
+ /* search for the alternate setting interface descritpor */
+ while ((uint32_t)unionDes < endPosition)
+ {
+ if (unionDes->common.bDescriptorType == USB_DESCRIPTOR_TYPE_INTERFACE)
+ {
+ if (unionDes->interface.bAlternateSetting == alternateSetting)
+ {
+ break;
+ }
+ else
+ {
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ }
+ else
+ {
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ }
+ if ((uint32_t)unionDes >= endPosition)
+ {
+ return kStatus_USB_Error;
+ }
+
+ /* initialize interface handle structure instance */
+ interface->interfaceDesc = &unionDes->interface;
+ interface->alternateSettingNumber = 0;
+ interface->epCount = 0;
+ interface->interfaceExtension = NULL;
+ interface->interfaceExtensionLength = 0;
+ interface->interfaceIndex = unionDes->interface.bInterfaceNumber;
+
+ /* search for endpoint descriptor start position */
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ interface->interfaceExtension = (uint8_t *)unionDes;
+ while ((uint32_t)unionDes < endPosition)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+ interface->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ /* parse endpoint descriptor */
+ if (interface->interfaceDesc->bNumEndpoints != 0)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) ||
+ (interface->interfaceDesc->bNumEndpoints > USB_HOST_CONFIG_INTERFACE_MAX_EP))
+ {
+#ifdef HOST_ECHO
+ usb_echo("interface descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ for (; interface->epCount < interface->interfaceDesc->bNumEndpoints; (interface->epCount)++)
+ {
+ if (((uint32_t)unionDes >= endPosition) ||
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT))
+ {
+#ifdef HOST_ECHO
+ usb_echo("endpoint descriptor error\n");
+#endif
+ return kStatus_USB_Error;
+ }
+ epParse = (usb_host_ep_t *)&interface->epList[interface->epCount];
+ epParse->epDesc = (usb_descriptor_endpoint_t *)unionDes;
+ epParse->epExtensionLength = 0;
+ epParse->epExtension = NULL;
+ interface->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ epParse->epExtension = (uint8_t *)unionDes;
+ while ((uint32_t)unionDes < endPosition)
+ {
+ if ((unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_ENDPOINT) &&
+ (unionDes->common.bDescriptorType != USB_DESCRIPTOR_TYPE_INTERFACE))
+ {
+ epParse->epExtensionLength += unionDes->common.bLength;
+ interface->interfaceExtensionLength += unionDes->common.bLength;
+ unionDes = (usb_descriptor_union_t *)((uint32_t)unionDes + unionDes->common.bLength);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ return kStatus_USB_Success;
+}
+
+void USB_HostGetVersion(uint32_t *version)
+{
+ if (version)
+ {
+ *version =
+ (uint32_t)USB_MAKE_VERSION(USB_STACK_VERSION_MAJOR, USB_STACK_VERSION_MINOR, USB_STACK_VERSION_BUGFIX);
+ }
+}
diff --git a/usb_1.1.0/host/usb_host_hci.h b/usb_1.1.0/host/usb_host_hci.h
new file mode 100644
index 0000000..f73c8f3
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_hci.h
@@ -0,0 +1,118 @@
+/*
+ * 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_HCI_H_
+#define _USB_HOST_HCI_H_
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief USB host lock */
+#define USB_HostLock() USB_OsaMutexLock(hostInstance->hostMutex)
+/*! @brief USB host unlock */
+#define USB_HostUnlock() USB_OsaMutexUnlock(hostInstance->hostMutex)
+
+/*!
+ * @addtogroup usb_host_controller_driver
+ * @{
+ */
+
+/*! @brief USB host controller control code */
+typedef enum _usb_host_controller_control
+{
+ kUSB_HostCancelTransfer = 1U, /*!< Cancel transfer code */
+ kUSB_HostBusControl, /*!< Bus control code */
+ kUSB_HostGetFrameNumber, /*!< Get frame number code */
+ kUSB_HostUpdateControlEndpointAddress, /*!< Update control endpoint address */
+ kUSB_HostUpdateControlPacketSize, /*!< Update control endpoint maximum packet size */
+} usb_host_controller_control_t;
+
+/*! @brief USB host controller bus control code */
+typedef enum _usb_host_bus_control
+{
+ kUSB_HostBusReset = 1U, /*!< Reset bus */
+ kUSB_HostBusRestart, /*!< Restart bus */
+ kUSB_HostBusEnableAttach, /*!< Enable attach */
+ kUSB_HostBusDisableAttach, /*!< Disable attach*/
+} usb_host_bus_control_t;
+
+/*! @brief USB host controller interface structure */
+typedef struct _usb_host_controller_interface
+{
+ usb_status_t (*controllerCreate)(
+ uint8_t controllerId,
+ usb_host_handle upperLayerHandle,
+ usb_host_controller_handle *controllerHandle); /*!< Create a controller instance function prototype*/
+ usb_status_t (*controllerDestory)(
+ usb_host_controller_handle controllerHandle); /*!< Destroy a controller instance function prototype*/
+ usb_status_t (*controllerOpenPipe)(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle *pipeHandle,
+ usb_host_pipe_init_t *pipeInit); /*!< Open a controller pipe function prototype*/
+ usb_status_t (*controllerClosePipe)(
+ usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle); /*!< Close a controller pipe function prototype*/
+ usb_status_t (*controllerWritePipe)(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer); /*!< Write data to a pipe function prototype*/
+ usb_status_t (*controllerReadPipe)(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer); /*!< Read data from a pipe function prototype*/
+ usb_status_t (*controllerIoctl)(usb_host_controller_handle controllerHandle,
+ uint32_t ioctlEvent,
+ void *ioctlParam); /*!< Control a controller function prototype*/
+} usb_host_controller_interface_t;
+
+/*! @}*/
+
+/*!
+ * @addtogroup usb_host_drv
+ * @{
+ */
+
+/*! @brief USB host instance structure */
+typedef struct _usb_host_instance
+{
+ void *controllerHandle; /*!< The low level controller handle*/
+ host_callback_t deviceCallback; /*!< Device attach/detach callback*/
+ usb_osa_mutex_handle hostMutex; /*!< Host layer mutex*/
+ usb_host_transfer_t transferList[USB_HOST_CONFIG_MAX_TRANSFERS]; /*!< Transfer resource*/
+ usb_host_transfer_t *transferHead; /*!< Idle transfer head*/
+ const usb_host_controller_interface_t *controllerTable; /*!< KHCI/EHCI interface*/
+ void *deviceList; /*!< Device list*/
+ uint8_t addressBitMap[16]; /*!< Used for address allocation. The first bit is the address 1, second bit is the
+ address 2*/
+ uint8_t occupied; /*!< 0 - the instance is not occupied; 1 - the instance is occupied*/
+ uint8_t controllerId; /*!< The controller ID*/
+} usb_host_instance_t;
+
+/*! @}*/
+
+#endif /* _USB_HOST_HCI_H_ */
diff --git a/usb_1.1.0/host/usb_host_khci.c b/usb_1.1.0/host/usb_host_khci.c
new file mode 100644
index 0000000..57af624
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_khci.c
@@ -0,0 +1,1886 @@
+/*
+ * 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_KHCI) && (USB_HOST_CONFIG_KHCI))
+#include "usb_host.h"
+#include "usb_host_hci.h"
+#include "fsl_device_registers.h"
+#include "usb_host_khci.h"
+#include "usb_host_devices.h"
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+#if defined(__ICCCF__) || defined(__ICCARM__)
+#pragma segment = "USB_BDT_Z"
+#pragma data_alignment = 512
+__no_init static uint8_t bdt[512] @"USB_BDT_Z";
+#elif defined(__GNUC__)
+__attribute__((aligned(512))) static uint8_t bdt[512];
+#elif defined(__CC_ARM)
+__align(512) uint8_t bdt[512];
+#else
+#error Unsupported compiler, please use IAR, Keil or arm gcc compiler and rebuild the project.
+#endif
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+/*!
+ * @brief get the 2 power value of uint32_t.
+ *
+ * @param data input uint32_t value.
+ *
+ */
+static uint32_t _USB_HostKhciGetRoundUpPow2(uint32_t data)
+{
+ uint8_t i = 0U;
+
+ if ((data == 1U) || (data == 0U))
+ {
+ return data;
+ }
+ while (data != 1U)
+ {
+ data = data >> 1U;
+ i++;
+ }
+ return 1U << (i);
+}
+
+/*!
+ * @brief get the current host khci frame number count.
+ *
+ * @param handle Pointer of the host KHCI state structure.
+ *
+ * @return current frame number count.
+ */
+static uint32_t _USB_HostKhciGetFrameCount(usb_host_controller_handle handle)
+{
+ uint32_t tempFrameCount;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+
+ tempFrameCount = usbHostPointer->usbRegBase->FRMNUMH;
+
+ return (uint16_t)((tempFrameCount << 8U) | (usbHostPointer->usbRegBase->FRMNUML));
+}
+
+/*!
+ * @brief get the total of host khci frame number count.
+ *
+ * @param usbHostPointer Pointer of the host KHCI state structure.
+ *
+ * @return total of frame number count.
+ */
+static uint32_t _USB_HostKhciGetFrameCountSum(usb_khci_host_state_struct_t *usbHostPointer)
+{
+ static uint32_t totalFrameNumber = 0U;
+ static uint16_t oldFrameNumber = 0U;
+ uint16_t frameNumber = 0xFFFFU;
+
+ frameNumber = _USB_HostKhciGetFrameCount((usb_host_controller_handle)usbHostPointer);
+
+ if (frameNumber < oldFrameNumber)
+ {
+ totalFrameNumber += 2048U;
+ }
+
+ oldFrameNumber = frameNumber;
+
+ return (frameNumber + totalFrameNumber);
+}
+
+/*!
+ * @brief host khci delay.
+ *
+ * @param usbHostPointer Pointer of the host KHCI state structure.
+ * @param ms milliseconds.
+ *
+ */
+static void _USB_HostKhciDelay(usb_khci_host_state_struct_t *usbHostPointer, uint32_t ms)
+{
+ uint32_t sofStart;
+ uint32_t sofEnd;
+ sofStart = _USB_HostKhciGetFrameCountSum(usbHostPointer);
+
+ do
+ {
+ sofEnd = _USB_HostKhciGetFrameCountSum(usbHostPointer);
+ } while ((sofEnd - sofStart) < ms);
+}
+
+/*!
+ * @brief Device KHCI isr function.
+ *
+ * The function is KHCI interrupt service routine.
+ *
+ * @param hostHandle The host handle.
+ */
+void USB_HostKhciIsrFunction(void *hostHandle)
+{
+ usb_khci_host_state_struct_t *usbHostPointer;
+
+ uint8_t status;
+
+ if (hostHandle == NULL)
+ {
+ return;
+ }
+
+ usbHostPointer = (usb_khci_host_state_struct_t *)((usb_host_instance_t *)hostHandle)->controllerHandle;
+
+ while (1U)
+ {
+ status = (uint8_t)((usbHostPointer->usbRegBase->ISTAT));
+ status &= (uint8_t)(usbHostPointer->usbRegBase->INTEN);
+
+ if (!status)
+ {
+ break;
+ }
+
+ usbHostPointer->usbRegBase->ISTAT = status;
+
+ if (status & USB_ISTAT_SOFTOK_MASK)
+ {
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_SOF_TOK);
+ }
+
+ if (status & USB_ISTAT_ATTACH_MASK)
+ {
+ usbHostPointer->usbRegBase->INTEN &= (~USB_INTEN_ATTACHEN_MASK);
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_ATTACH);
+ }
+
+ if (status & USB_ISTAT_TOKDNE_MASK)
+ {
+ /* atom transaction done - token done */
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE);
+ }
+
+ if (status & USB_ISTAT_USBRST_MASK)
+ {
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_RESET);
+ }
+ }
+}
+
+/*!
+ * @brief Handle khci host controller attach event.
+ *
+ * The function is used to handle attach event when a device is attached to khci host controller, the process is detect
+ * the line state, do bus reset, and call device attached function.
+ *
+ * @param usbHostPointer Pointer of the host KHCI state structure.
+ *
+ */
+static void _USB_HostKhciAttach(usb_khci_host_state_struct_t *usbHostPointer)
+{
+ uint8_t speed;
+ uint8_t temp;
+ usb_device_handle deviceHandle;
+ uint8_t index = 0U;
+
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
+ usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
+ usbHostPointer->usbRegBase->ADDR = ((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
+ ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
+ usbHostPointer->usbRegBase->ADDR &= (~USB_ADDR_LSEN_MASK);
+
+ /* here wait for about 120ms to check line state */
+ for (volatile uint32_t i = 0U; i < 2000000U; i++)
+ {
+ __ASM("nop");
+ }
+
+ do
+ {
+ temp = ((usbHostPointer->usbRegBase->CTL) & USB_CTL_JSTATE_MASK) ? 0U : 1U;
+ for (volatile uint32_t i = 0U; i < 100000U; i++)
+ {
+ __ASM("nop");
+ }
+ speed = ((usbHostPointer->usbRegBase->CTL) & USB_CTL_JSTATE_MASK) ? 0U : 1U;
+ index++;
+ } while ((temp != speed) && (index < USB_KHCI_MAX_SPEED_DETECTION_COUNT));
+
+ if (temp != speed)
+ {
+#ifdef HOST_ECHO
+ usb_echo("speed not match!\n");
+#endif
+ usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
+ return;
+ }
+ if (((usbHostPointer->usbRegBase->CTL) & USB_CTL_SE0_MASK) == USB_CTL_SE0_MASK)
+ {
+ usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
+ return;
+ }
+
+ if (speed == USB_SPEED_FULL)
+ {
+ usbHostPointer->usbRegBase->ADDR &= (~USB_ADDR_LSEN_MASK);
+ }
+ else if (speed == USB_SPEED_LOW)
+ {
+ usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT = USB_ENDPT_HOSTWOHUB_MASK;
+ usbHostPointer->usbRegBase->ADDR |= USB_ADDR_LSEN_MASK;
+ }
+ else
+ {
+ }
+
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_USBENSOFEN_MASK;
+
+ usbHostPointer->usbRegBase->ISTAT = 0xffU;
+ usbHostPointer->usbRegBase->INTEN &= (~(USB_INTEN_TOKDNEEN_MASK | USB_INTEN_USBRSTEN_MASK));
+
+ /* Do USB bus reset here */
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_RESET_MASK;
+ _USB_HostKhciDelay(usbHostPointer, 30U);
+ usbHostPointer->usbRegBase->CTL &= (~USB_CTL_RESET_MASK);
+
+#ifdef USBCFG_OTG
+ _USB_HostKhciDelay(usbHostPointer, 30U);
+#else
+ _USB_HostKhciDelay(usbHostPointer, 100U);
+#endif
+ usbHostPointer->usbRegBase->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
+ usbHostPointer->usbRegBase->INTEN |= (USB_INTEN_TOKDNEEN_MASK | USB_INTEN_USBRSTEN_MASK);
+ usbHostPointer->deviceAttached++;
+ USB_OsaEventClear(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE);
+ USB_HostAttachDevice(usbHostPointer->hostHandle, speed, 0U, 0U, 1, &deviceHandle);
+
+ usbHostPointer->txBd = 0U;
+ usbHostPointer->rxBd = 0U;
+}
+
+/*!
+ * @brief Handle khci host controller bus reset event.
+ *
+ * The function is used to handle khci host controller bus reset event, reset event also is used for khci detached
+ * detecction.
+ *
+ * @param usbHostPointer Pointer of the host KHCI state structure.
+ *
+ */
+static void _USB_HostKhciReset(usb_khci_host_state_struct_t *usbHostPointer)
+{
+ volatile uint32_t i = 0xfffU;
+ /* clear attach flag */
+ usbHostPointer->usbRegBase->ISTAT = USB_ISTAT_ATTACH_MASK;
+ while (i--)
+ {
+ __ASM("nop");
+ }
+ /* Test the presence of USB device */
+ if ((usbHostPointer->usbRegBase->ISTAT) & USB_ISTAT_ATTACH_MASK)
+ {
+ /* device attached, so really normal reset was performed */
+ usbHostPointer->usbRegBase->INTEN |= USB_ISTAT_USBRST_MASK;
+ usbHostPointer->usbRegBase->ADDR = ((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
+ ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
+ usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT |= USB_ENDPT_HOSTWOHUB_MASK;
+ }
+ else
+ {
+ /* device was detached,, notify about detach */
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_DETACH);
+ }
+}
+
+/*!
+ * @brief Handle khci host controller bus detach event.
+ *
+ * @param usbHostPointer Pointer of the host KHCI state structure.
+ *
+ */
+static void _USB_HostKhciDetach(usb_khci_host_state_struct_t *usbHostPointer)
+{
+ if (usbHostPointer->deviceAttached > 0)
+ {
+ usbHostPointer->deviceAttached--;
+ }
+ else
+ {
+ return;
+ }
+ USB_HostDetachDevice(usbHostPointer->hostHandle, 0U, 0U);
+ /* Enable USB week pull-downs, useful for detecting detach (effectively bus discharge) */
+ usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
+ /* Remove suspend state */
+ usbHostPointer->usbRegBase->USBCTRL &= (~USB_USBCTRL_SUSP_MASK);
+
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
+
+ usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
+
+ usbHostPointer->txBd = 0U;
+ usbHostPointer->rxBd = 0U;
+
+ usbHostPointer->usbRegBase->ISTAT = 0xffU;
+ USB_OsaEventClear(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+}
+
+/*!
+ * @brief get a right transfer from periodic and async list.
+ *
+ * This function return a right transfer for khci atom transfer, the function implemented simple USB transaction
+ * dispatch algorithm.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of pointer of transfer node struct, will get the a tr quest pointer if operator
+ * success, will get NULL pointer if fail.
+ *
+ */
+static void _USB_HostKhciGetRightTrRequest(usb_host_controller_handle handle, usb_host_transfer_t **transfer)
+{
+ usb_host_transfer_t *tempTransfer;
+ usb_host_transfer_t *firstTransfer;
+ usb_host_transfer_t *prevTtransfer;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+ uint32_t frame_number;
+
+ if (handle == NULL)
+ {
+ *transfer = NULL;
+ return;
+ }
+
+ USB_HostKhciLock();
+ /* First check whether periodic list is active, will get transfer from periodic list */
+ if (usbHostPointer->periodicListAvtive)
+ {
+ prevTtransfer = tempTransfer = usbHostPointer->periodicListPointer;
+ frame_number = _USB_HostKhciGetFrameCount(usbHostPointer);
+ /* Will get the transfer if the pipe frame count and current frame count is equal */
+ while (tempTransfer != NULL)
+ {
+ if ((tempTransfer->transferPipe->currentCount != frame_number) &&
+ (frame_number % tempTransfer->transferPipe->interval == 0U) &&
+ (tempTransfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT))
+ {
+ tempTransfer->transferPipe->currentCount = frame_number;
+ *transfer = firstTransfer = tempTransfer;
+ /* Will move the selected interrupt transfer to end of the periodic list */
+ if ((tempTransfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT) && (tempTransfer->next != NULL))
+ {
+ if (tempTransfer == usbHostPointer->periodicListPointer)
+ {
+ usbHostPointer->periodicListPointer = tempTransfer->next;
+ }
+ else
+ {
+ prevTtransfer->next = tempTransfer->next;
+ }
+ while (tempTransfer != NULL)
+ {
+ prevTtransfer = tempTransfer;
+ tempTransfer = tempTransfer->next;
+ }
+ prevTtransfer->next = firstTransfer;
+ firstTransfer->next = NULL;
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+ }
+ USB_HostKhciUnlock();
+ return;
+ }
+ prevTtransfer = tempTransfer;
+ tempTransfer = tempTransfer->next;
+ }
+ }
+ /* will get the first transfer from active list if no active transfer in async list */
+ if (usbHostPointer->asyncListAvtive)
+ {
+ firstTransfer = tempTransfer = usbHostPointer->asyncListPointer;
+ *transfer = firstTransfer;
+
+ if (tempTransfer->next != NULL)
+ {
+ usbHostPointer->asyncListPointer = tempTransfer->next;
+ }
+ else
+ {
+ USB_HostKhciUnlock();
+ return;
+ }
+ tempTransfer = tempTransfer->next;
+ while (tempTransfer != NULL)
+ {
+ prevTtransfer = tempTransfer;
+ tempTransfer = tempTransfer->next;
+ }
+ prevTtransfer->next = firstTransfer;
+ firstTransfer->next = NULL;
+ }
+ USB_HostKhciUnlock();
+}
+
+/*!
+ * @brief unlink transfer from periodic and async khci transfer list.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will be unlink from transfer list.
+ *
+ */
+static void _USB_HostKhciUnlinkTrRequestFromList(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
+{
+ usb_host_transfer_t *temptr = NULL;
+ usb_host_transfer_t *pretr = NULL;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+
+ if ((handle == NULL) || (transfer == NULL))
+ {
+ return;
+ }
+
+ USB_HostKhciLock();
+ if (usbHostPointer->asyncListAvtive == 1U)
+ {
+ temptr = usbHostPointer->asyncListPointer;
+ if (transfer == temptr)
+ {
+ usbHostPointer->asyncListPointer = temptr->next;
+ }
+ else
+ {
+ while (temptr != NULL)
+ {
+ pretr = temptr;
+ temptr = temptr->next;
+ if (transfer == temptr)
+ {
+ pretr->next = temptr->next;
+ break;
+ }
+ }
+ }
+ if (usbHostPointer->asyncListPointer == NULL)
+ {
+ usbHostPointer->asyncListAvtive = 0U;
+ }
+ }
+ if (usbHostPointer->periodicListAvtive == 1U)
+ {
+ temptr = usbHostPointer->periodicListPointer;
+ if (transfer == temptr)
+ {
+ usbHostPointer->periodicListPointer = temptr->next;
+ }
+ else
+ {
+ while (temptr != NULL)
+ {
+ pretr = temptr;
+ temptr = temptr->next;
+ if (transfer == temptr)
+ {
+ pretr->next = temptr->next;
+ break;
+ }
+ }
+ }
+ if (usbHostPointer->periodicListPointer == NULL)
+ {
+ usbHostPointer->periodicListAvtive = 0U;
+ }
+ }
+ USB_HostKhciUnlock();
+}
+
+/*!
+ * @brief link transfer to periodic and async khci transfer list.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will be link to transfer list.
+ *
+ */
+static usb_status_t _USB_HostKhciLinkTrRequestToList(usb_host_controller_handle controllerHandle,
+ usb_host_transfer_t *transfer)
+{
+ usb_host_transfer_t *temptransfer;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+
+ if ((transfer == NULL))
+ {
+ return kStatus_USB_InvalidParameter;
+ }
+
+ USB_HostKhciLock();
+ if ((transfer->transferPipe->pipeType == USB_ENDPOINT_ISOCHRONOUS) ||
+ (transfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT))
+ {
+ if (usbHostPointer->periodicListAvtive == 0U)
+ {
+ usbHostPointer->periodicListPointer = transfer;
+ transfer->next = NULL;
+ usbHostPointer->periodicListAvtive = 1U;
+ }
+ else
+ {
+ temptransfer = usbHostPointer->periodicListPointer;
+ while (temptransfer->next != NULL)
+ {
+ temptransfer = temptransfer->next;
+ }
+ temptransfer->next = transfer;
+ transfer->next = NULL;
+ }
+ }
+ else if ((transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL) ||
+ (transfer->transferPipe->pipeType == USB_ENDPOINT_BULK))
+ {
+ if (usbHostPointer->asyncListAvtive == 0U)
+ {
+ usbHostPointer->asyncListPointer = transfer;
+ transfer->next = NULL;
+ usbHostPointer->asyncListAvtive = 1U;
+ }
+ else
+ {
+ temptransfer = usbHostPointer->asyncListPointer;
+ while (temptransfer->next != NULL)
+ {
+ temptransfer = temptransfer->next;
+ }
+ temptransfer->next = transfer;
+ transfer->next = NULL;
+ }
+ }
+ else
+ {
+ }
+ USB_HostKhciUnlock();
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief khci process tranfer callback function.
+ *
+ * @param controllerHandle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer , which will be process callback.
+ * @param err The return value of transfer.
+ *
+ */
+static void _USB_HostKhciProcessTrCallback(usb_host_controller_handle controllerHandle,
+ usb_host_transfer_t *transfer,
+ int32_t err)
+{
+ usb_status_t status = kStatus_USB_Success;
+
+ if (err == USB_KHCI_ATOM_TR_STALL)
+ {
+ status = kStatus_USB_TransferStall;
+ }
+ else if ((err == USB_KHCI_ATOM_TR_NAK) || (err >= 0))
+ {
+ status = kStatus_USB_Success;
+
+ if (err == USB_KHCI_ATOM_TR_NAK)
+ {
+ status = kStatus_USB_TransferFailed;
+ }
+ }
+ else if (err < 0)
+ {
+ status = kStatus_USB_TransferFailed;
+ }
+ else
+ {
+ }
+
+ transfer->callbackFn(transfer->callbackParam, transfer, status);
+}
+
+/*!
+ * @brief khci transaction done process function.
+ *
+ * @param usbHostPointer Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will be handled process done.
+ *1400
+ */
+static int32_t _USB_HostKhciTransactionDone(usb_khci_host_state_struct_t *usbHostPointer, usb_host_transfer_t *transfer)
+{
+ uint32_t bd;
+ uint8_t err;
+ int32_t transferResult = 0U;
+ uint32_t type = kTr_Unknown;
+ uint32_t *bdPointer = NULL;
+ usb_host_pipe_t *pipeDescPointer = transfer->transferPipe;
+
+ if (pipeDescPointer->pipeType == USB_ENDPOINT_CONTROL)
+ {
+ if (transfer->setupStatus == kTransfer_Setup0)
+ {
+ type = kTr_Ctrl;
+ }
+ else if ((transfer->setupStatus == kTransfer_Setup1))
+ {
+ if (transfer->transferLength)
+ {
+ if (transfer->direction == USB_IN)
+ {
+ type = kTr_In;
+ }
+ else
+ {
+ type = kTr_Out;
+ }
+ }
+ else
+ {
+ type = kTr_In;
+ }
+ }
+ else if (transfer->setupStatus == kTransfer_Setup2)
+ {
+ if (transfer->transferLength)
+ {
+ if (transfer->direction == USB_IN)
+ {
+ type = kTr_Out;
+ }
+ else
+ {
+ type = kTr_In;
+ }
+ }
+ else
+ {
+ type = kTr_In;
+ }
+ }
+ else if (transfer->setupStatus == kTransfer_Setup3)
+ {
+ type = kTr_In;
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ if (pipeDescPointer->direction == USB_IN)
+ {
+ type = kTr_In;
+ }
+ else if (pipeDescPointer->direction == USB_OUT)
+ {
+ type = kTr_Out;
+ }
+ else
+ {
+ }
+ }
+ switch (type)
+ {
+ case kTr_Ctrl:
+ case kTr_Out:
+ usbHostPointer->txBd ^= 1U;
+ bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1, usbHostPointer->txBd);
+ usbHostPointer->txBd ^= 1U;
+ break;
+
+ case kTr_In:
+ usbHostPointer->rxBd ^= 1U;
+ bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 0U, usbHostPointer->rxBd);
+ usbHostPointer->rxBd ^= 1U;
+ break;
+
+ default:
+ bdPointer = NULL;
+ break;
+ }
+
+ if (bdPointer == NULL)
+ {
+ return -1;
+ }
+
+ bd = *bdPointer;
+ err = usbHostPointer->usbRegBase->ERRSTAT;
+ if (err & (USB_ERRSTAT_PIDERR_MASK | USB_ERRSTAT_CRC5EOF_MASK | USB_ERRSTAT_CRC16_MASK | USB_ERRSTAT_DFN8_MASK |
+ USB_ERRSTAT_DMAERR_MASK | USB_ERRSTAT_BTSERR_MASK))
+ {
+ transferResult = -(int32_t)err;
+ return transferResult;
+ }
+ else
+ {
+ if (bd & USB_KHCI_BD_OWN)
+ {
+#ifdef HOST_ECHO
+ usb_echo("Own bit is not clear 0x%x\n", (unsigned int)bd);
+#endif
+ *bdPointer = 0U;
+ }
+ if ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS))
+ {
+ transferResult = (bd >> 16) & 0x3ffU;
+ }
+ else
+ {
+ switch (bd >> 2 & 0xfU)
+ {
+ case 0x03: /* Last Transfer status is DATA0 */
+ case 0x0b: /* Last Transfer status is DATA1 */
+ case 0x02: /* Last Transfer status is ACK */
+ transferResult = (bd >> 16) & 0x3ffU;
+ /* switch data toggle */
+ pipeDescPointer->nextdata01 ^= 1U;
+ break;
+
+ case 0x0e: /* Last Transfer status is STALL */
+ transferResult = USB_KHCI_ATOM_TR_STALL;
+ break;
+
+ case 0x0a: /* Last Transfer status is NAK */
+ transferResult = USB_KHCI_ATOM_TR_NAK;
+ break;
+
+ case 0x00: /* Last Transfer status is bus timeout **/
+ transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
+ break;
+
+ case 0x0f: /* Last Transfer status is data error */
+ transferResult = USB_KHCI_ATOM_TR_DATA_ERROR;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if ((kTr_In == type) && (0 == usbHostPointer->sXferSts.isDmaAlign))
+ {
+ usbHostPointer->sXferSts.isDmaAlign = 1U;
+ if (transferResult > 0)
+ {
+ for (int j = 0; j < transferResult; j++)
+ {
+ usbHostPointer->sXferSts.rxBufOrig[j] = usbHostPointer->sXferSts.rxBuf[j];
+ }
+ }
+ }
+ return transferResult;
+}
+
+/*!
+ * @brief khci atom transaction process function.
+ *
+ * @param usbHostPointer Pointer of the host khci controller instance.
+ * @param type The USB transfer type.
+ * @param pipeDescPointer Pointer of usb pipe desc.
+ * @param bufPointer The memory address is needed to be transferred.
+ * @param len Transferred data length.
+ *
+ * @return 0 mean sucess or other opertor failure error code.
+ *
+ */
+static int32_t _USB_HostKhciAtomNonblockingTransaction(usb_khci_host_state_struct_t *usbHostPointer,
+ uint32_t type,
+ usb_host_pipe_t *pipeDescPointer,
+ uint8_t *bufPointer,
+ uint32_t len)
+{
+ uint32_t *bdPointer = NULL;
+ uint8_t *buf = bufPointer;
+ int32_t transferResult;
+ uint32_t speed;
+ uint32_t address;
+ uint32_t level;
+ uint8_t counter = 0U;
+ uint32_t eventBit;
+ usb_osa_status_t osaStatus;
+ uint8_t epCtlVal;
+
+ len = (len > pipeDescPointer->maxPacketSize) ? pipeDescPointer->maxPacketSize : len;
+ USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, kUSB_HostGetDeviceLevel, &level);
+ USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, kUSB_HostGetDeviceSpeed, &speed);
+ USB_HostHelperGetPeripheralInformation(pipeDescPointer->deviceHandle, kUSB_HostGetDeviceAddress, &address);
+
+ if (speed == USB_SPEED_LOW)
+ {
+ usbHostPointer->usbRegBase->ADDR |= USB_ADDR_LSEN_MASK;
+ }
+ else
+ {
+ usbHostPointer->usbRegBase->ADDR &= (~USB_ADDR_LSEN_MASK);
+ }
+ usbHostPointer->usbRegBase->ADDR = ((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
+ ((((address) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
+
+#if (FSL_FEATURE_USB_KHCI_HOST_ENABLED)
+ epCtlVal = (level == 1 ? USB_ENDPT_HOSTWOHUB_MASK : 0U) | USB_ENDPT_RETRYDIS_MASK | USB_ENDPT_EPTXEN_MASK |
+ USB_ENDPT_EPRXEN_MASK |
+ ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS ? 0 : USB_ENDPT_EPHSHK_MASK));
+#else
+ epCtlVal = USB_ENDPT_EPTXEN_MASK | USB_ENDPT_EPRXEN_MASK |
+ ((pipeDescPointer->pipeType == USB_ENDPOINT_ISOCHRONOUS ? 0 : USB_ENDPT_EPHSHK_MASK));
+#endif
+ usbHostPointer->usbRegBase->ENDPOINT[0U].ENDPT = epCtlVal;
+
+ transferResult = 0U;
+ counter = 0U;
+ /* wait for USB conttoller is ready, and with timeout */
+ while ((usbHostPointer->usbRegBase->CTL) & USB_CTL_TXSUSPENDTOKENBUSY_MASK)
+ {
+ _USB_HostKhciDelay(usbHostPointer, 1U);
+ osaStatus = USB_OsaEventWait(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_TOK_DONE, 0U, 1, &eventBit);
+ if (osaStatus == kStatus_USB_OSA_Success)
+ {
+ transferResult = USB_KHCI_ATOM_TR_RESET;
+ break;
+ }
+ else
+ {
+ counter++;
+ if (counter >= 3)
+ {
+ transferResult = USB_KHCI_ATOM_TR_CRC_ERROR;
+ return transferResult;
+ }
+ }
+ }
+
+ if (!transferResult)
+ {
+#if defined(FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED) && \
+ (FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED == 1U)
+ if (speed == USB_SPEED_LOW)
+ {
+ usbHostPointer->usbRegBase->SOFTHLD = (len * 12 * 7 / 6 + KHCICFG_THSLD_DELAY) / 8;
+ }
+ else
+ {
+ usbHostPointer->usbRegBase->SOFTHLD = (len * 7 / 6 + KHCICFG_THSLD_DELAY) / 8;
+ }
+#endif
+ usbHostPointer->usbRegBase->ERRSTAT = 0xffU;
+
+ if ((kTr_In == type) && ((len & USB_MEM4_ALIGN_MASK) || ((uint32_t)bufPointer & USB_MEM4_ALIGN_MASK)))
+ {
+ if ((usbHostPointer->khciSwapBufPointer != NULL) && (len <= USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER))
+ {
+ buf = (uint8_t *)USB_MEM4_ALIGN((uint32_t)(usbHostPointer->khciSwapBufPointer + 4));
+ usbHostPointer->sXferSts.rxBuf = buf;
+ usbHostPointer->sXferSts.rxBufOrig = bufPointer;
+ usbHostPointer->sXferSts.rxLen = len;
+ usbHostPointer->sXferSts.isDmaAlign = 0U;
+ }
+ }
+ else
+ {
+ usbHostPointer->sXferSts.isDmaAlign = 1U;
+ }
+
+ switch (type)
+ {
+ case kTr_Ctrl:
+ bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1, usbHostPointer->txBd);
+ *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
+ *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN);
+ usbHostPointer->usbRegBase->TOKEN =
+ (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0xD));
+ usbHostPointer->txBd ^= 1U;
+ break;
+ case kTr_In:
+ bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 0U, usbHostPointer->rxBd);
+ *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
+ *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN |
+ USB_KHCI_BD_DATA01(pipeDescPointer->nextdata01));
+ usbHostPointer->usbRegBase->TOKEN =
+ (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0x9));
+ usbHostPointer->rxBd ^= 1U;
+ break;
+ case kTr_Out:
+ bdPointer = (uint32_t *)USB_KHCI_BD_PTR(0U, 1, usbHostPointer->txBd);
+ *(bdPointer + 1U) = USB_LONG_TO_LITTLE_ENDIAN((uint32_t)buf);
+ *bdPointer = USB_LONG_TO_LITTLE_ENDIAN(USB_KHCI_BD_BC(len) | USB_KHCI_BD_OWN |
+ USB_KHCI_BD_DATA01(pipeDescPointer->nextdata01));
+ usbHostPointer->usbRegBase->TOKEN =
+ (USB_TOKEN_TOKENENDPT((uint8_t)pipeDescPointer->endpointAddress) | USB_TOKEN_TOKENPID(0x1));
+ usbHostPointer->txBd ^= 1U;
+ break;
+ default:
+ bdPointer = NULL;
+ break;
+ }
+ }
+
+ return transferResult;
+}
+
+/*!
+ * @brief khci host start tramsfer.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will transfer.
+ *
+ * @retval kKhci_TrTransmiting khci host transaction prime successfully, will enter next stage.
+ * @retval kKhci_TrTransmitDone khci host transaction prime unsuccessfully, will enter exit stage.
+ *
+ */
+static khci_tr_state_t _USB_HostKhciStartTranfer(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
+{
+ static int32_t transferResult;
+ uint8_t *buf;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+
+ if (transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL)
+ {
+ if ((transfer->setupStatus == kTransfer_Setup0))
+ {
+ transferResult = _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, kTr_Ctrl, transfer->transferPipe,
+ (uint8_t *)&transfer->setupPacket, 8U);
+ }
+ else if (transfer->setupStatus == kTransfer_Setup1)
+ {
+ if (transfer->transferLength)
+ {
+ buf = transfer->transferBuffer;
+ buf += transfer->transferSofar;
+ transferResult = _USB_HostKhciAtomNonblockingTransaction(
+ usbHostPointer, (transfer->direction == USB_IN) ? kTr_In : kTr_Out, transfer->transferPipe, buf,
+ transfer->transferLength - transfer->transferSofar);
+ }
+ else
+ {
+ transfer->transferPipe->nextdata01 = 1U;
+ transfer->setupStatus = kTransfer_Setup3;
+ transferResult =
+ _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, kTr_In, transfer->transferPipe, 0U, 0U);
+ }
+ }
+ else if (transfer->setupStatus == kTransfer_Setup2)
+ {
+ if (transfer->transferLength)
+ {
+ transfer->transferPipe->nextdata01 = 1U;
+
+ transferResult = _USB_HostKhciAtomNonblockingTransaction(
+ usbHostPointer, (transfer->direction == USB_IN) ? kTr_Out : kTr_In, transfer->transferPipe, 0U, 0U);
+ }
+ else
+ {
+ transfer->transferPipe->nextdata01 = 1U;
+ transferResult =
+ _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, kTr_In, transfer->transferPipe, 0U, 0U);
+ }
+ }
+ else if (transfer->setupStatus == kTransfer_Setup3)
+ {
+ transfer->transferPipe->nextdata01 = 1U;
+ transferResult =
+ _USB_HostKhciAtomNonblockingTransaction(usbHostPointer, kTr_In, transfer->transferPipe, 0U, 0U);
+ }
+ else
+ {
+ }
+ }
+ else
+ {
+ buf = transfer->transferBuffer;
+ buf += transfer->transferSofar;
+ transferResult = _USB_HostKhciAtomNonblockingTransaction(
+ usbHostPointer, (transfer->transferPipe->direction == USB_IN) ? kTr_In : kTr_Out, transfer->transferPipe,
+ buf, transfer->transferLength - transfer->transferSofar);
+ }
+
+ transfer->transferResult = transferResult;
+
+ if (transfer->transferResult == 0U)
+ {
+ usbHostPointer->trState = kKhci_TrTransmiting;
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ }
+ return (khci_tr_state_t)usbHostPointer->trState;
+}
+
+/*!
+ * @brief khci host finish tramsfer.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will be transfer.
+ *
+ * @retval kKhci_TrGetMsg The current of transaction is transfer done, will enter first stage.
+ * @retval kKhci_TrTransmitDone All of khci host transaction of the transfer have transfer done, will enter exit
+ * stage.
+ *
+ */
+static khci_tr_state_t _USB_HostKhciFinishTranfer(usb_host_controller_handle handle, usb_host_transfer_t *transfer)
+{
+ static int32_t transferResult;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+
+ transfer->transferResult = transferResult = _USB_HostKhciTransactionDone(usbHostPointer, transfer);
+ if (transferResult >= 0)
+ {
+ if (transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL)
+ {
+ if ((transfer->setupStatus == kTransfer_Setup2) || (transfer->setupStatus == kTransfer_Setup3))
+ {
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrStartTransmit;
+ if (transfer->setupStatus == kTransfer_Setup1)
+ {
+ transfer->transferSofar += transferResult;
+ if (((transfer->transferLength - transfer->transferSofar) <= 0U) ||
+ (transferResult < transfer->transferPipe->maxPacketSize))
+ {
+ transfer->setupStatus++;
+ }
+ }
+ else
+ {
+ transfer->setupStatus++;
+ }
+ }
+ }
+ else
+ {
+ transfer->transferSofar += transferResult;
+ if (((transfer->transferLength - transfer->transferSofar) == 0U) ||
+ (transferResult < transfer->transferPipe->maxPacketSize))
+ {
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrStartTransmit;
+ }
+ }
+ }
+ else
+ {
+ if ((transferResult == USB_KHCI_ATOM_TR_NAK))
+ {
+ if (transfer->transferPipe->pipeType == USB_ENDPOINT_INTERRUPT)
+ {
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+ }
+ else
+ {
+ if ((_USB_HostKhciGetFrameCountSum(usbHostPointer) - transfer->frame) > transfer->nakTimeout)
+ {
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ transfer->transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+ }
+ }
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ }
+ }
+ return (khci_tr_state_t)usbHostPointer->trState;
+}
+
+/*!
+ * @brief host khci controller transfer clear up
+ *
+ * The function is used to handle controller transfer clear up.
+ * @param handle Pointer of the host khci controller handle.
+ *
+ *
+ */
+void _USB_HostKhciTransferClearUp(usb_host_controller_handle controllerHandle)
+{
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+ usb_host_transfer_t *trCancel;
+
+ USB_HostKhciLock();
+ trCancel = usbHostPointer->periodicListPointer;
+ USB_HostKhciUnlock();
+ while (trCancel != NULL)
+ {
+ _USB_HostKhciUnlinkTrRequestFromList(controllerHandle, trCancel);
+ trCancel->callbackFn(trCancel->callbackParam, trCancel, kStatus_USB_TransferCancel);
+ USB_HostKhciLock();
+ trCancel = usbHostPointer->periodicListPointer;
+ USB_HostKhciUnlock();
+ }
+
+ USB_HostKhciLock();
+ trCancel = usbHostPointer->asyncListPointer;
+ USB_HostKhciUnlock();
+ while (trCancel != NULL)
+ {
+ _USB_HostKhciUnlinkTrRequestFromList(controllerHandle, trCancel);
+ trCancel->callbackFn(trCancel->callbackParam, trCancel, kStatus_USB_TransferCancel);
+ USB_HostKhciLock();
+ trCancel = usbHostPointer->asyncListPointer;
+ USB_HostKhciUnlock();
+ }
+ usbHostPointer->trState = kKhci_TrGetMsg;
+}
+
+/*!
+ * @brief host khci controller transfer state machine
+ *
+ * The function is used to handle controller transfer state machine.
+ * @param handle Pointer of the host khci controller handle.
+ * @param transfer Pointer of transfer node struct, which will be transfer.
+ *
+ *
+ */
+void _USB_HostKhciTransferStateMachine(usb_host_controller_handle controllerHandle, usb_host_transfer_t **ptransfer)
+{
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+ usb_host_transfer_t *transfer = *ptransfer;
+ usb_host_transfer_t *tempTransfer = NULL;
+ uint32_t eventBit = 0;
+
+ switch (usbHostPointer->trState)
+ {
+ case kKhci_TrGetMsg:
+ transfer = NULL;
+ _USB_HostKhciGetRightTrRequest(controllerHandle, &transfer);
+ if (transfer != NULL)
+ {
+ *ptransfer = transfer;
+ usbHostPointer->trState = _USB_HostKhciStartTranfer(controllerHandle, transfer);
+ usbHostPointer->trState = kKhci_TrTransmiting;
+ }
+ break;
+
+ case kKhci_IsoTrGetMsg:
+ *ptransfer = NULL;
+ if (usbHostPointer->periodicListAvtive)
+ {
+ tempTransfer = usbHostPointer->periodicListPointer;
+ while (tempTransfer != NULL)
+ {
+ if ((_USB_HostKhciGetFrameCount(usbHostPointer) % tempTransfer->transferPipe->interval == 0U) &&
+ (tempTransfer->transferPipe->pipeType == USB_ENDPOINT_ISOCHRONOUS))
+ {
+ *ptransfer = tempTransfer;
+
+ _USB_HostKhciStartTranfer(controllerHandle, tempTransfer);
+ usbHostPointer->trState = kKhci_TrTransmiting;
+ if (kStatus_USB_OSA_Success == USB_OsaEventWait(usbHostPointer->khciEventPointer,
+ USB_KHCI_EVENT_TOK_DONE, 0U, 0, &eventBit))
+ {
+ if (eventBit & USB_KHCI_EVENT_TOK_DONE)
+ {
+ _USB_HostKhciTransactionDone(usbHostPointer, tempTransfer);
+ _USB_HostKhciUnlinkTrRequestFromList(usbHostPointer, tempTransfer);
+ _USB_HostKhciProcessTrCallback(usbHostPointer, tempTransfer, transfer->transferResult);
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ }
+ }
+ else
+ {
+ usbHostPointer->trState = kKhci_TrTransmiting;
+ }
+ break;
+ }
+ tempTransfer = tempTransfer->next;
+ }
+ }
+ if (*ptransfer == NULL)
+ {
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ }
+ break;
+
+ case kKhci_TrStartTransmit:
+ if (transfer != NULL)
+ {
+ usbHostPointer->trState = _USB_HostKhciStartTranfer(controllerHandle, transfer);
+ }
+ break;
+
+ case kKhci_TrTransmiting:
+ if (transfer != NULL)
+ {
+ if ((_USB_HostKhciGetFrameCountSum(usbHostPointer) - transfer->frame) > USB_TIMEOUT_OTHER)
+ {
+ if ((transfer->transferPipe->pipeType == USB_ENDPOINT_CONTROL) ||
+ (transfer->transferPipe->pipeType == USB_ENDPOINT_BULK))
+ {
+ /* clear current bdt status */
+ _USB_HostKhciTransactionDone(usbHostPointer, transfer);
+ usbHostPointer->trState = kKhci_TrTransmitDone;
+ transfer->transferResult = USB_KHCI_ATOM_TR_BUS_TIMEOUT;
+ return;
+ }
+ }
+ }
+ break;
+
+ case kKhci_TrTransmitDone:
+ if (transfer != NULL)
+ {
+ _USB_HostKhciUnlinkTrRequestFromList(usbHostPointer, transfer);
+ _USB_HostKhciProcessTrCallback(usbHostPointer, transfer, transfer->transferResult);
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ if ((usbHostPointer->asyncListAvtive == 1U) || (usbHostPointer->periodicListAvtive == 1U))
+ {
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*!
+ * @brief khci task function.
+ *
+ * The function is used to handle KHCI controller message.
+ * In the BM environment, this function should be called periodically in the main function.
+ * And in the RTOS environment, this function should be used as a function entry to create a task.
+ *
+ * @param hostHandle The host handle.
+ */
+void USB_HostKhciTaskFunction(void *hostHandle)
+{
+ volatile ptr_usb_host_khci_state_struct_t usbHostPointer;
+ uint32_t eventBit = 0;
+ static usb_host_transfer_t *transfer;
+
+ if (hostHandle == NULL)
+ {
+ return;
+ }
+
+ usbHostPointer = (usb_khci_host_state_struct_t *)(((usb_host_instance_t *)hostHandle)->controllerHandle);
+ if (USB_OsaEventWait(usbHostPointer->khciEventPointer, 0xff, 0U, 1U, &eventBit) ==
+ kStatus_USB_OSA_Success) /* wait all event */
+ {
+ if (eventBit & USB_KHCI_EVENT_ATTACH)
+ {
+ _USB_HostKhciAttach(usbHostPointer);
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ }
+ if (eventBit & USB_KHCI_EVENT_RESET)
+ {
+ _USB_HostKhciReset(usbHostPointer);
+ }
+ if (eventBit & USB_KHCI_EVENT_DETACH)
+ {
+ _USB_HostKhciDetach(usbHostPointer);
+ }
+ if (eventBit & USB_KHCI_EVENT_SOF_TOK)
+ {
+ if ((kKhci_TrGetMsg == usbHostPointer->trState) && (usbHostPointer->deviceAttached))
+ {
+ usbHostPointer->trState = kKhci_IsoTrGetMsg;
+ _USB_HostKhciTransferStateMachine(usbHostPointer, &transfer);
+ }
+ }
+ if (eventBit & USB_KHCI_EVENT_TOK_DONE)
+ {
+ if (transfer != NULL)
+ {
+ usbHostPointer->trState =
+ _USB_HostKhciFinishTranfer(((usb_host_instance_t *)hostHandle)->controllerHandle, transfer);
+ }
+ }
+ }
+ if (usbHostPointer->deviceAttached)
+ {
+ _USB_HostKhciTransferStateMachine(usbHostPointer, &transfer);
+ }
+ else
+ {
+ _USB_HostKhciTransferClearUp(usbHostPointer);
+ }
+}
+
+/*!
+ * @brief create the USB host khci instance.
+ *
+ * This function initializes the USB host khci controller driver.
+ *
+ * @param controllerId The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t.
+ * @param hostHandle The host level handle.
+ * @param controllerHandle Return the controller instance handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_AllocFail allocate memory fail.
+ * @retval kStatus_USB_Error host mutex create fail, KHCI/EHCI mutex or KHCI/EHCI event create fail.
+ * Or, KHCI/EHCI IP initialize fail.
+ *
+ */
+usb_status_t USB_HostKhciCreate(uint8_t controllerId,
+ usb_host_handle hostHandle,
+ usb_host_controller_handle *controllerHandle)
+{
+ usb_khci_host_state_struct_t *usbHostPointer;
+ usb_status_t status = kStatus_USB_Success;
+ usb_osa_status_t osaStatus;
+ uint32_t usb_base_addrs[] = USB_BASE_ADDRS;
+
+ if (((controllerId - kUSB_ControllerKhci0) >= (uint8_t)USB_HOST_CONFIG_KHCI) ||
+ ((controllerId - kUSB_ControllerKhci0) >= (sizeof(usb_base_addrs) / sizeof(uint32_t))))
+ {
+ return kStatus_USB_ControllerNotFound;
+ }
+
+ usbHostPointer = (usb_khci_host_state_struct_t *)USB_OsaMemoryAllocate(sizeof(usb_khci_host_state_struct_t));
+ if (NULL == usbHostPointer)
+ {
+ *controllerHandle = NULL;
+ return kStatus_USB_AllocFail;
+ }
+
+ /* Allocate the USB Host Pipe Descriptors */
+ usbHostPointer->pipeDescriptorBasePointer = NULL;
+ usbHostPointer->hostHandle = hostHandle;
+ *controllerHandle = (usb_host_handle)usbHostPointer;
+
+ if (NULL == (usbHostPointer->khciSwapBufPointer =
+ (uint8_t *)USB_OsaMemoryAllocate(USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER + 4)))
+ {
+#ifdef HOST_DEBUG_
+ usb_echo("usbHostPointer->khciSwapBufPointer- memory allocation failed");
+#endif
+ USB_HostKhciDestory(controllerHandle);
+ return kStatus_USB_AllocFail;
+ }
+
+ /* init khci mutext */
+ osaStatus = USB_OsaMutexCreate(&usbHostPointer->khciMutex);
+ if (osaStatus != kStatus_USB_OSA_Success)
+ {
+#ifdef HOST_ECHO
+ usb_echo("khci mutex init fail\r\n");
+#endif
+ USB_HostKhciDestory(controllerHandle);
+ return kStatus_USB_Error;
+ }
+
+ USB_OsaEventCreate(&usbHostPointer->khciEventPointer, 1U);
+ if (usbHostPointer->khciEventPointer == NULL)
+ {
+#ifdef HOST_ECHO
+ usb_echo(" memalloc failed in usb_khci_init\n");
+#endif
+
+ return kStatus_USB_AllocFail;
+ } /* Endif */
+
+ usbHostPointer->usbRegBase = (USB_Type *)usb_base_addrs[controllerId - kUSB_ControllerKhci0];
+
+ usbHostPointer->asyncListAvtive = 0U;
+ usbHostPointer->periodicListAvtive = 0U;
+ usbHostPointer->periodicListPointer = NULL;
+ usbHostPointer->asyncListPointer = NULL;
+ usbHostPointer->sXferSts.isDmaAlign = 0U;
+
+ /* set internal register pull down */
+ usbHostPointer->usbRegBase->CTL = USB_CTL_SE0_MASK;
+
+ /* Reset USB CTRL register */
+ usbHostPointer->usbRegBase->CTL = 0UL;
+ usbHostPointer->usbRegBase->ISTAT = 0xffU;
+ /* Enable week pull-downs, useful for detecting detach (effectively bus discharge) */
+ usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
+ /* Remove suspend state */
+ usbHostPointer->usbRegBase->USBCTRL &= (~USB_USBCTRL_SUSP_MASK);
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
+
+ usbHostPointer->usbRegBase->BDTPAGE1 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 8U);
+ usbHostPointer->usbRegBase->BDTPAGE2 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 16);
+ usbHostPointer->usbRegBase->BDTPAGE3 = (uint8_t)((uint32_t)USB_KHCI_BDT_BASE >> 24);
+ /* Set SOF threshold */
+ usbHostPointer->usbRegBase->SOFTHLD = 255;
+
+ usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
+ /* Wait for attach interrupt */
+ usbHostPointer->usbRegBase->INTEN |= (USB_INTEN_ATTACHEN_MASK);// | USB_INTEN_SOFTOKEN_MASK);
+#if defined(FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED) && \
+ (FSL_FEATURE_USB_KHCI_DYNAMIC_SOF_THRESHOLD_COMPARE_ENABLED == 1U)
+ usbHostPointer->usbRegBase->MISCCTRL |= USB_MISCCTRL_SOFDYNTHLD_MASK;
+#endif
+ usbHostPointer->trState = kKhci_TrGetMsg;
+ return status;
+}
+
+/*!
+ * @brief destroy USB host khci instance.
+ *
+ * This function de-initialize the USB host khci controller driver.
+ *
+ * @param handle the controller handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ */
+usb_status_t USB_HostKhciDestory(usb_host_controller_handle controllerHandle)
+{
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+
+ usbHostPointer->usbRegBase->INTEN &= (~0xFFU);
+
+ usbHostPointer->usbRegBase->ADDR = ((usbHostPointer->usbRegBase->ADDR & (~USB_ADDR_ADDR_MASK)) |
+ ((((0U) << USB_ADDR_ADDR_SHIFT) & USB_ADDR_ADDR_MASK)));
+ usbHostPointer->usbRegBase->CTL &= (~0xFFu);
+ usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_PDE_MASK;
+ usbHostPointer->usbRegBase->USBCTRL |= USB_USBCTRL_SUSP_MASK;
+ usbHostPointer->usbRegBase->ADDR &= (~USB_ADDR_LSEN_MASK);
+
+ if (NULL != usbHostPointer->khciEventPointer)
+ {
+ USB_OsaEventDestroy(usbHostPointer->khciEventPointer);
+ }
+ if (NULL != usbHostPointer->khciMutex)
+ {
+ USB_OsaMutexDestroy(usbHostPointer->khciMutex);
+ }
+
+ if (NULL != usbHostPointer->khciSwapBufPointer)
+ {
+ USB_OsaMemoryFree(usbHostPointer->khciSwapBufPointer);
+ usbHostPointer->khciSwapBufPointer = NULL;
+ }
+
+ USB_OsaMemoryFree(usbHostPointer);
+ usbHostPointer = NULL;
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief open USB host pipe.
+ *
+ * This function open one pipe according to the pipeInitPointer parameter.
+ *
+ * @param controllerHandle the controller handle.
+ * @param pipeHandlePointer the pipe handle pointer, it is used to return the pipe handle.
+ * @param pipeInitPointer it is used to initialize the pipe.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_Error there is no idle pipe.
+*
+*/
+usb_status_t USB_HostKhciOpenPipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle *pipeHandlePointer,
+ usb_host_pipe_init_t *pipeInitPointer)
+{
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+ usb_host_pipe_t *pipePointer;
+ usb_host_pipe_t *prePipePointer;
+ usb_host_pipe_t *tempPipePointer;
+
+ USB_OSA_SR_ALLOC();
+ USB_OSA_ENTER_CRITICAL();
+ pipePointer = (usb_host_pipe_t *)USB_OsaMemoryAllocate(sizeof(usb_host_pipe_t));
+ if (pipePointer == NULL)
+ {
+ USB_OsaMemoryFree(usbHostPointer);
+ return kStatus_USB_AllocFail;
+ }
+ else
+ {
+ if (usbHostPointer->pipeDescriptorBasePointer == NULL)
+ {
+ usbHostPointer->pipeDescriptorBasePointer = pipePointer;
+ }
+ else
+ {
+ tempPipePointer = usbHostPointer->pipeDescriptorBasePointer;
+ while (NULL != tempPipePointer)
+ {
+ prePipePointer = tempPipePointer;
+ tempPipePointer = tempPipePointer->next;
+ }
+ prePipePointer->next = pipePointer;
+ }
+ pipePointer->next = NULL;
+ }
+ USB_OSA_EXIT_CRITICAL();
+
+ pipePointer->deviceHandle = pipeInitPointer->devInstance;
+ pipePointer->endpointAddress = pipeInitPointer->endpointAddress;
+ pipePointer->direction = pipeInitPointer->direction;
+ pipePointer->interval = pipeInitPointer->interval;
+ pipePointer->maxPacketSize = pipeInitPointer->maxPacketSize;
+ pipePointer->pipeType = pipeInitPointer->pipeType;
+ pipePointer->numberPerUframe = pipeInitPointer->numberPerUframe;
+ pipePointer->nakCount = pipeInitPointer->nakCount;
+ pipePointer->nextdata01 = 0U;
+ pipePointer->open = (uint8_t)1U;
+ pipePointer->currentCount = 0xffffU;
+
+ if (pipePointer->pipeType == USB_ENDPOINT_ISOCHRONOUS)
+ {
+ pipePointer->interval = 1 << (pipeInitPointer->interval - 1U);
+ }
+ else
+ {
+ pipePointer->interval = _USB_HostKhciGetRoundUpPow2(pipeInitPointer->interval);
+ }
+ *pipeHandlePointer = pipePointer;
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief close USB host pipe.
+ *
+ * This function close one pipe and release the related resources.
+ *
+ * @param controllerHandle the controller handle.
+ * @param pipeHandle the closing pipe handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ */
+usb_status_t USB_HostKhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle)
+{
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+ usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
+ usb_host_pipe_t *prePipePointer;
+
+ USB_OSA_SR_ALLOC();
+ USB_OSA_ENTER_CRITICAL();
+
+ if ((pipePointer != NULL) && (pipePointer->open == (uint8_t)1U))
+ {
+ if (pipeHandle == usbHostPointer->pipeDescriptorBasePointer)
+ {
+ usbHostPointer->pipeDescriptorBasePointer = usbHostPointer->pipeDescriptorBasePointer->next;
+ USB_OsaMemoryFree(pipeHandle);
+ }
+ else
+ {
+ pipePointer = usbHostPointer->pipeDescriptorBasePointer;
+ prePipePointer = pipePointer;
+ while (NULL != pipePointer)
+ {
+ if ((pipePointer->open) && (pipePointer == pipeHandle))
+ {
+ prePipePointer->next = pipePointer->next;
+ if (NULL != pipePointer)
+ {
+ USB_OsaMemoryFree(pipePointer);
+ pipePointer = NULL;
+ }
+ break;
+ }
+ prePipePointer = pipePointer;
+ pipePointer = pipePointer->next;
+ }
+ }
+ }
+ else
+ {
+#ifdef HOST_ECHO
+ usb_echo("usb_khci_close_pipe invalid pipe \n");
+#endif
+ }
+ USB_OSA_EXIT_CRITICAL();
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief send data to pipe.
+ *
+ * This function request to send the transfer to the specified pipe.
+ *
+ * @param controllerHandle the controller handle.
+ * @param pipeHandle the sending pipe handle.
+ * @param transfer the transfer which will be wrote.
+ *
+ * @retval kStatus_USB_Success send successfully.
+ * @retval kStatus_USB_LackSwapBuffer there is no swap buffer for KHCI.
+ *
+ */
+usb_status_t USB_HostKhciWritePipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+
+ usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
+
+ transfer->transferPipe = pipePointer;
+ transfer->retry = RETRY_TIME;
+
+ if (pipePointer->endpointAddress == 0U)
+ {
+ if ((transfer->direction == USB_IN) && (transfer->transferBuffer != NULL) &&
+ ((transfer->transferLength & USB_MEM4_ALIGN_MASK) ||
+ ((uint32_t)transfer->transferBuffer & USB_MEM4_ALIGN_MASK)))
+ {
+ if (usbHostPointer->khciSwapBufPointer == NULL)
+ {
+ return kStatus_USB_LackSwapBuffer;
+ }
+ if (pipePointer->maxPacketSize > USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER)
+ {
+ return kStatus_USB_LackSwapBuffer;
+ }
+ }
+ transfer->setupStatus = kTransfer_Setup0;
+
+ if (transfer->transferLength)
+ {
+ if (transfer->direction == USB_IN)
+ {
+ transfer->nakTimeout = USB_TIMEOUT_TOHOST;
+ }
+ else
+ {
+ transfer->nakTimeout = USB_TIMEOUT_TODEVICE;
+ }
+ }
+ else
+ {
+ transfer->nakTimeout = USB_TIMEOUT_NODATA;
+ }
+ }
+ else
+ {
+ if (pipePointer->nakCount == 0U)
+ {
+ transfer->nakTimeout = USB_TIMEOUT_DEFAULT;
+ }
+ else
+ {
+ transfer->nakTimeout = pipePointer->nakCount * NAK_RETRY_TIME;
+ }
+ }
+ transfer->frame = _USB_HostKhciGetFrameCountSum(usbHostPointer);
+
+ _USB_HostKhciLinkTrRequestToList(controllerHandle, transfer);
+
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+
+ return status;
+}
+
+/*!
+ * @brief receive data from pipe.
+ *
+ * This function request to receive the transfer from the specified pipe.
+ *
+ * @param controllerHandle the controller handle.
+ * @param pipeHandle the receiving pipe handle.
+ * @param transfer the transfer which will be read.
+ *
+ * @retval kStatus_USB_Success send successfully.
+ * @retval kStatus_USB_LackSwapBuffer there is no swap buffer for KHCI.
+ *
+ */
+usb_status_t USB_HostKhciReadpipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)controllerHandle;
+ usb_host_pipe_t *pipePointer = (usb_host_pipe_t *)pipeHandle;
+
+ if ((transfer->transferLength & USB_MEM4_ALIGN_MASK) || ((uint32_t)transfer->transferBuffer & USB_MEM4_ALIGN_MASK))
+ {
+ if (usbHostPointer->khciSwapBufPointer == NULL)
+ {
+ return kStatus_USB_LackSwapBuffer;
+ }
+ if (pipePointer->maxPacketSize > USB_HOST_CONFIG_KHCI_DMA_ALIGN_BUFFER)
+ {
+ return kStatus_USB_LackSwapBuffer;
+ }
+ }
+
+ transfer->transferPipe = pipePointer;
+ transfer->transferSofar = 0U;
+ if (pipePointer->nakCount == 0U)
+ {
+ transfer->nakTimeout = USB_TIMEOUT_DEFAULT;
+ }
+ else
+ {
+ transfer->nakTimeout = pipePointer->nakCount * NAK_RETRY_TIME;
+ }
+ transfer->retry = RETRY_TIME;
+ transfer->frame = _USB_HostKhciGetFrameCountSum(usbHostPointer);
+
+ _USB_HostKhciLinkTrRequestToList(controllerHandle, transfer);
+ USB_OsaEventSet(usbHostPointer->khciEventPointer, USB_KHCI_EVENT_MSG);
+
+ return status;
+}
+
+/*!
+ * @brief cancel pipe's transfers.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param pipePointer Pointer of the pipe.
+ * @param trPointer The canceling transfer.
+ *
+ * @return kStatus_USB_Success or error codes.
+ */
+static usb_status_t _USB_HostKhciCancelPipe(usb_host_controller_handle handle,
+ usb_host_pipe_t *pipePointer,
+ usb_host_transfer_t *trPointer)
+{
+ usb_host_transfer_t *temptr = NULL;
+ usb_khci_host_state_struct_t *usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+
+ if ((pipePointer->pipeType == USB_ENDPOINT_ISOCHRONOUS) || (pipePointer->pipeType == USB_ENDPOINT_INTERRUPT))
+ {
+ temptr = usbHostPointer->periodicListPointer;
+ }
+ else if ((pipePointer->pipeType == USB_ENDPOINT_CONTROL) || (pipePointer->pipeType == USB_ENDPOINT_BULK))
+ {
+ temptr = usbHostPointer->asyncListPointer;
+ }
+ else
+ {
+ }
+
+ while (temptr != NULL)
+ {
+ if (((usb_host_pipe_t *)(temptr->transferPipe) == pipePointer) &&
+ ((trPointer == NULL) || (trPointer == temptr)))
+ {
+ _USB_HostKhciUnlinkTrRequestFromList(handle, temptr);
+ temptr->callbackFn(temptr->callbackParam, temptr, kStatus_USB_TransferCancel);
+ return kStatus_USB_Success;
+ }
+ temptr = temptr->next;
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief khci bus control.
+ *
+ * @param handle Pointer of the host khci controller handle.
+ * @param busControl Bus control code.
+ *
+ * @return kStatus_USB_Success
+ */
+static usb_status_t _USB_HostKhciBusControl(usb_host_controller_handle handle, uint8_t busControl)
+{
+ ptr_usb_host_khci_state_struct_t usbHostPointer = (usb_khci_host_state_struct_t *)handle;
+ if (busControl == kUSB_HostBusReset)
+ {
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_RESET_MASK;
+ /* wait for 30 milliseconds (2.5 is minimum for reset, 10 recommended) */
+ _USB_HostKhciDelay(usbHostPointer, 30U);
+ usbHostPointer->usbRegBase->CTL &= (~USB_CTL_RESET_MASK);
+ usbHostPointer->usbRegBase->CTL |= USB_CTL_ODDRST_MASK;
+ usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
+
+ usbHostPointer->txBd = 0U;
+ usbHostPointer->rxBd = 0U;
+ }
+ else if (busControl == kUSB_HostBusRestart)
+ {
+ usbHostPointer->deviceAttached = 0U;
+
+ usbHostPointer->usbRegBase->CTL = USB_CTL_HOSTMODEEN_MASK;
+ usbHostPointer->usbRegBase->ISTAT = 0xffU;
+ /* Now, enable only USB interrupt attach for host mode */
+ usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
+ }
+ else if (busControl == kUSB_HostBusEnableAttach)
+ {
+ if (usbHostPointer->deviceAttached <= 0)
+ {
+ usbHostPointer->usbRegBase->INTEN |= USB_INTEN_ATTACHEN_MASK;
+ }
+ }
+ else if (busControl == kUSB_HostBusDisableAttach)
+ {
+ usbHostPointer->usbRegBase->INTEN &= (~USB_INTEN_ATTACHEN_MASK);
+ }
+ else
+ {
+ }
+
+ return kStatus_USB_Success;
+}
+
+/*!
+ * @brief io control khci.
+ *
+ * This function implemented khci io control khci.
+ *
+ * @param controllerHandle the controller handle.
+ * @param ioctlEvent please reference to enumeration host_busControl_t.
+ * @param ioctlParam the control parameter.
+ *
+ * @retval kStatus_USB_Success io ctrol successfully.
+ * @retval kStatus_USB_InvalidHandle The controllerHandle is a NULL pointer.
+ */
+usb_status_t USB_HostKciIoctl(usb_host_controller_handle controllerHandle, uint32_t ioctlEvent, void *ioctlParam)
+{
+ usb_status_t status = kStatus_USB_Success;
+ usb_host_cancel_param_t *param;
+
+ if (controllerHandle == NULL)
+ {
+ return kStatus_USB_InvalidHandle;
+ }
+
+ switch (ioctlEvent)
+ {
+ case kUSB_HostCancelTransfer:
+ param = (usb_host_cancel_param_t *)ioctlParam;
+ status = _USB_HostKhciCancelPipe(controllerHandle, (usb_host_pipe_t *)param->pipeHandle, param->transfer);
+ break;
+
+ case kUSB_HostBusControl:
+ status = _USB_HostKhciBusControl(controllerHandle, *((uint8_t *)ioctlParam));
+ break;
+
+ case kUSB_HostGetFrameNumber:
+ *((uint32_t *)ioctlParam) = _USB_HostKhciGetFrameCount(controllerHandle);
+ break;
+
+ default:
+ break;
+ }
+ return status;
+}
+#endif /* USB_HOST_CONFIG_KHCI */
diff --git a/usb_1.1.0/host/usb_host_khci.h b/usb_1.1.0/host/usb_host_khci.h
new file mode 100644
index 0000000..38884c7
--- /dev/null
+++ b/usb_1.1.0/host/usb_host_khci.h
@@ -0,0 +1,328 @@
+/*
+ * 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_KHCI_H__
+#define __USB_HOST_KHCI_H__
+
+/*******************************************************************************
+ * KHCI driver private structures, enumerations, macros, functions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#define USB_KHCI_MAX_SPEED_DETECTION_COUNT 3
+
+/* usb khci atom transaction error results */
+#define USB_KHCI_ATOM_TR_PID_ERROR (-1)
+#define USB_KHCI_ATOM_TR_EOF_ERROR (-2)
+#define USB_KHCI_ATOM_TR_CRC_ERROR (-4)
+#define USB_KHCI_ATOM_TR_TO (-16)
+#define USB_KHCI_ATOM_TR_DMA_ERROR (-32)
+#define USB_KHCI_ATOM_TR_BTS_ERROR (-128)
+#define USB_KHCI_ATOM_TR_NAK (-256)
+#define USB_KHCI_ATOM_TR_DATA_ERROR (-512)
+#define USB_KHCI_ATOM_TR_STALL (-1024)
+#define USB_KHCI_ATOM_TR_RESET (-2048)
+#define USB_KHCI_ATOM_TR_BUS_TIMEOUT (-4096)
+#define USB_KHCI_ATOM_TR_INVALID (-8192)
+
+/* KHCI event bits */
+#define USB_KHCI_EVENT_ATTACH 0x01
+#define USB_KHCI_EVENT_RESET 0x02
+#define USB_KHCI_EVENT_TOK_DONE 0x04
+#define USB_KHCI_EVENT_SOF_TOK 0x08
+#define USB_KHCI_EVENT_DETACH 0x10
+#define USB_KHCI_EVENT_MSG 0x20
+#define USB_KHCI_EVENT_ISO_MSG 0x40
+#define USB_KHCI_EVENT_NAK_MSG 0x80
+#define USB_KHCI_EVENT_MASK 0xff
+
+typedef enum _transfer_status
+{
+ kTransfer_Idle = 0,
+ kTransfer_Setup0,
+ kTransfer_Setup1,
+ kTransfer_Setup2,
+ kTransfer_Setup3,
+} transfer_status_t;
+
+typedef enum _khci_intr_type
+{
+ kIntr_UsbRst = 0x01,
+ kIntr_Error = 0x02,
+ kIntr_SofTok = 0x04,
+ kIntr_TokDne = 0x08,
+ kIntr_Sleep = 0x10,
+ kIntr_Resume = 0x20,
+ kIntr_Attach = 0x40,
+ kIntr_Stall = 0x80,
+} khci_intr_type_t;
+
+typedef enum _tr_type
+{
+ kTr_Ctrl = 0,
+ kTr_In,
+ kTr_Out,
+ kTr_OutHndsk,
+ kTr_InHndsk,
+ kTr_Unknown
+} tr_type_t;
+
+/* Transaction type */
+typedef enum _tr_request_type
+{
+ kTr_MsgUnknown = 0, /*Unknown - not used */
+ kTr_MsgSetup, /* Set up transaction */
+ kTr_MsgSend, /* Send transaction */
+ kTr_MsgRecv /* Receive transaction */
+} tr_request_type_t;
+
+typedef enum tr_request_state
+{
+ kTr_MsgIdle = 0, /*Normal transfer */
+ kTr_MsgNak, /* NAK transfer */
+ kTr_BusTimeout,
+} tr_request_state_t;
+
+typedef enum khci_tr_state
+{
+ kKhci_TrGetMsg = 0,
+ kKhci_IsoTrGetMsg,
+ kKhci_TrStartTransmit,
+ kKhci_TrTransmiting,
+ kKhci_TrTransmitDone,
+ kKhci_TrNone
+} khci_tr_state_t;
+
+/* Defines the USB KHCI time out value from USB specification */
+#define USB_TIMEOUT_NODATA (500)
+#define USB_TIMEOUT_TOHOST (5000)
+#define USB_TIMEOUT_TODEVICE (5000)
+#define USB_TIMEOUT_OTHER (10000)
+#define USB_TIMEOUT_DEFAULT (500)
+
+#define NAK_RETRY_TIME (1)
+#define RETRY_TIME (3)
+
+/* Define USB buffer descriptor operator MACRO definitions; This part is not included in header files */
+#define USB_KHCI_BDT_BASE ((uint32_t *)(&bdt[0]))
+#define USB_KHCI_BD_PTR(ep, rxtx, odd) \
+ ((((uint32_t)USB_KHCI_BDT_BASE) & 0xfffffe00U) | ((ep & 0x0fu) << 5) | ((rxtx & 1u) << 4) | ((odd & 1u) << 3))
+
+#define USB_KHCI_BD_CTRL(ep, rxtx, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, rxtx, odd)))
+#define USB_KHCI_BD_CTRL_RX(ep, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, 0, odd)))
+#define USB_KHCI_BD_CTRL_TX(ep, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, 1, odd)))
+
+#define USB_KHCI_BD_ADDR(ep, rxtx, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, rxtx, odd) + 1))
+#define USB_KHCI_BD_ADDR_RX(ep, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, 0, odd) + 1))
+#define USB_KHCI_BD_ADDR_TX(ep, odd) (*((uint32_t *)USB_KHCI_BD_PTR(ep, 1, odd) + 1))
+
+/* Define USB buffer descriptor definitions; This part is not included in header files */
+#define USB_KHCI_BD_BC(n) ((n & 0x3ffu) << 16)
+#define USB_KHCI_BD_OWN 0x80u
+#define USB_KHCI_BD_DATA01(n) ((n & 1u) << 6)
+#define USB_KHCI_BD_DATA0 USB_KHCI_BD_DATA01(0u)
+#define USB_KHCI_BD_DATA1 USB_KHCI_BD_DATA01(1u)
+#define USB_KHCI_BD_KEEP 0x20u
+#define USB_KHCI_BD_NINC 0x10u
+#define USB_KHCI_BD_DTS 0x08u
+#define USB_KHCI_BD_STALL 0x04u
+#define USB_KHCI_BD_PID(n) ((n & 0x0fu) << 2)
+
+#define USB_HostKhciLock() USB_OsaMutexLock(usbHostPointer->khciMutex)
+#define USB_HostKhciUnlock() USB_OsaMutexUnlock(usbHostPointer->khciMutex)
+
+typedef struct _khci_xfer_sts
+{
+ uint32_t rxLen;
+ uint8_t *rxBuf;
+ uint8_t *rxBufOrig;
+ uint8_t isDmaAlign;
+} khci_xfer_sts_t;
+
+/*******************************************************************************
+ * KHCI driver public structures, enumerations, macros, functions
+ ******************************************************************************/
+
+/*!
+ * @addtogroup usb_host_controller_khci
+ * @{
+ */
+
+/*! @brief The value programmed into the threshold register must reserve enough time to ensure the worst case
+ transaction completes. In general, the worst case transaction is an IN token followed by a data packet from the target
+ followed by the response from the host. The actual time required is a function of the maximum packet size on the bus. Set the
+ KHCICFG_THSLD_DELAY to 0x65 to meet the worst case.*/
+
+#define KHCICFG_THSLD_DELAY 0x65
+
+/*! @brief KHCI controller driver instance structure */
+typedef struct _usb_khci_host_state_struct
+{
+ volatile USB_Type *usbRegBase; /*!< The base address of the register */
+ void *hostHandle; /*!< Related host handle*/
+ usb_host_pipe_t *pipeDescriptorBasePointer; /*!< Pipe descriptor bas pointer*/
+ usb_osa_event_handle khciEventPointer; /*!< KHCI event*/
+ usb_osa_mutex_handle khciMutex; /*!< KHCI mutex*/
+ usb_host_transfer_t
+ *periodicListPointer; /*!< KHCI periodic list pointer, which link is an interrupt and an ISO transfer request*/
+ usb_host_transfer_t *asyncListPointer; /*!< KHCI async list pointer, which link controls and bulk transfer request*/
+ khci_xfer_sts_t sXferSts; /*!< KHCI transfer status structure for the DAM ALIGN workaround */
+ uint8_t *khciSwapBufPointer; /*!< KHCI swap buffer pointer for the DAM ALIGN workaround*/
+ volatile uint32_t trState; /*!< KHCI transfer state*/
+ uint8_t asyncListAvtive; /*!< KHCI async list is active*/
+ uint8_t periodicListAvtive; /*!< KHCI periodic list is active*/
+ uint8_t rxBd; /*!< RX buffer descriptor toggle bits*/
+ uint8_t txBd; /*!< TX buffer descriptor toggle bits*/
+ uint8_t deviceSpeed; /*!< Device speed*/
+ int8_t deviceAttached; /*!< Device attach/detach state */
+} usb_khci_host_state_struct_t, *ptr_usb_host_khci_state_struct_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*!
+ * @name USB host KHCI APIs
+ * @{
+ */
+
+/*!
+ * @brief Creates the USB host KHCI instance.
+ *
+ * This function initializes the USB host KHCI controller driver.
+ *
+ * @param controllerId The controller ID of the USB IP. See the enumeration usb_controller_index_t.
+ * @param hostHandle The host level handle.
+ * @param controllerHandle Returns the controller instance handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_AllocFail Allocates memory failed.
+ * @retval kStatus_USB_Error Host mutex create failed, KHCI mutex or KHCI event create failed.
+ * Or, KHCI IP initialize failed.
+ */
+extern usb_status_t USB_HostKhciCreate(uint8_t controllerId,
+ usb_host_handle hostHandle,
+ usb_host_controller_handle *controllerHandle);
+
+/*!
+ * @brief Destroys the USB host KHCI instance.
+ *
+ * This function deinitializes the USB host KHCI controller driver.
+ *
+ * @param controllerHandle The controller handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ */
+extern usb_status_t USB_HostKhciDestory(usb_host_controller_handle controllerHandle);
+
+/*!
+ * @brief Opens the USB host pipe.
+ *
+ * This function opens a pipe according to the pipe_init_ptr parameter.
+ *
+ * @param controllerHandle The controller handle.
+ * @param pipeHandlePointer The pipe handle pointer used to return the pipe handle.
+ * @param pipeInitPointer It is used to initialize the pipe.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ * @retval kStatus_USB_Error There is no idle pipe.
+ *
+ */
+extern usb_status_t USB_HostKhciOpenPipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle *pipeHandlePointer,
+ usb_host_pipe_init_t *pipeInitPointer);
+
+/*!
+ * @brief Closes the USB host pipe.
+ *
+ * This function closes a pipe and frees the related resources.
+ *
+ * @param controllerHandle The controller handle.
+ * @param pipeHandle The closing pipe handle.
+ *
+ * @retval kStatus_USB_Success The host is initialized successfully.
+ */
+extern usb_status_t USB_HostKhciClosePipe(usb_host_controller_handle controllerHandle, usb_host_pipe_handle pipeHandle);
+
+/*!
+ * @brief Sends data to the pipe.
+ *
+ * This function requests to send the transfer to the specified pipe.
+ *
+ * @param controllerHandle The controller handle.
+ * @param pipeHandle The sending pipe handle.
+ * @param transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Send successful.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ */
+extern usb_status_t USB_HostKhciWritePipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Receives data from the pipe.
+ *
+ * This function requests to receive the transfer from the specified pipe.
+ *
+ * @param controllerHandle The controller handle.
+ * @param pipeHandle The receiving pipe handle.
+ * @param transfer The transfer information.
+ *
+ * @retval kStatus_USB_Success Receive successful.
+ * @retval kStatus_USB_LackSwapBuffer There is no swap buffer for KHCI.
+ */
+extern usb_status_t USB_HostKhciReadpipe(usb_host_controller_handle controllerHandle,
+ usb_host_pipe_handle pipeHandle,
+ usb_host_transfer_t *transfer);
+
+/*!
+ * @brief Controls the KHCI.
+ *
+ * This function controls the KHCI.
+ *
+ * @param controllerHandle The controller handle.
+ * @param ioctlEvent See the enumeration host_bus_control_t.
+ * @param ioctlParam The control parameter.
+ *
+ * @retval kStatus_USB_Success Cancel successful.
+ * @retval kStatus_USB_InvalidHandle The controllerHandle is a NULL pointer.
+ */
+extern usb_status_t USB_HostKciIoctl(usb_host_controller_handle controllerHandle,
+ uint32_t ioctlEvent,
+ void *ioctlParam);
+
+/*! @}*/
+#ifdef __cplusplus
+}
+#endif
+/*! @}*/
+#endif /* __USB_HOST_KHCI_H__ */