1108 lines
41 KiB
C
1108 lines
41 KiB
C
/*
|
|
* Copyright 2015-2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016-2021 NXP
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list
|
|
* of conditions and the following disclaimer.
|
|
*
|
|
* 2. 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.
|
|
*
|
|
* 3. Neither the name of copyright holder 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_device_config.h"
|
|
#include "usb.h"
|
|
#include "usb_device.h"
|
|
|
|
#include "usb_device_class.h"
|
|
#include "usb_device_ch9.h"
|
|
#include "usb_device_descriptor.h"
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
#include "usb_hsdcd.h"
|
|
#elif (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
#include "usb_phydcd.h"
|
|
#endif
|
|
|
|
#include "usb_device_composite.h"
|
|
|
|
#include "usb_device_interface_0_cic_vcom.h"
|
|
|
|
#include "usb_device_interface_2_cic_vcom.h"
|
|
|
|
#include "usb_device_interface_4_cic_vcom.h"
|
|
|
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
|
#include "fsl_sysmpu.h"
|
|
#endif
|
|
#if ((defined(FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U)) && \
|
|
((defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
|
|
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))))
|
|
#include "usb_phy.h"
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
#include "fsl_power.h"
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|
|
#if !((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
#include "fsl_mrt.h"
|
|
#endif
|
|
#include "fsl_power.h"
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
#include "fsl_adapter_timer.h"
|
|
#endif
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
#define TIMER_SOURCE_CLOCK CLOCK_GetFreq(kCLOCK_OscClk)
|
|
#endif
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)) && \
|
|
!(defined(FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
#define CHIRP_ISSUE_WORKAROUND_NEEDED 1
|
|
#else
|
|
#define CHIRP_ISSUE_WORKAROUND_NEEDED 0
|
|
#endif
|
|
|
|
|
|
/* USB PHY configuration */
|
|
#ifndef BOARD_USB_PHY_D_CAL
|
|
#define BOARD_USB_PHY_D_CAL (0x0CU)
|
|
#endif
|
|
#ifndef BOARD_USB_PHY_TXCAL45DP
|
|
#define BOARD_USB_PHY_TXCAL45DP (0x06U)
|
|
#endif
|
|
#ifndef BOARD_USB_PHY_TXCAL45DM
|
|
#define BOARD_USB_PHY_TXCAL45DM (0x06U)
|
|
#endif
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
|
|
void USB_DeviceIsrEnable(void);
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
void USB_DeviceTaskFn(void *deviceHandle);
|
|
#endif
|
|
|
|
static void USB_DeviceClockInit(void);
|
|
|
|
#if CHIRP_ISSUE_WORKAROUND_NEEDED
|
|
void USB_DeviceHsPhyChirpIssueWorkaround(void);
|
|
void USB_DeviceDisconnected(void);
|
|
#endif
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
|
|
#elif (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
extern void HW_TimerControl(uint8_t enable);
|
|
#endif
|
|
|
|
|
|
|
|
static usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param);
|
|
static usb_status_t USB_UpdateInterfaceSetting(uint8_t interface, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface0CicVcomInit(usb_device_composite_struct_t *deviceComposite);
|
|
extern usb_status_t USB_DeviceInterface0CicVcomCallback(class_handle_t handle, uint32_t event, void *param);
|
|
extern usb_status_t USB_DeviceInterface0CicVcomSetConfiguration(class_handle_t handle, uint8_t configuration_index);
|
|
extern usb_status_t USB_DeviceInterface0CicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface1DicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface2CicVcomInit(usb_device_composite_struct_t *deviceComposite);
|
|
extern usb_status_t USB_DeviceInterface2CicVcomCallback(class_handle_t handle, uint32_t event, void *param);
|
|
extern usb_status_t USB_DeviceInterface2CicVcomSetConfiguration(class_handle_t handle, uint8_t configuration_index);
|
|
extern usb_status_t USB_DeviceInterface2CicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface3DicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface4CicVcomInit(usb_device_composite_struct_t *deviceComposite);
|
|
extern usb_status_t USB_DeviceInterface4CicVcomCallback(class_handle_t handle, uint32_t event, void *param);
|
|
extern usb_status_t USB_DeviceInterface4CicVcomSetConfiguration(class_handle_t handle, uint8_t configuration_index);
|
|
extern usb_status_t USB_DeviceInterface4CicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
extern usb_status_t USB_DeviceInterface5DicVcomSetInterface(class_handle_t handle, uint8_t alternateSetting);
|
|
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
uint32_t g_halTimerHandle[(HAL_TIMER_HANDLE_SIZE + 3) / 4];
|
|
#endif
|
|
|
|
#if CHIRP_ISSUE_WORKAROUND_NEEDED
|
|
volatile uint32_t hwTick;
|
|
uint32_t timerInterval;
|
|
uint32_t isConnectedToFsHost = 0U;
|
|
uint32_t isConnectedToHsHost = 0U;
|
|
#endif
|
|
|
|
usb_device_composite_struct_t g_UsbDeviceComposite;
|
|
|
|
extern usb_device_class_struct_t g_UsbDeviceInterface0CicVcomConfig;
|
|
extern usb_device_class_struct_t g_UsbDeviceInterface2CicVcomConfig;
|
|
extern usb_device_class_struct_t g_UsbDeviceInterface4CicVcomConfig;
|
|
|
|
/* Set class configurations. */
|
|
usb_device_class_config_struct_t g_CompositeClassConfig[USB_COMPOSITE_INTERFACE_COUNT] = {
|
|
{
|
|
USB_DeviceInterface0CicVcomCallback, (class_handle_t)NULL, &g_UsbDeviceInterface0CicVcomConfig,
|
|
},
|
|
{
|
|
(usb_device_class_callback_t)NULL, (class_handle_t)NULL, NULL,
|
|
},
|
|
{
|
|
USB_DeviceInterface2CicVcomCallback, (class_handle_t)NULL, &g_UsbDeviceInterface2CicVcomConfig,
|
|
},
|
|
{
|
|
(usb_device_class_callback_t)NULL, (class_handle_t)NULL, NULL,
|
|
},
|
|
{
|
|
USB_DeviceInterface4CicVcomCallback, (class_handle_t)NULL, &g_UsbDeviceInterface4CicVcomConfig,
|
|
},
|
|
{
|
|
(usb_device_class_callback_t)NULL, (class_handle_t)NULL, NULL,
|
|
},
|
|
};
|
|
|
|
/* Set class configuration list. */
|
|
usb_device_class_config_list_struct_t g_UsbDeviceCompositeConfigList = {
|
|
g_CompositeClassConfig, USB_DeviceCallback, USB_COMPOSITE_INTERFACE_COUNT,
|
|
};
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
void HW_TimerCallback(void *param)
|
|
{
|
|
g_UsbDeviceComposite.hwTick++;
|
|
USB_DeviceUpdateHwTick(g_UsbDeviceComposite.deviceHandle, g_UsbDeviceComposite.hwTick);
|
|
}
|
|
|
|
void HW_TimerInit(void)
|
|
{
|
|
hal_timer_config_t halTimerConfig;
|
|
halTimerConfig.timeout = 1000;
|
|
halTimerConfig.srcClock_Hz = TIMER_SOURCE_CLOCK;
|
|
halTimerConfig.instance = 0U;
|
|
hal_timer_handle_t halTimerHandle = &g_halTimerHandle[0];
|
|
HAL_TimerInit(halTimerHandle, &halTimerConfig);
|
|
HAL_TimerInstallCallback(halTimerHandle, HW_TimerCallback, NULL);
|
|
}
|
|
void HW_TimerControl(uint8_t enable)
|
|
{
|
|
if (enable)
|
|
{
|
|
HAL_TimerEnable(g_halTimerHandle);
|
|
}
|
|
else
|
|
{
|
|
HAL_TimerDisable(g_halTimerHandle);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
usb_power_status_t getPowerStatus(void)
|
|
{
|
|
return g_UsbDeviceComposite.suspend;
|
|
}
|
|
|
|
void USB_LowpowerModeInit(void)
|
|
{
|
|
#if (defined(FSL_FEATURE_SIM_OPT_HAS_USB_PHY) && (FSL_FEATURE_SIM_OPT_HAS_USB_PHY > 0))
|
|
SIM->SOPT2 |= SIM_SOPT2_USBSLSRC_MASK;
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* Switch to low power mode
|
|
*/
|
|
static void EnterDeepSleep(void)
|
|
{
|
|
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
|
|
__asm("WFI");
|
|
}
|
|
/*
|
|
* Enter the LowPower mode.
|
|
*/
|
|
void APP_LowPower_EnterLowPower(void)
|
|
{
|
|
CLOCK_SetMode(kCLOCK_ModeStop);
|
|
EnterDeepSleep();
|
|
}
|
|
|
|
uint8_t USB_EnterLowpowerMode(void)
|
|
{
|
|
APP_LowPower_EnterLowPower();
|
|
return 0;
|
|
}
|
|
|
|
void USB_WaitForPllLock(void)
|
|
{
|
|
|
|
}
|
|
|
|
void USB_PostLowpowerMode(void)
|
|
{
|
|
USB_WaitForPllLock();
|
|
}
|
|
|
|
void USB_ControllerSuspended(void)
|
|
{
|
|
}
|
|
|
|
void USB_PowerPreSwitchHook(void)
|
|
{
|
|
}
|
|
|
|
void USB_PowerPostSwitchHook(void)
|
|
{
|
|
USB_WaitForPllLock();
|
|
USB_PostLowpowerMode();
|
|
}
|
|
|
|
void USB_DeviceSuspendResumeTask(void)
|
|
{
|
|
if (g_UsbDeviceComposite.isResume)
|
|
{
|
|
g_UsbDeviceComposite.isResume = 0U;
|
|
if (kStatus_Idle != g_UsbDeviceComposite.suspend)
|
|
{
|
|
g_UsbDeviceComposite.suspend = kStatus_Resumed;
|
|
}
|
|
}
|
|
|
|
switch (g_UsbDeviceComposite.suspend)
|
|
{
|
|
case kStatus_Idle:
|
|
break;
|
|
case kStatus_StartSuspend:
|
|
g_UsbDeviceComposite.suspend = kStatus_Suspending;
|
|
break;
|
|
case kStatus_Suspending:
|
|
usb_echo("USB device suspended.\r\n");
|
|
if (g_UsbDeviceComposite.remoteWakeup)
|
|
{
|
|
usb_echo("Please Press wakeup switch to remote wakeup the host.\r\n");
|
|
}
|
|
g_UsbDeviceComposite.suspend = kStatus_Suspended;
|
|
break;
|
|
case kStatus_Suspended:
|
|
USB_PowerPreSwitchHook();
|
|
USB_DeviceSetStatus(g_UsbDeviceComposite.deviceHandle, kUSB_DeviceStatusBusSuspend, NULL);
|
|
if (kStatus_Success != USB_EnterLowpowerMode())
|
|
{
|
|
g_UsbDeviceComposite.selfWakeup = 1U;
|
|
USB_PowerPostSwitchHook();
|
|
usb_echo("Enter VLPS mode failed!\r\n");
|
|
}
|
|
else
|
|
{
|
|
USB_PowerPostSwitchHook();
|
|
}
|
|
|
|
if (g_UsbDeviceComposite.attach)
|
|
{
|
|
g_UsbDeviceComposite.suspend = kStatus_StartResume;
|
|
}
|
|
else
|
|
{
|
|
g_UsbDeviceComposite.suspend = kStatus_Idle;
|
|
}
|
|
break;
|
|
case kStatus_StartResume:
|
|
if (g_UsbDeviceComposite.selfWakeup)
|
|
{
|
|
g_UsbDeviceComposite.selfWakeup = 0U;
|
|
if (g_UsbDeviceComposite.remoteWakeup)
|
|
{
|
|
if (kStatus_USB_Success ==
|
|
USB_DeviceSetStatus(g_UsbDeviceComposite.deviceHandle, kUSB_DeviceStatusBusResume, NULL))
|
|
{
|
|
usb_echo("Remote wakeup the host.\r\n");
|
|
g_UsbDeviceComposite.suspend = kStatus_Resuming;
|
|
}
|
|
else
|
|
{
|
|
usb_echo("Send resume signal failed.\r\n");
|
|
g_UsbDeviceComposite.suspend = kStatus_StartResume;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_UsbDeviceComposite.suspend = kStatus_Resuming;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
g_UsbDeviceComposite.suspend = kStatus_Resumed;
|
|
}
|
|
break;
|
|
case kStatus_Resuming:
|
|
break;
|
|
case kStatus_Resumed:
|
|
usb_echo("USB device resumed.\r\n");
|
|
g_UsbDeviceComposite.suspend = kStatus_Idle;
|
|
break;
|
|
default:
|
|
g_UsbDeviceComposite.suspend = kStatus_Idle;
|
|
break;
|
|
}
|
|
}
|
|
#if CHIRP_ISSUE_WORKAROUND_NEEDED
|
|
/*!
|
|
* @brief Initialization on MRT timer
|
|
*
|
|
* @param uint8_t Instance of timer.
|
|
* @interval uint32_t Interrupt interval.
|
|
*
|
|
*/
|
|
void USB_TimerInit(uint8_t instance, uint32_t interval)
|
|
{
|
|
MRT_Type *instanceList[] = MRT_BASE_PTRS;
|
|
IRQn_Type instanceIrq[] = MRT_IRQS;
|
|
/* Structure of initialize MRT */
|
|
mrt_config_t mrtConfig;
|
|
/* mrtConfig.enableMultiTask = false; */
|
|
MRT_GetDefaultConfig(&mrtConfig);
|
|
/* Init mrt module */
|
|
MRT_Init(instanceList[instance], &mrtConfig);
|
|
/* Setup Channel 0 to be repeated */
|
|
MRT_SetupChannelMode(instanceList[instance], kMRT_Channel_0, kMRT_RepeatMode);
|
|
/* Enable timer interrupts for channel 0 */
|
|
MRT_EnableInterrupts(instanceList[instance], kMRT_Channel_0, kMRT_TimerInterruptEnable);
|
|
timerInterval = interval;
|
|
/* Enable at the NVIC */
|
|
EnableIRQ(instanceIrq[instance]);
|
|
}
|
|
|
|
/*!
|
|
* @brief Function used to start/stop the MRT timer
|
|
*
|
|
* @param uint8_t MRT timer instance.
|
|
* @param uint8_t Set to 0 to disable the timer. Other values enable the timer.
|
|
*/
|
|
void USB_TimerInt(uint8_t instance, uint8_t enable)
|
|
{
|
|
MRT_Type *instanceList[] = MRT_BASE_PTRS;
|
|
uint32_t mrt_clock;
|
|
mrt_clock = CLOCK_GetFreq(kCLOCK_BusClk);
|
|
if (enable)
|
|
{
|
|
/* Start channel 0 */
|
|
MRT_StartTimer(instanceList[instance], kMRT_Channel_0, USEC_TO_COUNT(timerInterval, mrt_clock));
|
|
}
|
|
else
|
|
{
|
|
/* Stop channel 0 */
|
|
MRT_StopTimer(instanceList[instance], kMRT_Channel_0);
|
|
/* Clear interrupt flag.*/
|
|
MRT_ClearStatusFlags(instanceList[instance], kMRT_Channel_0, kMRT_TimerInterruptFlag);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief MRT0 interrupt service routine
|
|
*/
|
|
void MRT0_IRQHandler(void)
|
|
{
|
|
/* Clear interrupt flag.*/
|
|
MRT_ClearStatusFlags(MRT0, kMRT_Channel_0, kMRT_TimerInterruptFlag);
|
|
if (hwTick)
|
|
{
|
|
hwTick--;
|
|
if (!hwTick)
|
|
{
|
|
USB_TimerInt(0, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
USB_TimerInt(0, 0);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
* @brief Clears device connected flag for chirp issue
|
|
*/
|
|
void USB_DeviceDisconnected(void)
|
|
{
|
|
isConnectedToFsHost = 0U;
|
|
}
|
|
|
|
/*!
|
|
* @brief Chirp issue workaround
|
|
*
|
|
* This is a work-around to fix the HS device Chirping issue.
|
|
* The device (IP3511HS controller) will sometimes not work when the cable
|
|
* is attached first time after a Power-on Reset.
|
|
*/
|
|
void USB_DeviceHsPhyChirpIssueWorkaround(void)
|
|
{
|
|
uint32_t startFrame = USBHSD->INFO & USBHSD_INFO_FRAME_NR_MASK;
|
|
uint32_t currentFrame;
|
|
uint32_t isConnectedToFsHostFlag = 0U;
|
|
|
|
if ((!isConnectedToHsHost) && (!isConnectedToFsHost))
|
|
{
|
|
if (((USBHSD->DEVCMDSTAT & USBHSD_DEVCMDSTAT_Speed_MASK) >> USBHSD_DEVCMDSTAT_Speed_SHIFT) == 0x01U)
|
|
{
|
|
USBHSD->DEVCMDSTAT = (USBHSD->DEVCMDSTAT & (~(0x0F000000U | USBHSD_DEVCMDSTAT_PHY_TEST_MODE_MASK))) |
|
|
USBHSD_DEVCMDSTAT_PHY_TEST_MODE(0x05U);
|
|
hwTick = 100;
|
|
USB_TimerInt(0, 1);
|
|
|
|
while (hwTick)
|
|
{
|
|
}
|
|
|
|
currentFrame = USBHSD->INFO & USBHSD_INFO_FRAME_NR_MASK;
|
|
|
|
if (currentFrame != startFrame)
|
|
{
|
|
isConnectedToHsHost = 1U;
|
|
}
|
|
else
|
|
{
|
|
hwTick = 1;
|
|
USB_TimerInt(0, 1);
|
|
|
|
while (hwTick)
|
|
{
|
|
}
|
|
|
|
currentFrame = USBHSD->INFO & USBHSD_INFO_FRAME_NR_MASK;
|
|
|
|
if (currentFrame != startFrame)
|
|
{
|
|
isConnectedToHsHost = 1U;
|
|
}
|
|
else
|
|
{
|
|
isConnectedToFsHostFlag = 1U;
|
|
}
|
|
}
|
|
|
|
USBHSD->DEVCMDSTAT = (USBHSD->DEVCMDSTAT & (~(0x0F000000U | USBHSD_DEVCMDSTAT_PHY_TEST_MODE_MASK)));
|
|
USBHSD->DEVCMDSTAT = (USBHSD->DEVCMDSTAT & (~(0x0F000000U | USBHSD_DEVCMDSTAT_DCON_MASK)));
|
|
hwTick = 510;
|
|
USB_TimerInt(0, 1);
|
|
|
|
while (hwTick)
|
|
{
|
|
}
|
|
|
|
USBHSD->DEVCMDSTAT = (USBHSD->DEVCMDSTAT & (~(0x0F000000U))) | USB_DEVCMDSTAT_DCON_C_MASK;
|
|
USBHSD->DEVCMDSTAT =
|
|
(USBHSD->DEVCMDSTAT & (~(0x0F000000U))) | USBHSD_DEVCMDSTAT_DCON_MASK | USB_DEVCMDSTAT_DRES_C_MASK;
|
|
|
|
if (isConnectedToFsHostFlag)
|
|
{
|
|
isConnectedToFsHost = 1U;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* @brief USB Interrupt service routine.
|
|
*
|
|
* This function serves as the USB interrupt service routine.
|
|
*
|
|
* @return None.
|
|
*/
|
|
void USB_OTG1_IRQHandler(void)
|
|
{
|
|
USB_DeviceEhciIsrFunction(g_UsbDeviceComposite.deviceHandle);
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)) || (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U))
|
|
/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
|
|
exception return operation might vector to incorrect interrupt */
|
|
__DSB();
|
|
#endif
|
|
}
|
|
|
|
/*!
|
|
* @brief Initializes USB specific setting that was not set by the Clocks tool.
|
|
*/
|
|
static void USB_DeviceClockInit(void)
|
|
{
|
|
usb_phy_config_struct_t phyConfig = {
|
|
BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM,
|
|
};
|
|
uint32_t notUsed = 0;
|
|
|
|
if (USB_DEVICE_CONTROLLER_ID == kUSB_ControllerEhci0)
|
|
{
|
|
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
|
|
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
|
|
}
|
|
else
|
|
{
|
|
CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
|
|
CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
|
|
}
|
|
|
|
USB_EhciPhyInit(USB_DEVICE_CONTROLLER_ID, notUsed, &phyConfig);
|
|
}
|
|
|
|
/*!
|
|
* @brief Enables interrupt service routines for device.
|
|
*/
|
|
void USB_DeviceIsrEnable(void)
|
|
{
|
|
uint8_t irqNumber;
|
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
|
|
uint8_t usbDeviceKhciIrq[] = USB_IRQS;
|
|
irqNumber = usbDeviceKhciIrq[USB_DEVICE_CONTROLLER_ID - kUSB_ControllerKhci0];
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
|
uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
|
|
irqNumber = usbDeviceEhciIrq[USB_DEVICE_CONTROLLER_ID - kUSB_ControllerEhci0];
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
|
|
uint8_t usbDeviceIP3511Irq[] = USB_IRQS;
|
|
irqNumber = usbDeviceIP3511Irq[USB_DEVICE_CONTROLLER_ID - kUSB_ControllerLpcIp3511Fs0];
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
|
uint8_t usbDeviceIP3511Irq[] = USBHSD_IRQS;
|
|
irqNumber = usbDeviceIP3511Irq[USB_DEVICE_CONTROLLER_ID - kUSB_ControllerLpcIp3511Hs0];
|
|
#endif
|
|
/* Install isr, set priority, and enable IRQ. */
|
|
#if defined(__GIC_PRIO_BITS)
|
|
GIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
|
|
#else
|
|
NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
|
|
#endif
|
|
EnableIRQ((IRQn_Type)irqNumber);
|
|
}
|
|
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
/*!
|
|
* @brief USB device task. When USB device does not use interrupt service routines, this function should be called periodically.
|
|
*
|
|
* @param *deviceHandle Pointer to device handle.
|
|
*/
|
|
void USB_DeviceTaskFn(void *deviceHandle)
|
|
{
|
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U)
|
|
USB_DeviceKhciTaskFunction(deviceHandle);
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)
|
|
USB_DeviceEhciTaskFunction(deviceHandle);
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
|
|
USB_DeviceLpcIp3511TaskFunction(deviceHandle);
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
|
USB_DeviceLpcIp3511TaskFunction(deviceHandle);
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* @brief Standard device callback function.
|
|
*
|
|
* This function handle the USB standard event. For more information, please refer to usb spec chapter 9.
|
|
* @param handle The USB device handle.
|
|
* @param event The USB device event type.
|
|
* @param *param The parameter of the device specific request.
|
|
* @return usb_status_t Returns status of operation.
|
|
*/
|
|
static usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
|
|
{
|
|
usb_status_t error = kStatus_USB_Error;
|
|
uint16_t *temp16 = (uint16_t *)param;
|
|
uint8_t *temp8 = (uint8_t *)param;
|
|
uint8_t count = 0U;
|
|
|
|
switch (event)
|
|
{
|
|
case kUSB_DeviceEventBusReset:
|
|
/* USB bus reset signal detected */
|
|
for (count = 0U; count < USB_COMPOSITE_INTERFACE_COUNT; count++)
|
|
{
|
|
g_UsbDeviceComposite.currentInterfaceAlternateSetting[count] = 0U;
|
|
}
|
|
g_UsbDeviceComposite.attach = 0U;
|
|
g_UsbDeviceComposite.currentConfiguration = 0U;
|
|
error = kStatus_USB_Success;
|
|
#if CHIRP_ISSUE_WORKAROUND_NEEDED
|
|
/* The work-around is used to fix the HS device Chirping issue.
|
|
* Please refer to the implementation for the detail information.
|
|
*/
|
|
USB_DeviceHsPhyChirpIssueWorkaround();
|
|
#endif
|
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) || \
|
|
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|
|
/* Get USB speed to configure the device, including max packet size and interval of the endpoints. */
|
|
if (kStatus_USB_Success == USB_DeviceClassGetSpeed(USB_DEVICE_CONTROLLER_ID, &g_UsbDeviceComposite.speed))
|
|
{
|
|
USB_DeviceSetSpeed(handle, g_UsbDeviceComposite.speed);
|
|
}
|
|
#endif
|
|
break;
|
|
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
|
|
case kUSB_DeviceEventAttach:
|
|
g_UsbDeviceComposite.connectStateChanged = 1U;
|
|
g_UsbDeviceComposite.connectState = 1U;
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))) || \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)))
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionInit;
|
|
|
|
#else
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)) || \
|
|
(defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
#else
|
|
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
|
|
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
#endif
|
|
break;
|
|
case kUSB_DeviceEventDetach:
|
|
g_UsbDeviceComposite.connectStateChanged = 1U;
|
|
g_UsbDeviceComposite.connectState = 0U;
|
|
g_UsbDeviceComposite.attach = 0U;
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))) || \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)))
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionInit;
|
|
#else
|
|
g_UsbDeviceComposite.attach = 0;
|
|
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
|
|
(defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0U))
|
|
USB_DeviceStop(g_UsbDeviceComposite.deviceHandle);
|
|
#else
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|
|
USB_DeviceDisconnected();
|
|
#endif
|
|
#endif
|
|
#endif
|
|
break;
|
|
#endif
|
|
case kUSB_DeviceEventSetConfiguration:
|
|
if (0 == temp8)
|
|
{
|
|
g_UsbDeviceComposite.attach = 0U;
|
|
g_UsbDeviceComposite.currentConfiguration = 0U;
|
|
/* The device is detached - the zero configuration is set. */
|
|
USB_DeviceInterface0CicVcomSetConfiguration(g_UsbDeviceComposite.interface0CicVcomHandle, *temp8);
|
|
/* The device is detached - the zero configuration is set. */
|
|
USB_DeviceInterface2CicVcomSetConfiguration(g_UsbDeviceComposite.interface2CicVcomHandle, *temp8);
|
|
/* The device is detached - the zero configuration is set. */
|
|
USB_DeviceInterface4CicVcomSetConfiguration(g_UsbDeviceComposite.interface4CicVcomHandle, *temp8);
|
|
}
|
|
else if (USB_COMPOSITE_CONFIGURATION_INDEX == (*temp8))
|
|
{
|
|
/* Set device configuration request */
|
|
g_UsbDeviceComposite.attach = 1U;
|
|
g_UsbDeviceComposite.currentConfiguration = *temp8;
|
|
USB_DeviceInterface0CicVcomSetConfiguration(g_UsbDeviceComposite.interface0CicVcomHandle, *temp8);
|
|
USB_DeviceInterface2CicVcomSetConfiguration(g_UsbDeviceComposite.interface2CicVcomHandle, *temp8);
|
|
USB_DeviceInterface4CicVcomSetConfiguration(g_UsbDeviceComposite.interface4CicVcomHandle, *temp8);
|
|
error = kStatus_USB_Success;
|
|
}
|
|
else
|
|
{
|
|
error = kStatus_USB_InvalidRequest;
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventSetInterface:
|
|
if (g_UsbDeviceComposite.attach)
|
|
{
|
|
/* Set device interface request */
|
|
uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U);
|
|
uint8_t alternateSetting = (uint8_t)(*temp16 & 0x00FFU);
|
|
|
|
if (interface < USB_COMPOSITE_INTERFACE_COUNT)
|
|
{
|
|
error = USB_UpdateInterfaceSetting(interface, alternateSetting);
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetConfiguration:
|
|
if (param)
|
|
{
|
|
/* Get current configuration request */
|
|
*temp8 = g_UsbDeviceComposite.currentConfiguration;
|
|
error = kStatus_USB_Success;
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetInterface:
|
|
if (param)
|
|
{
|
|
/* Get current alternate setting of the interface request */
|
|
uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U);
|
|
if (interface < USB_COMPOSITE_INTERFACE_COUNT)
|
|
{
|
|
*temp16 = (*temp16 & 0xFF00U) | g_UsbDeviceComposite.currentInterfaceAlternateSetting[interface];
|
|
error = kStatus_USB_Success;
|
|
}
|
|
else
|
|
{
|
|
error = kStatus_USB_InvalidRequest;
|
|
}
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetDeviceDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get device descriptor request */
|
|
error = USB_DeviceGetDeviceDescriptor(handle, (usb_device_get_device_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetConfigurationDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get device configuration descriptor request */
|
|
error = USB_DeviceGetConfigurationDescriptor(handle,
|
|
(usb_device_get_configuration_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetStringDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get device string descriptor request */
|
|
error = USB_DeviceGetStringDescriptor(handle, (usb_device_get_string_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
#if (USB_DEVICE_CONFIG_HID > 0U)
|
|
case kUSB_DeviceEventGetHidDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get hid descriptor request */
|
|
error = USB_DeviceGetHidDescriptor(handle, (usb_device_get_hid_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetHidReportDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get hid report descriptor request */
|
|
error =
|
|
USB_DeviceGetHidReportDescriptor(handle, (usb_device_get_hid_report_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventGetHidPhysicalDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get hid physical descriptor request */
|
|
error = USB_DeviceGetHidPhysicalDescriptor(handle,
|
|
(usb_device_get_hid_physical_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
#endif /* USB_DEVICE_CONFIG_HID */
|
|
#if (defined(USB_DEVICE_CONFIG_CV_TEST) && (USB_DEVICE_CONFIG_CV_TEST > 0U))
|
|
case kUSB_DeviceEventGetDeviceQualifierDescriptor:
|
|
if (param)
|
|
{
|
|
/* Get Qualifier descriptor request */
|
|
error = USB_DeviceGetDeviceQualifierDescriptor(
|
|
handle, (usb_device_get_device_qualifier_descriptor_struct_t *)param);
|
|
}
|
|
break;
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))) || \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)))
|
|
case kUSB_DeviceEventDcdDetectionfinished:
|
|
/*temp pointer point to detection result*/
|
|
if (param)
|
|
{
|
|
if (kUSB_DcdSDP == *temp8)
|
|
{
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionSDP;
|
|
}
|
|
else if (kUSB_DcdCDP == *temp8)
|
|
{
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionCDP;
|
|
}
|
|
else if (kUSB_DcdDCP == *temp8)
|
|
{
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionDCP;
|
|
}
|
|
else if (kUSB_DcdTimeOut == *temp8)
|
|
{
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionTimeOut;
|
|
}
|
|
else if (kUSB_DcdError == *temp8)
|
|
{
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionError;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/*!
|
|
* @brief Select interface and call setInterface callback.
|
|
*
|
|
* @param interface Number of interface to be set to.
|
|
* @param alternateSetting Alternate setting to be used.
|
|
* @return usb_status_t Returns status of operation.
|
|
*/
|
|
usb_status_t USB_UpdateInterfaceSetting(uint8_t interface, uint8_t alternateSetting)
|
|
{
|
|
usb_status_t ret = kStatus_USB_Error;
|
|
|
|
/* select appropriate interface to be updated*/
|
|
switch (interface)
|
|
{
|
|
|
|
case USB_INTERFACE_0_CIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface0CicVcomSetInterface(g_UsbDeviceComposite.interface0CicVcomHandle, alternateSetting);
|
|
break;
|
|
case USB_INTERFACE_1_DIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface1DicVcomSetInterface(g_UsbDeviceComposite.interface0CicVcomHandle, alternateSetting);
|
|
break;
|
|
|
|
case USB_INTERFACE_2_CIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface2CicVcomSetInterface(g_UsbDeviceComposite.interface2CicVcomHandle, alternateSetting);
|
|
break;
|
|
case USB_INTERFACE_3_DIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface3DicVcomSetInterface(g_UsbDeviceComposite.interface2CicVcomHandle, alternateSetting);
|
|
break;
|
|
|
|
case USB_INTERFACE_4_CIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface4CicVcomSetInterface(g_UsbDeviceComposite.interface4CicVcomHandle, alternateSetting);
|
|
break;
|
|
case USB_INTERFACE_5_DIC_VCOM_INDEX:
|
|
ret = USB_DeviceInterface5DicVcomSetInterface(g_UsbDeviceComposite.interface4CicVcomHandle, alternateSetting);
|
|
break;
|
|
}
|
|
|
|
if (ret == kStatus_USB_Success)
|
|
{
|
|
//interface setting was set
|
|
g_UsbDeviceComposite.currentInterfaceAlternateSetting[interface] = alternateSetting;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/*!
|
|
* @brief Completely initializes USB device.
|
|
*
|
|
* This function calls other USB device functions and directly initializes following: USB specific clocks, g_UsbDeviceComposite values, USB stack, class drivers and device isr.
|
|
*
|
|
* @return A USB error code or kStatus_USB_Success.
|
|
*/
|
|
usb_status_t USB_DeviceApplicationInit(void)
|
|
{
|
|
usb_status_t status;
|
|
|
|
USB_DeviceClockInit();
|
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
|
SYSMPU_Enable(SYSMPU, 0);
|
|
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
|
|
|
|
g_UsbDeviceComposite.speed = USB_SPEED_FULL;
|
|
g_UsbDeviceComposite.attach = 0U;
|
|
g_UsbDeviceComposite.interface0CicVcomHandle = (class_handle_t)NULL;
|
|
g_UsbDeviceComposite.interface2CicVcomHandle = (class_handle_t)NULL;
|
|
g_UsbDeviceComposite.interface4CicVcomHandle = (class_handle_t)NULL;
|
|
g_UsbDeviceComposite.deviceHandle = NULL;
|
|
|
|
/* Initialize the usb stack and class drivers. */
|
|
status = USB_DeviceClassInit(USB_DEVICE_CONTROLLER_ID, &g_UsbDeviceCompositeConfigList, &g_UsbDeviceComposite.deviceHandle);
|
|
|
|
if (kStatus_USB_Success != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* Get the class handle. */
|
|
g_UsbDeviceComposite.interface0CicVcomHandle = g_UsbDeviceCompositeConfigList.config[0].classHandle;
|
|
USB_DeviceInterface0CicVcomInit(&g_UsbDeviceComposite);
|
|
g_UsbDeviceComposite.interface2CicVcomHandle = g_UsbDeviceCompositeConfigList.config[2].classHandle;
|
|
USB_DeviceInterface2CicVcomInit(&g_UsbDeviceComposite);
|
|
g_UsbDeviceComposite.interface4CicVcomHandle = g_UsbDeviceCompositeConfigList.config[4].classHandle;
|
|
USB_DeviceInterface4CicVcomInit(&g_UsbDeviceComposite);
|
|
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))) || \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)))
|
|
g_UsbDeviceComposite.dcdDectionStatus = kUSB_DeviceDCDDectionInit;
|
|
#endif
|
|
|
|
USB_DeviceIsrEnable();
|
|
|
|
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
|
|
/*USB_DeviceRun could not be called here to avoid DP/DM confliction between DCD function and USB function in case
|
|
DCD is enabled. Instead, USB_DeviceRun should be called after the DCD is finished immediately*/
|
|
#if (defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U))
|
|
/* Start USB device HID mouse */
|
|
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
|
|
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
#else
|
|
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
|
|
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
return status;
|
|
}
|
|
|
|
/*!
|
|
* @brief USB device charger task function.
|
|
*
|
|
* This function handles the USB device charger events.
|
|
* @param usbDeviceCompositeDcd Device charger configuration.
|
|
* @return None.
|
|
*/
|
|
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
|
|
void USB_DeviceChargerTask(usb_device_composite_struct_t *usbDeviceCompositeDcd)
|
|
{
|
|
if (usbDeviceCompositeDcd->connectStateChanged)
|
|
{
|
|
usbDeviceCompositeDcd->connectStateChanged = 0;
|
|
if (g_UsbDeviceComposite.connectState)
|
|
{
|
|
/*user need call USB_DeviceRun here to usb function run if dcd function is disabled*/
|
|
/*USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);*/
|
|
usb_echo("USB device attached.\r\n");
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
|
|
#elif (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
HW_TimerControl(1U);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U))
|
|
/*USB_DeviceStop should be called here to avoid DP/DM confliction between DCD function and USB function in
|
|
* case next time DCD dection. */
|
|
USB_DeviceStop(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))
|
|
|
|
#elif (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U))
|
|
HW_TimerControl(0U);
|
|
#endif
|
|
usb_echo("USB device detached.\r\n");
|
|
}
|
|
}
|
|
#if (defined(USB_DEVICE_CONFIG_CHARGER_DETECT) && (USB_DEVICE_CONFIG_CHARGER_DETECT > 0U)) && \
|
|
(((defined(FSL_FEATURE_SOC_USBHSDCD_COUNT) && (FSL_FEATURE_SOC_USBHSDCD_COUNT > 0U))) || \
|
|
(defined(FSL_FEATURE_SOC_USB_ANALOG_COUNT) && (FSL_FEATURE_SOC_USB_ANALOG_COUNT > 0U)))
|
|
if ((kUSB_DeviceDCDDectionInit != usbDeviceCompositeDcd->dcdDectionStatus) &&
|
|
(kUSB_DeviceDCDDectionFinished != usbDeviceCompositeDcd->dcdDectionStatus))
|
|
{
|
|
switch (usbDeviceCompositeDcd->dcdDectionStatus)
|
|
{
|
|
case kUSB_DeviceDCDDectionSDP:
|
|
{
|
|
usb_echo("SDP(standard downstream port) is detected.\r\n");
|
|
/* Start USB device HID mouse */
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
}
|
|
break;
|
|
case kUSB_DeviceDCDDectionDCP:
|
|
{
|
|
usb_echo("DCP (dedicated charging port) is detected.\r\n");
|
|
#if (defined(FSL_FEATURE_USBPHY_HAS_DCD_ANALOG) && (FSL_FEATURE_USBPHY_HAS_DCD_ANALOG > 0U))
|
|
/*
|
|
* This is a work-around to fix the DCP device detach event missing issue.
|
|
* The device (IP3511HS controller) VBUSDEBOUNCED bit is not updated on time before softeware read this
|
|
* bit, so when DCP is detached from usb port, softeware can't detect DCP disconnection.
|
|
*/
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
}
|
|
break;
|
|
case kUSB_DeviceDCDDectionCDP:
|
|
{
|
|
usb_echo("CDP(charging downstream port) is detected.\r\n");
|
|
/* Start USB device HID mouse */
|
|
USB_DeviceRun(g_UsbDeviceComposite.deviceHandle);
|
|
}
|
|
break;
|
|
case kUSB_DeviceDCDDectionTimeOut:
|
|
{
|
|
usb_echo("Timeout error.\r\n");
|
|
}
|
|
break;
|
|
case kUSB_DeviceDCDDectionError:
|
|
{
|
|
usb_echo("Detect error.\r\n");
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
usbDeviceCompositeDcd->dcdDectionStatus = kUSB_DeviceDCDDectionFinished;
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
/*!
|
|
* @brief USB device tasks function.
|
|
*
|
|
* This function runs the tasks for USB device.
|
|
*
|
|
* @return None.
|
|
*/
|
|
void USB_DeviceTasks(void)
|
|
{
|
|
|
|
USB_DeviceInterface0CicVcomTask();
|
|
|
|
USB_DeviceInterface2CicVcomTask();
|
|
|
|
USB_DeviceInterface4CicVcomTask();
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
USB_DeviceTaskFn(g_UsbDeviceComposite.deviceHandle);
|
|
#endif
|
|
#if (defined(USB_DEVICE_CONFIG_DETACH_ENABLE) && (USB_DEVICE_CONFIG_DETACH_ENABLE > 0U))
|
|
USB_DeviceChargerTask(&g_UsbDeviceComposite);
|
|
#endif
|
|
}
|