694 lines
25 KiB
C
694 lines
25 KiB
C
|
/*
|
||
|
* The Clear BSD License
|
||
|
* Copyright (c) 2015, Freescale Semiconductor, Inc.
|
||
|
* Copyright 2016-2017 NXP
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||
|
* are permitted (subject to the limitations in the disclaimer below) 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 the 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.
|
||
|
*
|
||
|
* NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
|
||
|
* 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 "fsl_device_registers.h"
|
||
|
#include "clock_config.h"
|
||
|
#include "board.h"
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "usb_device_config.h"
|
||
|
#include "usb.h"
|
||
|
#include "usb_device.h"
|
||
|
|
||
|
#include "usb_device_cdc_acm.h"
|
||
|
#include "usb_device_ch9.h"
|
||
|
|
||
|
#include "usb_device_descriptor.h"
|
||
|
#include "virtual_com.h"
|
||
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
||
|
#include "fsl_sysmpu.h"
|
||
|
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
|
||
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
|
||
|
#include "usb_phy.h"
|
||
|
#endif
|
||
|
|
||
|
/* Provided by users. */
|
||
|
extern void USB_DeviceClockInit(void);
|
||
|
extern void USB_DeviceIsrEnable(void);
|
||
|
/*******************************************************************************
|
||
|
* Definitions
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Variables
|
||
|
******************************************************************************/
|
||
|
/* Data structure of virtual com device */
|
||
|
usb_cdc_vcom_struct_t s_cdcVcom;
|
||
|
|
||
|
/* Line codinig of cdc device */
|
||
|
static uint8_t s_lineCoding[LINE_CODING_SIZE] = {
|
||
|
/* E.g. 0x00,0xC2,0x01,0x00 : 0x0001C200 is 115200 bits per second */
|
||
|
(LINE_CODING_DTERATE >> 0U) & 0x000000FFU,
|
||
|
(LINE_CODING_DTERATE >> 8U) & 0x000000FFU,
|
||
|
(LINE_CODING_DTERATE >> 16U) & 0x000000FFU,
|
||
|
(LINE_CODING_DTERATE >> 24U) & 0x000000FFU,
|
||
|
LINE_CODING_CHARFORMAT,
|
||
|
LINE_CODING_PARITYTYPE,
|
||
|
LINE_CODING_DATABITS};
|
||
|
|
||
|
/* Abstract state of cdc device */
|
||
|
static uint8_t s_abstractState[COMM_FEATURE_DATA_SIZE] = {(STATUS_ABSTRACT_STATE >> 0U) & 0x00FFU,
|
||
|
(STATUS_ABSTRACT_STATE >> 8U) & 0x00FFU};
|
||
|
|
||
|
/* Country code of cdc device */
|
||
|
static uint8_t s_countryCode[COMM_FEATURE_DATA_SIZE] = {(COUNTRY_SETTING >> 0U) & 0x00FFU,
|
||
|
(COUNTRY_SETTING >> 8U) & 0x00FFU};
|
||
|
|
||
|
/* CDC ACM information */
|
||
|
static usb_cdc_acm_info_t s_usbCdcAcmInfo = {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0};
|
||
|
|
||
|
/* Data buffer for receiving and sending*/
|
||
|
static uint8_t s_currRecvBuf[DATA_BUFF_SIZE];
|
||
|
volatile static uint32_t s_recvSize = 0;
|
||
|
volatile static uint32_t s_sendSize = 0;
|
||
|
volatile static uint8_t s_sendComplete = 0;
|
||
|
volatile static uint8_t s_currRecvIndex = 0;
|
||
|
static uint32_t s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
|
||
|
/*******************************************************************************
|
||
|
* Prototypes
|
||
|
******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
* Code
|
||
|
******************************************************************************/
|
||
|
/*!
|
||
|
* @brief Interrupt in pipe callback function.
|
||
|
*
|
||
|
* This function serves as the callback function for interrupt in pipe.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param message The endpoint callback message
|
||
|
* @param callbackParam The parameter of the callback.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceCdcAcmInterruptIn(usb_device_handle handle,
|
||
|
usb_device_endpoint_callback_message_struct_t *message,
|
||
|
void *callbackParam)
|
||
|
{
|
||
|
usb_status_t error = kStatus_USB_Error;
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Bulk in pipe callback function.
|
||
|
*
|
||
|
* This function serves as the callback function for bulk in pipe.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param message The endpoint callback message
|
||
|
* @param callbackParam The parameter of the callback.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceCdcAcmBulkIn(usb_device_handle handle,
|
||
|
usb_device_endpoint_callback_message_struct_t *message,
|
||
|
void *callbackParam)
|
||
|
{
|
||
|
usb_status_t error = kStatus_USB_Error;
|
||
|
|
||
|
if ((message->length != 0) && (!(message->length % s_usbBulkMaxPacketSize)))
|
||
|
{
|
||
|
/* If the last packet is the size of endpoint, then send also zero-ended packet,
|
||
|
** meaning that we want to inform the host that we do not have any additional
|
||
|
** data, so it can flush the output.
|
||
|
*/
|
||
|
USB_DeviceSendRequest(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0);
|
||
|
}
|
||
|
else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
|
||
|
{
|
||
|
if ((message->buffer != NULL) || ((message->buffer == NULL) && (message->length == 0)))
|
||
|
{
|
||
|
/* User: add your own code for send complete event */
|
||
|
s_sendComplete = 1;
|
||
|
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
|
||
|
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
|
||
|
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
|
||
|
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else if ((0 == s_sendComplete) && (1 == s_cdcVcom.attach) && (0 == s_cdcVcom.startTransactions))
|
||
|
{
|
||
|
s_sendComplete = 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Bulk out pipe callback function.
|
||
|
*
|
||
|
* This function serves as the callback function for bulk out pipe.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param message The endpoint callback message
|
||
|
* @param callbackParam The parameter of the callback.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceCdcAcmBulkOut(usb_device_handle handle,
|
||
|
usb_device_endpoint_callback_message_struct_t *message,
|
||
|
void *callbackParam)
|
||
|
{
|
||
|
usb_status_t error = kStatus_USB_Error;
|
||
|
if (USB_UNINITIALIZED_VAL_32 == message->length)
|
||
|
{
|
||
|
s_recvSize = 0xFFFFFFFFU;
|
||
|
}
|
||
|
else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions))
|
||
|
{
|
||
|
s_recvSize = message->length;
|
||
|
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
|
||
|
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
|
||
|
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
|
||
|
USB0->INTEN |= USB_INTEN_SOFTOKEN_MASK;
|
||
|
#endif
|
||
|
if (!s_recvSize)
|
||
|
{
|
||
|
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
|
||
|
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
|
||
|
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
|
||
|
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Get the setup packet buffer.
|
||
|
*
|
||
|
* This function provides the buffer for setup packet.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param setupBuffer The pointer to the address of setup packet buffer.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
|
||
|
{
|
||
|
static uint32_t cdcVcomSetup[2];
|
||
|
if (NULL == setupBuffer)
|
||
|
{
|
||
|
return kStatus_USB_InvalidParameter;
|
||
|
}
|
||
|
*setupBuffer = (usb_setup_struct_t *)&cdcVcomSetup;
|
||
|
return kStatus_USB_Success;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Get the setup packet data buffer.
|
||
|
*
|
||
|
* This function gets the data buffer for setup packet.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param setup The pointer to the setup packet.
|
||
|
* @param length The pointer to the length of the data buffer.
|
||
|
* @param buffer The pointer to the address of setup packet data buffer.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
|
||
|
usb_setup_struct_t *setup,
|
||
|
uint32_t *length,
|
||
|
uint8_t **buffer)
|
||
|
{
|
||
|
static uint8_t setupOut[8];
|
||
|
if ((NULL == buffer) || ((*length) > sizeof(setupOut)))
|
||
|
{
|
||
|
return kStatus_USB_InvalidRequest;
|
||
|
}
|
||
|
*buffer = setupOut;
|
||
|
return kStatus_USB_Success;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief Configure remote wakeup feature.
|
||
|
*
|
||
|
* This function configures the remote wakeup feature.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param enable 1: enable, 0: disable.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
|
||
|
{
|
||
|
return kStatus_USB_InvalidRequest;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief CDC class specific callback function.
|
||
|
*
|
||
|
* This function handles the CDC class specific requests.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param setup The pointer to the setup packet.
|
||
|
* @param length The pointer to the length of the data buffer.
|
||
|
* @param buffer The pointer to the address of setup packet data buffer.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
|
||
|
usb_setup_struct_t *setup,
|
||
|
uint32_t *length,
|
||
|
uint8_t **buffer)
|
||
|
{
|
||
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
||
|
|
||
|
usb_cdc_acm_info_t *acmInfo = &s_usbCdcAcmInfo;
|
||
|
uint32_t len;
|
||
|
uint16_t *uartBitmap;
|
||
|
if (setup->wIndex != USB_CDC_VCOM_COMM_INTERFACE_INDEX)
|
||
|
{
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
switch (setup->bRequest)
|
||
|
{
|
||
|
case USB_DEVICE_CDC_REQUEST_SEND_ENCAPSULATED_COMMAND:
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_GET_ENCAPSULATED_RESPONSE:
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_SET_COMM_FEATURE:
|
||
|
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
|
||
|
{
|
||
|
*buffer = s_abstractState;
|
||
|
}
|
||
|
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
|
||
|
{
|
||
|
*buffer = s_countryCode;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
error = kStatus_USB_Success;
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_GET_COMM_FEATURE:
|
||
|
if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == setup->wValue)
|
||
|
{
|
||
|
*buffer = s_abstractState;
|
||
|
*length = COMM_FEATURE_DATA_SIZE;
|
||
|
}
|
||
|
else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == setup->wValue)
|
||
|
{
|
||
|
*buffer = s_countryCode;
|
||
|
*length = COMM_FEATURE_DATA_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
}
|
||
|
error = kStatus_USB_Success;
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_CLEAR_COMM_FEATURE:
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_GET_LINE_CODING:
|
||
|
*buffer = s_lineCoding;
|
||
|
*length = LINE_CODING_SIZE;
|
||
|
error = kStatus_USB_Success;
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_SET_LINE_CODING:
|
||
|
*buffer = s_lineCoding;
|
||
|
error = kStatus_USB_Success;
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_SET_CONTROL_LINE_STATE:
|
||
|
{
|
||
|
acmInfo->dteStatus = setup->wValue;
|
||
|
/* activate/deactivate Tx carrier */
|
||
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
|
||
|
{
|
||
|
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_TX_CARRIER;
|
||
|
}
|
||
|
|
||
|
/* activate carrier and DTE */
|
||
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
|
||
|
{
|
||
|
acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_RX_CARRIER;
|
||
|
}
|
||
|
|
||
|
/* Indicates to DCE if DTE is present or not */
|
||
|
acmInfo->dtePresent = (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) ? true : false;
|
||
|
|
||
|
/* Initialize the serial state buffer */
|
||
|
acmInfo->serialStateBuf[0] = NOTIF_REQUEST_TYPE; /* bmRequestType */
|
||
|
acmInfo->serialStateBuf[1] = USB_DEVICE_CDC_REQUEST_SERIAL_STATE_NOTIF; /* bNotification */
|
||
|
acmInfo->serialStateBuf[2] = 0x00; /* wValue */
|
||
|
acmInfo->serialStateBuf[3] = 0x00;
|
||
|
acmInfo->serialStateBuf[4] = 0x00; /* wIndex */
|
||
|
acmInfo->serialStateBuf[5] = 0x00;
|
||
|
acmInfo->serialStateBuf[6] = UART_BITMAP_SIZE; /* wLength */
|
||
|
acmInfo->serialStateBuf[7] = 0x00;
|
||
|
/* Notifiy to host the line state */
|
||
|
acmInfo->serialStateBuf[4] = setup->wIndex;
|
||
|
/* Lower byte of UART BITMAP */
|
||
|
uartBitmap = (uint16_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2];
|
||
|
*uartBitmap = acmInfo->uartState;
|
||
|
len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE);
|
||
|
error = USB_DeviceSendRequest(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len);
|
||
|
|
||
|
/* Update status */
|
||
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION)
|
||
|
{
|
||
|
/* To do: CARRIER_ACTIVATED */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* To do: CARRIER_DEACTIVATED */
|
||
|
}
|
||
|
if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE)
|
||
|
{
|
||
|
/* DTE_ACTIVATED */
|
||
|
if (1 == s_cdcVcom.attach)
|
||
|
{
|
||
|
s_cdcVcom.startTransactions = 1;
|
||
|
#if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \
|
||
|
defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \
|
||
|
defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U)
|
||
|
USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK;
|
||
|
#endif
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* DTE_DEACTIVATED */
|
||
|
if (1 == s_cdcVcom.attach)
|
||
|
{
|
||
|
s_cdcVcom.startTransactions = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case USB_DEVICE_CDC_REQUEST_SEND_BREAK:
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief USB device callback function.
|
||
|
*
|
||
|
* This function handles the usb device specific requests.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param event The USB device event type.
|
||
|
* @param param The parameter of the device specific request.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
|
||
|
{
|
||
|
usb_status_t error = kStatus_USB_Error;
|
||
|
uint8_t *temp8 = (uint8_t *)param;
|
||
|
|
||
|
switch (event)
|
||
|
{
|
||
|
case kUSB_DeviceEventBusReset:
|
||
|
{
|
||
|
USB_DeviceControlPipeInit(s_cdcVcom.deviceHandle);
|
||
|
s_cdcVcom.attach = 0;
|
||
|
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)) || \
|
||
|
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|
||
|
if (kStatus_USB_Success ==
|
||
|
USB_DeviceGetStatus(s_cdcVcom.deviceHandle, kUSB_DeviceStatusSpeed, &s_cdcVcom.speed))
|
||
|
{
|
||
|
USB_DeviceSetSpeed(handle, s_cdcVcom.speed);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
break;
|
||
|
case kUSB_DeviceEventSetConfiguration:
|
||
|
if (param)
|
||
|
{
|
||
|
s_cdcVcom.attach = 1;
|
||
|
s_cdcVcom.currentConfiguration = *temp8;
|
||
|
if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8))
|
||
|
{
|
||
|
usb_device_endpoint_init_struct_t epInitStruct;
|
||
|
usb_device_endpoint_callback_struct_t endpointCallback;
|
||
|
|
||
|
/* Initiailize endpoint for interrupt pipe */
|
||
|
endpointCallback.callbackFn = USB_DeviceCdcAcmInterruptIn;
|
||
|
endpointCallback.callbackParam = handle;
|
||
|
|
||
|
epInitStruct.zlt = 0;
|
||
|
epInitStruct.transferType = USB_ENDPOINT_INTERRUPT;
|
||
|
epInitStruct.endpointAddress = USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT |
|
||
|
(USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
|
||
|
if (USB_SPEED_HIGH == s_cdcVcom.speed)
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE;
|
||
|
}
|
||
|
|
||
|
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
|
||
|
|
||
|
/* Initiailize endpoints for bulk pipe */
|
||
|
endpointCallback.callbackFn = USB_DeviceCdcAcmBulkIn;
|
||
|
endpointCallback.callbackParam = handle;
|
||
|
|
||
|
epInitStruct.zlt = 0;
|
||
|
epInitStruct.transferType = USB_ENDPOINT_BULK;
|
||
|
epInitStruct.endpointAddress =
|
||
|
USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
|
||
|
if (USB_SPEED_HIGH == s_cdcVcom.speed)
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE;
|
||
|
}
|
||
|
|
||
|
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
|
||
|
|
||
|
endpointCallback.callbackFn = USB_DeviceCdcAcmBulkOut;
|
||
|
endpointCallback.callbackParam = handle;
|
||
|
|
||
|
epInitStruct.zlt = 0;
|
||
|
epInitStruct.transferType = USB_ENDPOINT_BULK;
|
||
|
epInitStruct.endpointAddress =
|
||
|
USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
|
||
|
if (USB_SPEED_HIGH == s_cdcVcom.speed)
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
|
||
|
}
|
||
|
|
||
|
USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback);
|
||
|
|
||
|
if (USB_SPEED_HIGH == s_cdcVcom.speed)
|
||
|
{
|
||
|
s_usbBulkMaxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/*!
|
||
|
* @brief USB configure endpoint function.
|
||
|
*
|
||
|
* This function configure endpoint status.
|
||
|
*
|
||
|
* @param handle The USB device handle.
|
||
|
* @param ep Endpoint address.
|
||
|
* @param status A flag to indicate whether to stall the endpoint. 1: stall, 0: unstall.
|
||
|
*
|
||
|
* @return A USB error code or kStatus_USB_Success.
|
||
|
*/
|
||
|
usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
|
||
|
{
|
||
|
if (status)
|
||
|
{
|
||
|
return USB_DeviceStallEndpoint(handle, ep);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return USB_DeviceUnstallEndpoint(handle, ep);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* See virtual_com.h for documentation of this function. */
|
||
|
void USB_VcomWriteBlocking(usb_device_handle baseAddr, const uint8_t *buf, size_t count)
|
||
|
{
|
||
|
while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
|
||
|
{
|
||
|
__NOP();
|
||
|
};
|
||
|
USB_DeviceSendRequest((usb_device_handle)baseAddr, USB_CDC_VCOM_BULK_IN_ENDPOINT, (uint8_t *)buf, count);
|
||
|
while (!s_sendComplete)
|
||
|
{
|
||
|
__NOP();
|
||
|
};
|
||
|
s_sendComplete = 0;
|
||
|
}
|
||
|
|
||
|
/* See virtual_com.h for documentation of this function. */
|
||
|
status_t USB_VcomReadBlocking(usb_device_handle baseAddr, uint8_t *buf, size_t count)
|
||
|
{
|
||
|
status_t error = kStatus_Success;
|
||
|
size_t bufIndex = 0U, bytesToReceive = 0U;
|
||
|
assert(count != 0U);
|
||
|
|
||
|
/* Waiting for the USB ready. */
|
||
|
while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
|
||
|
{
|
||
|
__NOP();
|
||
|
};
|
||
|
|
||
|
do
|
||
|
{
|
||
|
/* If no receive request. */
|
||
|
if (s_recvSize <= 0)
|
||
|
{
|
||
|
if (kStatus_USB_Success !=
|
||
|
USB_DeviceRecvRequest(baseAddr, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, s_usbBulkMaxPacketSize))
|
||
|
{
|
||
|
return kStatus_Fail;
|
||
|
}
|
||
|
s_currRecvIndex = 0;
|
||
|
}
|
||
|
/* Waiting for data received by virtual com. */
|
||
|
while (s_recvSize <= 0)
|
||
|
{
|
||
|
__NOP();
|
||
|
};
|
||
|
|
||
|
/* When receive request is error. */
|
||
|
if (0xFFFFFFFFU == s_recvSize)
|
||
|
{
|
||
|
/* Waiting for the USB ready and transfer started. */
|
||
|
while ((s_cdcVcom.attach != 1) || (s_cdcVcom.startTransactions != 1))
|
||
|
{
|
||
|
__NOP();
|
||
|
};
|
||
|
s_recvSize = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bytesToReceive = MIN(count, s_recvSize);
|
||
|
memcpy((void *)&buf[bufIndex], s_currRecvBuf + s_currRecvIndex, bytesToReceive);
|
||
|
count -= bytesToReceive;
|
||
|
s_recvSize -= bytesToReceive;
|
||
|
bufIndex += bytesToReceive;
|
||
|
s_currRecvIndex += bytesToReceive;
|
||
|
}
|
||
|
} while (0U != count);
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
/* See virtual_com.h for documentation of this function. */
|
||
|
usb_device_handle USB_VcomInit(void)
|
||
|
{
|
||
|
usb_device_handle deviceHandle = NULL;
|
||
|
|
||
|
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 */
|
||
|
|
||
|
s_cdcVcom.speed = USB_SPEED_FULL;
|
||
|
s_cdcVcom.attach = 0;
|
||
|
s_cdcVcom.deviceHandle = NULL;
|
||
|
|
||
|
if (kStatus_USB_Success != USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &s_cdcVcom.deviceHandle))
|
||
|
{
|
||
|
deviceHandle = NULL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
deviceHandle = s_cdcVcom.deviceHandle;
|
||
|
USB_DeviceIsrEnable();
|
||
|
USB_DeviceRun(s_cdcVcom.deviceHandle);
|
||
|
}
|
||
|
return deviceHandle;
|
||
|
}
|
||
|
|
||
|
/* See virtual_com.h for documentation of this function. */
|
||
|
void USB_VcomDeinit(usb_device_handle deviceHandle)
|
||
|
{
|
||
|
USB_DeviceStop(deviceHandle);
|
||
|
USB_DeviceDeinit(deviceHandle);
|
||
|
s_cdcVcom.deviceHandle = NULL;
|
||
|
#if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)
|
||
|
USB_EhciPhyDeinit(CONTROLLER_ID);
|
||
|
#endif
|
||
|
#if defined(USB_DEVICE_CONFIG_KHCI) && (USB_DEVICE_CONFIG_KHCI > 0)
|
||
|
CLOCK_DisableUsbfs0Clock();
|
||
|
#endif
|
||
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511FS) && (USB_DEVICE_CONFIG_LPCIP3511FS > 0U)
|
||
|
/* enable USB IP clock, user code. */
|
||
|
CLOCK_DisableClock(kCLOCK_Usbd0);
|
||
|
#endif /* USB_DEVICE_CONFIG_LPCIP3511FS */
|
||
|
|
||
|
#if defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)
|
||
|
/* enable USB IP clock,user code. */
|
||
|
#endif /* USB_DEVICE_CONFIG_LPCIP3511HS */
|
||
|
}
|