1899 lines
84 KiB
C
1899 lines
84 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* uC/USB-Host
|
|
* The Embedded USB Host Stack
|
|
*
|
|
* Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com
|
|
*
|
|
* SPDX-License-Identifier: APACHE-2.0
|
|
*
|
|
* This software is subject to an open source license and is distributed by
|
|
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
|
|
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*
|
|
* FUTURE TECHNOLOGY DEVICES INTERNATIONAL CLASS
|
|
*
|
|
* Filename : usbh_ftdi.c
|
|
* Version : V3.42.01
|
|
* Note(s) : The reference document "API for FTxxxx Devices Application Note AN_115" can be
|
|
* requested from FTDI after signing a Non-Disclosure Agreement (NDA).
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_FTDI_MODULE
|
|
#define MICRIUM_SOURCE
|
|
#include "usbh_ftdi.h"
|
|
#include "../../Source/usbh_core.h"
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* FTDI VENDOR ID
|
|
*
|
|
* Note(s) : (1) See "API for FTxxxx Devices Application Note AN_115", April 04 2011, Version 1.1,
|
|
* section 2.
|
|
*
|
|
* (2) The 'idVendor' field of the device descriptor may contain this value.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_FTDI_ID_VENDOR 0x0403u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* FTDI PRODUCT IDs
|
|
*
|
|
* Note(s) : (1) See "API for FTxxxx Devices Application Note AN_115", April 04 2011, Version 1.1,
|
|
* section 2.
|
|
*
|
|
* (2) The 'idProduct' field of the device descriptor may contain one of these values.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_FTDI_ID_PRODUCT_FT8U232AM 0x6001u
|
|
#define USBH_FTDI_ID_PRODUCT_FT232B 0x6001u
|
|
#define USBH_FTDI_ID_PRODUCT_FT2232D 0x6010u
|
|
#define USBH_FTDI_ID_PRODUCT_FT232R 0x6001u
|
|
#define USBH_FTDI_ID_PRODUCT_FT2232H 0x6010u
|
|
#define USBH_FTDI_ID_PRODUCT_FT4232H 0x6011u
|
|
#define USBH_FTDI_ID_PRODUCT_FT232H 0x6014u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* CLASS-SPECIFIC REQUESTS
|
|
*
|
|
* Note(s) : (1) See "API for FTxxxx Devices Application Note AN_115", April 04 2011, Version 1.1,
|
|
* section 3.
|
|
*
|
|
* (2) The 'bRequest' field of a class-specific setup request may contain one of these values.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_FTDI_REQ_RESET 0x00u
|
|
#define USBH_FTDI_REQ_SET_MODEM_CTRL 0x01u
|
|
#define USBH_FTDI_REQ_SET_FLOW_CTRL 0x02u
|
|
#define USBH_FTDI_REQ_SET_BAUD_RATE 0x03u
|
|
#define USBH_FTDI_REQ_SET_DATA 0x04u
|
|
#define USBH_FTDI_REQ_GET_MODEM_STATUS 0x05u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_FNCT
|
|
*
|
|
* Note(s) : (1) FTDI device main structure.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbh_ftdi_fnct {
|
|
USBH_FTDI_HANDLE Handle; /* Handle of FTDI dev struct. */
|
|
USBH_DEV *DevPtr; /* Ptr to dev struct. */
|
|
USBH_IF *IF_Ptr; /* Ptr to IF struct. */
|
|
USBH_EP BulkInEP; /* Bulk IN EP. */
|
|
USBH_EP BulkOutEP; /* Bulk OUT EP. */
|
|
|
|
CPU_INT08U Port; /* Holds cur port. */
|
|
CPU_INT08U State; /* Holds cur dev state. */
|
|
CPU_INT32U MaxPktSize; /* Holds max pkt size. */
|
|
|
|
USBH_HMUTEX RxHMutex; /* Handle on RX mutex. */
|
|
|
|
USBH_FTDI_ASYNC_TX_FNCT DataTxNotifyPtr; /* Ptr to TX callback fnct. */
|
|
void *DataTxNotifyArgPtr; /* Ptr to TX notify arg. */
|
|
USBH_FTDI_ASYNC_RX_FNCT DataRxNotifyPtr; /* Ptr to RX callback fnct. */
|
|
void *DataRxNotifyArgPtr; /* Ptr to RX notify arg. */
|
|
void *DataRxBuf; /* Ptr to data RX buf. */
|
|
USBH_FTDI_SERIAL_STATUS *SerialStatusPtr; /* Ptr to serial status. */
|
|
CPU_INT32U RxBufLen; /* Size of RX buf. */
|
|
CPU_INT32U XferLen; /* Tot len of data rx'd in octets. */
|
|
CPU_INT16U LastBytes; /* Last two bytes of last RX pkt. */
|
|
} USBH_FTDI_FNCT;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_CLASS_DRV USBH_FTDI_ClassDrv; /* FTDI Class drv API. */
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL TABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_FTDI_FNCT USBH_FTDI_DevTbl[USBH_FTDI_CFG_MAX_DEV];
|
|
static MEM_POOL USBH_FTDI_DevPool;
|
|
|
|
static USBH_DEV *USBH_FTDI_DevPtrPrev; /* Last conn'd dev addr. */
|
|
static CPU_INT08U USBH_FTDI_PortCnt; /* Cnt nbr of port of a dev. */
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL MACROS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_FTDI_HANDLE_IX_GET(ftdi_handle) ((CPU_INT08U)ftdi_handle);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH CLASS DRIVER API PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_GlobalInit (USBH_ERR *p_err);
|
|
|
|
static void *USBH_FTDI_ProbeIF (USBH_DEV *p_dev,
|
|
USBH_IF *p_if,
|
|
USBH_ERR *p_err);
|
|
|
|
static void USBH_FTDI_Suspend (void *p_class_dev);
|
|
|
|
static void USBH_FTDI_Resume (void *p_class_dev);
|
|
|
|
static void USBH_FTDI_Disconn (void *p_class_dev);
|
|
|
|
static void USBH_FTDI_ClassDevNotify(void *p_class_dev,
|
|
CPU_INT08U state,
|
|
void *p_ctx);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_StdReq (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT08U request,
|
|
CPU_INT16U value,
|
|
CPU_INT08U index,
|
|
USBH_ERR *p_err);
|
|
|
|
static void USBH_FTDI_DataTxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err);
|
|
|
|
static void USBH_FTDI_DataRxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONFIGURATION ERRORS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* FTDI CLASS DRIVER
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_CLASS_DRV USBH_FTDI_ClassDrv = {
|
|
(CPU_INT08U *)"FTDI",
|
|
USBH_FTDI_GlobalInit,
|
|
0,
|
|
USBH_FTDI_ProbeIF,
|
|
USBH_FTDI_Suspend,
|
|
USBH_FTDI_Resume,
|
|
USBH_FTDI_Disconn
|
|
};
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Init()
|
|
*
|
|
* Description : Initialize the global variables of the FTDI Class.
|
|
*
|
|
* Argument(s) : p_ftdi_callbacks Callback functions structure to notify application when a FTDI device
|
|
* is connected/disconnected.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Interface is of FTDI type.
|
|
* USBH_ERR_DEV_ALLOC, Cannot allocate FTDI device.
|
|
*
|
|
* ----- RETURNED BY USBH_ClassDrvReg() : -----
|
|
* USBH_ERR_INVALID_ARG, If invalid argument(s) passed to 'p_host'/'p_class_drv'.
|
|
* USBH_ERR_CLASS_DRV_ALLOC, If maximum class driver limit reached.
|
|
*
|
|
* ----- RETURNED BY USBH_OS_MutexCreate() : -----
|
|
* USBH_ERR_ALLOC, Cannot allocate mutex.
|
|
* USBH_ERR_OS_SIGNAL_CREATE Cannot create mutex.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_Init (USBH_FTDI_CALLBACKS *p_ftdi_callbacks,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_SIZE_T octets_reqd;
|
|
CPU_INT08U ix;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
Mem_PoolCreate( &USBH_FTDI_DevPool,
|
|
(void *)USBH_FTDI_DevTbl,
|
|
(sizeof(USBH_FTDI_FNCT) * USBH_FTDI_CFG_MAX_DEV),
|
|
USBH_FTDI_CFG_MAX_DEV,
|
|
sizeof(USBH_FTDI_FNCT),
|
|
sizeof(CPU_ALIGN),
|
|
&octets_reqd,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBH_ERR_ALLOC;
|
|
return;
|
|
}
|
|
|
|
for (ix = 0u; ix < USBH_FTDI_CFG_MAX_DEV; ix++) {
|
|
*p_err = USBH_OS_MutexCreate(&USBH_FTDI_DevTbl[ix].RxHMutex);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return;
|
|
}
|
|
|
|
USBH_FTDI_DevTbl[ix].Handle = (USBH_FTDI_HANDLE)ix;
|
|
USBH_FTDI_DevTbl[ix].State = USBH_CLASS_DEV_STATE_NONE;
|
|
}
|
|
|
|
USBH_FTDI_DevPtrPrev = (void *)0;
|
|
USBH_FTDI_PortCnt = 0u;
|
|
|
|
*p_err = USBH_ClassDrvReg( &USBH_FTDI_ClassDrv,
|
|
USBH_FTDI_ClassDevNotify,
|
|
(void *)p_ftdi_callbacks);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Reset()
|
|
*
|
|
* Description : Reset the communication port.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* reset_ctrl Select buffer to reset. This is a bitmap of the following possible values:
|
|
*
|
|
* USBH_FTDI_RESET_CTRL_SIO, Reset SIO (Resets both RX and TX buffer).
|
|
* USBH_FTDI_RESET_CTRL_RX, Purge RX buffer.
|
|
* USBH_FTDI_RESET_CTRL_TX Purge TX buffer.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'reset_ctrl'.
|
|
*
|
|
* ----- RETURNED BY USBH_FTDI_StdReq() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : For more information on the 'Reset' request, see 'API for FTxxxx Devices Application
|
|
* Note AN_115, April 04 2011, Version 1.1, section 3.1'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_Reset (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT16U reset_ctrl,
|
|
USBH_ERR *p_err)
|
|
{
|
|
if ((reset_ctrl != USBH_FTDI_RESET_CTRL_SIO) &&
|
|
(reset_ctrl != USBH_FTDI_RESET_CTRL_RX) &&
|
|
(reset_ctrl != USBH_FTDI_RESET_CTRL_TX)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
USBH_FTDI_StdReq(ftdi_handle, /* Send Reset req. */
|
|
USBH_FTDI_REQ_RESET,
|
|
reset_ctrl,
|
|
0u,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_ModemCtrlSet()
|
|
*
|
|
* Description : Set modem control register of the communication port.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* modem_ctrl Modem control value. This is a bitmap of the following possible values:
|
|
*
|
|
* USBH_FTDI_MODEM_CTRL_DTR_SET, Set DTR state.
|
|
* USBH_FTDI_MODEM_CTRL_DTR_RESET, Reset DTR state.
|
|
* USBH_FTDI_MODEM_CTRL_DTR_ENABLED, Use DTR state.
|
|
* USBH_FTDI_MODEM_CTRL_DTR_DISABLED, Disable DTR state.
|
|
*
|
|
* USBH_FTDI_MODEM_CTRL_RTS_SET, Set RTS state.
|
|
* USBH_FTDI_MODEM_CTRL_RTS_RESET, Reset RTS state.
|
|
* USBH_FTDI_MODEM_CTRL_RTS_ENABLED, Use RTS state.
|
|
* USBH_FTDI_MODEM_CTRL_RTS_DISABLED Disable RTS state.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'modem_ctrl'.
|
|
*
|
|
* ----- RETURNED BY USBH_FTDI_StdReq() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : For more information on the 'ModemCtrl' request, see 'API for FTxxxx Devices Application
|
|
* Note AN_115, April 04 2011, Version 1.1, section 3.2'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_ModemCtrlSet (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT16U modem_ctrl,
|
|
USBH_ERR *p_err)
|
|
{
|
|
if ((modem_ctrl & 0xFCFCu) != 0u) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
USBH_FTDI_StdReq(ftdi_handle, /* Send ModemCtrl req. */
|
|
USBH_FTDI_REQ_SET_MODEM_CTRL,
|
|
modem_ctrl,
|
|
0u,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_FlowCtrlSet()
|
|
*
|
|
* Description : Set flow control handshaking for the communication port.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* protocol Protocol to set. This is a bitmap of the following possible values:
|
|
*
|
|
* USBH_FTDI_PROTOCOL_RTS_CTS, Enable output handshaking using RTS/CTS.
|
|
* USBH_FTDI_PROTOCOL_DTR_DSR, Enable output handshaking using DTR/DSR.
|
|
* USBH_FTDI_PROTOCOL_XON_XOFF Enable Xon/Xoff handshaking.
|
|
*
|
|
* xon_char Xon character.
|
|
*
|
|
* xoff_char Xoff character.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'xon_char'/
|
|
* 'xoff_char'/'protocol'.
|
|
*
|
|
* ----- RETURNED BY USBH_FTDI_StdReq() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : For more information on the 'SetFlowCtrl' request, see 'API for FTxxxx Devices
|
|
* Application Note AN_115, April 04 2011, Version 1.1, section 3.3'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_FlowCtrlSet (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT08U protocol,
|
|
CPU_INT08U xon_char,
|
|
CPU_INT08U xoff_char,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_INT16U value;
|
|
|
|
|
|
if ((protocol != USBH_FTDI_PROTOCOL_RTS_CTS) &&
|
|
(protocol != USBH_FTDI_PROTOCOL_DTR_DSR) &&
|
|
(protocol != USBH_FTDI_PROTOCOL_XON_XOFF) &&
|
|
(protocol != DEF_BIT_NONE)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
value = (CPU_INT16U)(((CPU_INT16U)xoff_char << 8u) | xon_char);
|
|
|
|
USBH_FTDI_StdReq(ftdi_handle, /* Send SetFlowCtrl req. */
|
|
USBH_FTDI_REQ_SET_FLOW_CTRL,
|
|
value,
|
|
protocol,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_BaudRateSet()
|
|
*
|
|
* Description : Set baud rate of the communication port.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* baud_rate Baud rate to set.
|
|
*
|
|
* USBH_FTDI_BAUD_RATE_300, Set baud rate to 300 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_600, Set baud rate to 600 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_1200, Set baud rate to 1200 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_2400, Set baud rate to 2400 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_4800, Set baud rate to 4800 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_9600, Set baud rate to 9600 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_19200, Set baud rate to 19200 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_38400, Set baud rate to 38400 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_57600, Set baud rate to 57600 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_115200, Set baud rate to 115200 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_230400, Set baud rate to 230400 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_460800, Set baud rate to 460800 bits/sec.
|
|
* USBH_FTDI_BAUD_RATE_921600 Set baud rate to 921600 bits/sec.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'baud_rate'.
|
|
*
|
|
* ----- RETURNED BY USBH_FTDI_StdReq() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : For more information on the 'SetBaudRate' request, see 'API for FTxxxx Devices
|
|
* Application Note AN_115, April 04 2011, Version 1.1, section 3.4'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_BaudRateSet (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT16U baud_rate,
|
|
USBH_ERR *p_err)
|
|
{
|
|
if ((baud_rate != USBH_FTDI_BAUD_RATE_300) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_600) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_1200) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_2400) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_4800) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_9600) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_19200) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_38400) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_57600) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_115200) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_230400) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_460800) &&
|
|
(baud_rate != USBH_FTDI_BAUD_RATE_921600)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
USBH_FTDI_StdReq(ftdi_handle, /* Send SetBaudRate req. */
|
|
USBH_FTDI_REQ_SET_BAUD_RATE,
|
|
baud_rate,
|
|
0u,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_DataSet()
|
|
*
|
|
* Description : Set data characteristics of the communication port.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* data_size Number of data bits.
|
|
*
|
|
* parity Parity to use.
|
|
*
|
|
* USBH_FTDI_DATA_PARITY_NONE, Do not use the parity bit.
|
|
* USBH_FTDI_DATA_PARITY_ODD, Use odd parity bit.
|
|
* USBH_FTDI_DATA_PARITY_EVEN, Use even parity bit.
|
|
* USBH_FTDI_DATA_PARITY_MARK, Use mark parity bit.
|
|
* USBH_FTDI_DATA_PARITY_SPACE Use space parity bit.
|
|
*
|
|
* stop_bits Number of stop bits.
|
|
*
|
|
* USBH_FTDI_DATA_STOP_BITS_1, Use 1 stop bit.
|
|
* USBH_FTDI_DATA_STOP_BITS_2 Use 2 stop bit.
|
|
*
|
|
* break_bit Send break.
|
|
*
|
|
* USBH_FTDI_DATA_BREAK_ENABLED, Send break.
|
|
* USBH_FTDI_DATA_BREAK_DISABLED Stop break.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'parity'/
|
|
* 'stop_bits'/'break_bit'.
|
|
*
|
|
* ----- RETURNED BY USBH_FTDI_StdReq() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : For more information on the 'SetData' request, see 'API for FTxxxx Devices Application
|
|
* Note AN_115, April 04 2011, Version 1.1, section 3.5'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_DataSet (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT08U data_size,
|
|
CPU_INT08U parity,
|
|
CPU_INT08U stop_bits,
|
|
CPU_INT08U break_bit,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_INT16U value;
|
|
|
|
|
|
if ((parity != USBH_FTDI_DATA_PARITY_NONE) &&
|
|
(parity != USBH_FTDI_DATA_PARITY_ODD) &&
|
|
(parity != USBH_FTDI_DATA_PARITY_EVEN) &&
|
|
(parity != USBH_FTDI_DATA_PARITY_MARK) &&
|
|
(parity != USBH_FTDI_DATA_PARITY_SPACE)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if ((stop_bits != USBH_FTDI_DATA_STOP_BITS_1) &&
|
|
(stop_bits != USBH_FTDI_DATA_STOP_BITS_2)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if ((break_bit != USBH_FTDI_DATA_BREAK_ENABLED) &&
|
|
(break_bit != USBH_FTDI_DATA_BREAK_DISABLED)) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
value = (CPU_INT16U)(((CPU_INT16U)(parity | stop_bits | break_bit) << 8u) | data_size);
|
|
|
|
USBH_FTDI_StdReq(ftdi_handle, /* Send SetData req. */
|
|
USBH_FTDI_REQ_SET_DATA,
|
|
value,
|
|
0u,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_ModemStatusGet()
|
|
*
|
|
* Description : Retrieve the current value of the serial status register.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_serial_status Pointer to USBH_FTDI_SERIAL_STATUS structure that will be filled by this function.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'/
|
|
* 'p_serial_status'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* Host controller drivers error code, Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : (1) The device updates the serial status every 16 milliseconds.
|
|
*
|
|
* (2) The following masks may be used to determine if a bit of the modem status is set:
|
|
*
|
|
* USBH_FTDI_MODEM_STATUS_FS
|
|
* USBH_FTDI_MODEM_STATUS_HS
|
|
* USBH_FTDI_MODEM_STATUS_CLEAR_TO_SEND
|
|
* USBH_FTDI_MODEM_STATUS_DATA_SET_READY
|
|
* USBH_FTDI_MODEM_STATUS_RING_INDICATOR
|
|
* USBH_FTDI_MODEM_STATUS_DATA_CARRIER_DETECT
|
|
*
|
|
* (3) The following masks may be used to determine if a bit of the line status is set:
|
|
*
|
|
* USBH_FTDI_LINE_STATUS_RX_OVERFLOW_ERROR
|
|
* USBH_FTDI_LINE_STATUS_PARITY_ERROR
|
|
* USBH_FTDI_LINE_STATUS_FRAMING_ERROR
|
|
* USBH_FTDI_LINE_STATUS_BREAK_INTERRUPT
|
|
* USBH_FTDI_LINE_STATUS_TX_REGISTER_EMPTY
|
|
* USBH_FTDI_LINE_STATUS_TX_EMPTY
|
|
*
|
|
* (4) For more information on the 'GetModemStat' request, see 'API for FTxxxx Devices
|
|
* Application Note AN_115, April 04 2011, Version 1.1, section 3.6'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_ModemStatusGet (USBH_FTDI_HANDLE ftdi_handle,
|
|
USBH_FTDI_SERIAL_STATUS *p_serial_status,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
CPU_INT08U status[USBH_FTDI_SERIAL_STATUS_LEN];
|
|
|
|
|
|
if (p_serial_status == (void *)0){
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return;
|
|
}
|
|
|
|
(void)USBH_CtrlRx( p_ftdi_fnct->DevPtr, /* Send GET_MODEM_STATUS req. */
|
|
USBH_FTDI_REQ_GET_MODEM_STATUS,
|
|
(USBH_REQ_DIR_DEV_TO_HOST | USBH_REQ_TYPE_VENDOR | USBH_REQ_RECIPIENT_DEV),
|
|
0u,
|
|
p_ftdi_fnct->Port,
|
|
(void *)&status,
|
|
USBH_FTDI_SERIAL_STATUS_LEN,
|
|
USBH_CFG_STD_REQ_TIMEOUT,
|
|
p_err);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return;
|
|
}
|
|
|
|
p_serial_status->ModemStatus = status[0u];
|
|
p_serial_status->LineStatus = status[1u];
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Tx()
|
|
*
|
|
* Description : Send data to FTDI device.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_buf Pointer to buffer that contains the data to transfer.
|
|
*
|
|
* buf_len Buffer length, in octets.
|
|
*
|
|
* timeout Timeout, in milliseconds.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Data successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'/
|
|
* 'buf_len'.
|
|
* USBH_ERR_NULL_PTR, Invalid null pointer passed to 'p_buf'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
*
|
|
* ----- RETURNED BY USBH_BulkTx() : -----
|
|
* USBH_ERR_NONE, Bulk transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE, Endpoint type is not Bulk or direction is not OUT.
|
|
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
|
|
* Host controller drivers error code Otherwise.
|
|
*
|
|
* Return(s) : Number of octets transferred, if NO error(s).
|
|
*
|
|
* 0, otherwise.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT32U USBH_FTDI_Tx (USBH_FTDI_HANDLE ftdi_handle,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT16U timeout,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
CPU_INT32U xfer_len;
|
|
|
|
|
|
if (buf_len == 0u) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBH_ERR_NULL_PTR;
|
|
return (0u);
|
|
}
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return (0u);
|
|
}
|
|
|
|
xfer_len = USBH_BulkTx(&p_ftdi_fnct->BulkOutEP, /* Send data through specified EP to FTDI dev. */
|
|
p_buf,
|
|
buf_len,
|
|
timeout,
|
|
p_err);
|
|
if (*p_err != USBH_ERR_NONE) { /* Reset EP if err occurred. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
&p_ftdi_fnct->BulkOutEP);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_ftdi_fnct->BulkOutEP);
|
|
}
|
|
|
|
return (0u);
|
|
}
|
|
|
|
return (xfer_len);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_TxAsync()
|
|
*
|
|
* Description : Send data to FTDI device. This function is non blocking.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_buf Pointer to buffer of data that will be sent.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* tx_cmpl_notify Function that will be invoked upon completion of transmit operation.
|
|
*
|
|
* p_arg Pointer to argument that will be passed as parameter of 'tx_cmpl_notify'.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, If data successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'/
|
|
* 'buf_len'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* USBH_ERR_NULL_PTR, Invalid null pointer passed to 'p_buf'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
*
|
|
* ----- RETURNED BY USBH_BulkTxAsync() : -----
|
|
* USBH_ERR_NONE, If request is successfully submitted.
|
|
* USBH_ERR_INVALID_ARG, If invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE, If endpoint type is not bulk or direction is
|
|
* not OUT.
|
|
* USBH_ERR_EP_INVALID_STATE, If endpoint is not opened.
|
|
* USBH_ERR_ALLOC, If URB cannot be allocated.
|
|
* USBH_ERR_UNKNOWN, If unknown error occured.
|
|
* Host controller drivers error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : (1) Asynchronous transmit is not thread safe. Hence, it is not safe to call this function
|
|
* from more than 1 application task at the same time for the same device. It is however
|
|
* safe to call it from the completion callback.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_TxAsync (USBH_FTDI_HANDLE ftdi_handle,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
USBH_FTDI_ASYNC_TX_FNCT tx_cmpl_notify,
|
|
void *p_arg,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
|
|
|
|
if (buf_len == 0u) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBH_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct->DataTxNotifyPtr = tx_cmpl_notify;
|
|
p_ftdi_fnct->DataTxNotifyArgPtr = p_arg;
|
|
|
|
*p_err = USBH_BulkTxAsync( &p_ftdi_fnct->BulkOutEP, /* Send data through specified EP to FTDI dev. */
|
|
p_buf,
|
|
buf_len,
|
|
USBH_FTDI_DataTxCmpl,
|
|
(void *)p_ftdi_fnct);
|
|
if (*p_err != USBH_ERR_NONE) { /* Reset EP if an err occurred. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
&p_ftdi_fnct->BulkOutEP);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_ftdi_fnct->BulkOutEP);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Rx()
|
|
*
|
|
* Description : Receive data from FTDI device.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_buf Pointer to data buffer to hold received data.
|
|
*
|
|
* buf_len Buffer length, in octets.
|
|
*
|
|
* timeout Timeout, in milliseconds.
|
|
*
|
|
* p_serial_status Pointer to USBH_FTDI_SERIAL_STATUS structure that will be filled by this function.
|
|
* This argument can be null.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Data successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'/
|
|
* 'buf_len'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* USBH_ERR_NULL_PTR, Invalid null pointer passed to 'p_buf'.
|
|
*
|
|
*
|
|
* ----- RETURNED BY USBH_BulkRx() : -----
|
|
* USBH_ERR_NONE Bulk transfer successfully received.
|
|
* USBH_ERR_INVALID_ARG Invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE Endpoint type is not Bulk or direction is not IN.
|
|
* USBH_ERR_EP_INVALID_STATE Endpoint is not opened.
|
|
* Host controller drivers error code Otherwise.
|
|
*
|
|
* Return(s) : Number of octets received, if NO error(s).
|
|
*
|
|
* 0, otherwise.
|
|
*
|
|
* Note(s) : (1) The following masks may be used to determine if a bit of the modem status is set:
|
|
*
|
|
* USBH_FTDI_MODEM_STATUS_FS
|
|
* USBH_FTDI_MODEM_STATUS_HS
|
|
* USBH_FTDI_MODEM_STATUS_CLEAR_TO_SEND
|
|
* USBH_FTDI_MODEM_STATUS_DATA_SET_READY
|
|
* USBH_FTDI_MODEM_STATUS_RING_INDICATOR
|
|
* USBH_FTDI_MODEM_STATUS_DATA_CARRIER_DETECT
|
|
*
|
|
* (2) The following masks may be used to determine if a bit of the line status is set:
|
|
*
|
|
* USBH_FTDI_LINE_STATUS_RX_OVERFLOW_ERROR
|
|
* USBH_FTDI_LINE_STATUS_PARITY_ERROR
|
|
* USBH_FTDI_LINE_STATUS_FRAMING_ERROR
|
|
* USBH_FTDI_LINE_STATUS_BREAK_INTERRUPT
|
|
* USBH_FTDI_LINE_STATUS_TX_REGISTER_EMPTY
|
|
* USBH_FTDI_LINE_STATUS_TX_EMPTY
|
|
*
|
|
* (3) The received data in 'p_buf' is in little-endian.
|
|
*
|
|
* (4) The FTDI device always add a status of two bytes at the beginning of every packet.
|
|
* This function manage those status bytes in order to get the latest status followed
|
|
* by the data in 'p_buf'.
|
|
* This only applies when the application requests more than max packet size (MPS) - 2 bytes of data.
|
|
*
|
|
* +----+----+----+----+-----+---------+---------+-----+-----
|
|
* (a) Receive first pkt in buffer. | S0 | S1 | D0 | D1 | ... | MPS - 2 | MPS - 1 | MPS | ...
|
|
* +----+----+----+----+-----+---------+---------+-----+-----
|
|
* | |
|
|
* v v
|
|
* +---------+-----+
|
|
* (b) Save the last two bytes of data. | MPS - 1 | MPS |
|
|
* +---------+-----+
|
|
*
|
|
* +----+----+----+----+-----+---------+-----+-----+---------+---------+-----
|
|
* (c) Receive next pkt in buffer. | S0 | S1 | D0 | D1 | ... | MPS - 2 | S2 | S3 | MPS + 1 | MPS + 2 | ...
|
|
* +----+----+----+----+-----+---------+-----+-----+---------+---------+-----
|
|
*
|
|
* +----+----+----+----+-----+---------+---------+-----+---------+---------+-----
|
|
* (d) Update the status. | S2 | S3 | D0 | D1 | ... | MPS - 2 | S2 | S3 | MPS + 1 | MPS + 2 | ...
|
|
* +----+----+----+----+-----+---------+---------+-----+---------+---------+-----
|
|
* ^ ^
|
|
* | |
|
|
* +---------+-----+
|
|
* (e) Restore the two bytes of data. | MPS - 1 | MPS |
|
|
* +---------+-----+
|
|
*
|
|
* (f) Repeat step (b) to (e) until the end of the buffer is reached or the last transfer size is
|
|
* smaller than maxPktSize.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT32U USBH_FTDI_Rx (USBH_FTDI_HANDLE ftdi_handle,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT16U timeout,
|
|
USBH_FTDI_SERIAL_STATUS *p_serial_status,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
CPU_INT32U xfer_len;
|
|
CPU_INT32U xfer_len_cur;
|
|
CPU_INT32U buf_len_cur;
|
|
CPU_INT16U data;
|
|
CPU_INT08U *p_buf_cur08;
|
|
CPU_INT32U pkt_size_rem;
|
|
CPU_INT32U nbr_pkt;
|
|
CPU_INT32U ix;
|
|
|
|
|
|
if (buf_len < 2u) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBH_ERR_NULL_PTR;
|
|
return (0u);
|
|
}
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return (0u);
|
|
}
|
|
|
|
p_buf_cur08 = (CPU_INT08U *)p_buf;
|
|
/* Get max nbr of rx pkt allowed. */
|
|
nbr_pkt = 1u + ((buf_len - 1u) / p_ftdi_fnct->MaxPktSize);
|
|
|
|
(void)USBH_OS_MutexLock(p_ftdi_fnct->RxHMutex);
|
|
|
|
for (ix = 0u; ix < nbr_pkt; ix++) {
|
|
|
|
if (ix == 0u) { /* If first pkt. */
|
|
buf_len_cur = (nbr_pkt > 1u) ? p_ftdi_fnct->MaxPktSize : buf_len;
|
|
|
|
} else { /* Ensure rx buf is large enough for another pkt. */
|
|
if (buf_len < (xfer_len + p_ftdi_fnct->MaxPktSize)) {
|
|
buf_len_cur = (buf_len - xfer_len);
|
|
} else {
|
|
buf_len_cur = p_ftdi_fnct->MaxPktSize;
|
|
}
|
|
/* Save last two bytes of data. */
|
|
MEM_VAL_COPY_16(&data, (p_buf_cur08 - USBH_FTDI_SERIAL_STATUS_LEN));
|
|
|
|
if (p_serial_status != (void *)0) { /* Chk for line status error. */
|
|
if ((DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_RX_OVERFLOW_ERROR) == DEF_YES) ||
|
|
(DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_PARITY_ERROR) == DEF_YES) ||
|
|
(DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_FRAMING_ERROR) == DEF_YES)) {
|
|
|
|
MEM_VAL_COPY_16(p_buf, p_buf_cur08);
|
|
*p_err = USBH_ERR_FTDI_LINE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
p_buf_cur08 -= USBH_FTDI_SERIAL_STATUS_LEN;
|
|
}
|
|
/* Rx pkt through specified EP. */
|
|
xfer_len_cur = USBH_BulkRx( &p_ftdi_fnct->BulkInEP,
|
|
(void *)p_buf_cur08,
|
|
buf_len_cur,
|
|
timeout,
|
|
p_err);
|
|
if (*p_err != USBH_ERR_NONE) { /* Reset EP if err occurred. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
&p_ftdi_fnct->BulkInEP);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_ftdi_fnct->BulkInEP);
|
|
}
|
|
|
|
(void)USBH_OS_MutexUnlock(p_ftdi_fnct->RxHMutex);
|
|
|
|
return (0u);
|
|
}
|
|
|
|
if (ix == 0u) { /* If first pkt. */
|
|
xfer_len = xfer_len_cur;
|
|
} else {
|
|
xfer_len += (xfer_len_cur - USBH_FTDI_SERIAL_STATUS_LEN);
|
|
MEM_VAL_COPY_16(p_buf, p_buf_cur08); /* Update status. */
|
|
MEM_VAL_COPY_16(p_buf_cur08, &data); /* Restore two bytes of data. */
|
|
}
|
|
p_buf_cur08 += p_ftdi_fnct->MaxPktSize;
|
|
|
|
if (p_serial_status != (void *)0) {
|
|
p_serial_status->ModemStatus = *((CPU_INT08U *)p_buf);
|
|
p_serial_status->LineStatus = *((CPU_INT08U *)p_buf + 1u);
|
|
}
|
|
|
|
pkt_size_rem = ((xfer_len - USBH_FTDI_SERIAL_STATUS_LEN) % (p_ftdi_fnct->MaxPktSize - USBH_FTDI_SERIAL_STATUS_LEN));
|
|
if ((xfer_len_cur == USBH_FTDI_SERIAL_STATUS_LEN) || /* Stop transfer if RX size is smaller than maxPktSize. */
|
|
(pkt_size_rem != 0u)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
(void)USBH_OS_MutexUnlock(p_ftdi_fnct->RxHMutex);
|
|
|
|
return (xfer_len);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_RxAsync()
|
|
*
|
|
* Description : Receive data from FTDI device. This function is non blocking.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_buf Pointer to data buffer to hold received data.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* p_serial_status Pointer to USBH_FTDI_SERIAL_STATUS structure that will be filled by this function.
|
|
* This argument can be null.
|
|
*
|
|
* rx_cmpl_notify Function that will be invoked upon completion of receive operation.
|
|
*
|
|
* p_arg Pointer to argument that will be passed as parameter of 'rx_cmpl_notify'.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, If data successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'/
|
|
* 'buf_len'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
* USBH_ERR_NULL_PTR, Invalid null pointer passed to 'p_buf'.
|
|
*
|
|
* ----- RETURNED BY USBH_BulkRxAsync() : -----
|
|
* USBH_ERR_NONE, If request is successfully submitted.
|
|
* USBH_ERR_INVALID_ARG, If invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE, If endpoint type is not Bulk or direction is
|
|
* not IN.
|
|
* USBH_ERR_EP_INVALID_STATE, If endpoint is not opened.
|
|
* USBH_ERR_ALLOC, If URB cannot be allocated.
|
|
* USBH_ERR_UNKNOWN, If unknown error occured.
|
|
* Host controller drivers error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : (1) The following masks may be used to determine if a bit of the modem status is set:
|
|
*
|
|
* USBH_FTDI_MODEM_STATUS_FS
|
|
* USBH_FTDI_MODEM_STATUS_HS
|
|
* USBH_FTDI_MODEM_STATUS_CLEAR_TO_SEND
|
|
* USBH_FTDI_MODEM_STATUS_DATA_SET_READY
|
|
* USBH_FTDI_MODEM_STATUS_RING_INDICATOR
|
|
* USBH_FTDI_MODEM_STATUS_DATA_CARRIER_DETECT
|
|
*
|
|
* (2) The following masks may be used to determine if a bit of the line status is set:
|
|
*
|
|
* USBH_FTDI_LINE_STATUS_RX_OVERFLOW_ERROR
|
|
* USBH_FTDI_LINE_STATUS_PARITY_ERROR
|
|
* USBH_FTDI_LINE_STATUS_FRAMING_ERROR
|
|
* USBH_FTDI_LINE_STATUS_BREAK_INTERRUPT
|
|
* USBH_FTDI_LINE_STATUS_TX_REGISTER_EMPTY
|
|
* USBH_FTDI_LINE_STATUS_TX_EMPTY
|
|
*
|
|
* (3) Asynchronous receive is not thread safe. Hence, it is not safe to call this function
|
|
* from more than 1 application task at the same time for the same device. It is however
|
|
* safe to call it from the completion callback.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBH_FTDI_RxAsync (USBH_FTDI_HANDLE ftdi_handle,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
USBH_FTDI_SERIAL_STATUS *p_serial_status,
|
|
USBH_FTDI_ASYNC_RX_FNCT rx_cmpl_notify,
|
|
void *p_arg,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
|
|
|
|
if (buf_len < 2u) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBH_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct->DataRxNotifyPtr = rx_cmpl_notify;
|
|
p_ftdi_fnct->DataRxNotifyArgPtr = p_arg;
|
|
p_ftdi_fnct->DataRxBuf = p_buf;
|
|
p_ftdi_fnct->RxBufLen = buf_len;
|
|
p_ftdi_fnct->SerialStatusPtr = p_serial_status;
|
|
p_ftdi_fnct->XferLen = 0u;
|
|
|
|
if (buf_len > p_ftdi_fnct->MaxPktSize) {
|
|
buf_len = p_ftdi_fnct->MaxPktSize;
|
|
}
|
|
|
|
*p_err = USBH_BulkRxAsync( &p_ftdi_fnct->BulkInEP, /* Rx first pkt through specified EP. */
|
|
p_buf,
|
|
buf_len,
|
|
USBH_FTDI_DataRxCmpl,
|
|
(void *)p_ftdi_fnct);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
&p_ftdi_fnct->BulkInEP);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_ftdi_fnct->BulkInEP);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_DevGet()
|
|
*
|
|
* Description : Retrieves the device informations.
|
|
*
|
|
* Argument(s) : ftdi_handle Handle on FTDI device.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, If device informations retrieved successfully.
|
|
* USBH_ERR_INVALID_ARG Invalid argument passed to 'ftdi_handle'
|
|
*
|
|
* Return(s) : Pointer to FTDI device.
|
|
*
|
|
* Note(s) : None.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
USBH_DEV *USBH_FTDI_DevGet (USBH_FTDI_HANDLE ftdi_handle,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
|
|
|
|
*p_err = USBH_ERR_NONE;
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return ((USBH_DEV *)0);
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return ((USBH_DEV *)0);
|
|
}
|
|
|
|
return(p_ftdi_fnct->DevPtr);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_GlobalInit()
|
|
*
|
|
* Description : Not used but it has to be called by the host stack.
|
|
*
|
|
* Argument(s) : p_err Returns 'USBH_ERR_NONE'.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_GlobalInit (USBH_ERR *p_err)
|
|
{
|
|
*p_err = USBH_ERR_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_ProbeIF()
|
|
*
|
|
* Description : Determine if the interface is FTDI class interface.
|
|
*
|
|
* Argument(s) : p_dev Pointer to USB device.
|
|
*
|
|
* p_if Pointer to interface.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
* USBH_ERR_NONE, Interface is of FTDI type.
|
|
* USBH_ERR_DEV_ALLOC, Cannot allocate FTDI device.
|
|
* USBH_ERR_CLASS_DRV_NOT_FOUND, Interface is not of FTDI type.
|
|
*
|
|
* ----- RETURNED BY USBH_IF_DescGet() : -----
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'alt_ix'.
|
|
*
|
|
* ----- RETURNED BY USBH_BulkInOpen() : -----
|
|
* USBH_ERR_EP_ALLOC, If USBH_CFG_MAX_NBR_EPS reached.
|
|
* USBH_ERR_EP_NOT_FOUND, If endpoint with given type and direction not found.
|
|
* USBH_ERR_OS_SIGNAL_CREATE, if mutex or semaphore creation failed.
|
|
* Host controller drivers error, Otherwise.
|
|
*
|
|
* ----- RETURNED BY USBH_BulkOutOpen() : -----
|
|
* USBH_ERR_EP_ALLOC, If USBH_CFG_MAX_NBR_EPS reached.
|
|
* USBH_ERR_EP_NOT_FOUND, If endpoint with given type and direction not found.
|
|
* USBH_ERR_OS_SIGNAL_CREATE, if mutex or semaphore creation failed.
|
|
* Host controller drivers error Otherwise.
|
|
*
|
|
* Return(s) : p_ftdi_dev, If device has a FTDI class interface.
|
|
* 0 Otherwise.
|
|
*
|
|
* Note(s) : (1) The 'bInterfaceClass' field of a FTDI device is 'Vendor Specific'. So, the 'Vendor ID'
|
|
* and the 'Product ID' must be parsed as well to ensure connected device is FTDI.
|
|
*
|
|
* (2) The port number is determined by increasing 'USBH_FTDI_PortCnt' every time a device
|
|
* with the same address is probed. If a new device is connected, this counter is reset
|
|
* to '0'.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void *USBH_FTDI_ProbeIF (USBH_DEV *p_dev,
|
|
USBH_IF *p_if,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
USBH_DEV_DESC dev_desc;
|
|
USBH_IF_DESC if_desc;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
*p_err = USBH_IF_DescGet(p_if, 0u, &if_desc); /* Get IF desc from IF. */
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return ((void *)0);
|
|
}
|
|
|
|
USBH_DevDescGet(p_dev, &dev_desc); /* Get dev desc. */
|
|
|
|
/* bInterfaceClass must be Vendor Specific. */
|
|
if (if_desc.bInterfaceClass != USBH_CLASS_CODE_VENDOR_SPECIFIC) {
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)0;
|
|
*p_err = USBH_ERR_CLASS_DRV_NOT_FOUND;
|
|
/* idVendor must be FTDI or burned Vendor ID. */
|
|
} else if ((dev_desc.idVendor != USBH_FTDI_ID_VENDOR) &&
|
|
(dev_desc.idVendor != USBH_FTDI_CFG_ID_VENDOR_CUSTOM)) {
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)0;
|
|
*p_err = USBH_ERR_CLASS_DRV_NOT_FOUND;
|
|
/* idProduct must be FT8U232AM, FT232B, FT2232D, FT232R,*/
|
|
/* FT2232H, FT4232H, FT232H or burned Product ID. */
|
|
} else if ((dev_desc.idProduct != USBH_FTDI_ID_PRODUCT_FT232R) &&
|
|
(dev_desc.idProduct != USBH_FTDI_ID_PRODUCT_FT2232D) &&
|
|
(dev_desc.idProduct != USBH_FTDI_ID_PRODUCT_FT4232H) &&
|
|
(dev_desc.idProduct != USBH_FTDI_ID_PRODUCT_FT232H) &&
|
|
(dev_desc.idProduct != USBH_FTDI_CFG_ID_PRODUCT_CUSTOM)) {
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)0;
|
|
*p_err = USBH_ERR_CLASS_DRV_NOT_FOUND;
|
|
|
|
} else {
|
|
/* Alloc a dev from FTDI fnct pool. */
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)Mem_PoolBlkGet(&USBH_FTDI_DevPool,
|
|
sizeof(USBH_FTDI_FNCT),
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBH_ERR_DEV_ALLOC;
|
|
return ((void *)0);
|
|
}
|
|
|
|
p_ftdi_fnct->State = USBH_CLASS_DEV_STATE_CONN;
|
|
p_ftdi_fnct->DevPtr = p_dev;
|
|
p_ftdi_fnct->IF_Ptr = p_if;
|
|
|
|
if (USBH_FTDI_DevPtrPrev == p_dev) { /* Determine serial port of actual IF. See note (2). */
|
|
USBH_FTDI_PortCnt++;
|
|
p_ftdi_fnct->Port = USBH_FTDI_PortCnt;
|
|
} else {
|
|
p_ftdi_fnct->Port = 0u;
|
|
USBH_FTDI_PortCnt = 1u;
|
|
}
|
|
USBH_FTDI_DevPtrPrev = p_dev;
|
|
|
|
*p_err = USBH_BulkInOpen(p_ftdi_fnct->DevPtr, /* Open Bulk IN EP. */
|
|
p_ftdi_fnct->IF_Ptr,
|
|
&p_ftdi_fnct->BulkInEP);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
USBH_FTDI_Disconn(p_ftdi_fnct);
|
|
|
|
return ((void *)0);
|
|
}
|
|
|
|
p_ftdi_fnct->MaxPktSize = (CPU_INT32U)USBH_EP_MaxPktSizeGet(&p_ftdi_fnct->BulkInEP);
|
|
|
|
*p_err = USBH_BulkOutOpen(p_ftdi_fnct->DevPtr, /* Open Bulk OUT EP. */
|
|
p_ftdi_fnct->IF_Ptr,
|
|
&p_ftdi_fnct->BulkOutEP);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
USBH_FTDI_Disconn(p_ftdi_fnct);
|
|
|
|
return ((void *)0);
|
|
}
|
|
}
|
|
|
|
return ((void *)p_ftdi_fnct);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Suspend()
|
|
*
|
|
* Description : Suspend FTDI device.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to FTDI device.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_Suspend (void *p_class_dev)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_class_dev;
|
|
|
|
p_ftdi_fnct->State = USBH_CLASS_DEV_STATE_SUSPEND;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Resume()
|
|
*
|
|
* Description : Resume FTDI device.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to FTDI device.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_Resume (void *p_class_dev)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_class_dev;
|
|
|
|
p_ftdi_fnct->State = USBH_CLASS_DEV_STATE_CONN;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_Disconn()
|
|
*
|
|
* Description : Handle disconnection of FTDI device.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to FTDI device.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_Disconn (void *p_class_dev)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_class_dev;
|
|
|
|
(void)USBH_EP_Close(&p_ftdi_fnct->BulkInEP); /* Close bulk EPs. */
|
|
(void)USBH_EP_Close(&p_ftdi_fnct->BulkOutEP);
|
|
|
|
p_ftdi_fnct->State = USBH_CLASS_DEV_STATE_DISCONN;
|
|
|
|
if (USBH_FTDI_DevPtrPrev == p_ftdi_fnct->DevPtr) {
|
|
USBH_FTDI_DevPtrPrev = (USBH_DEV *)0;
|
|
}
|
|
USBH_FTDI_PortCnt = 0u;
|
|
|
|
Mem_PoolBlkFree( &USBH_FTDI_DevPool,
|
|
(void *)p_ftdi_fnct,
|
|
&err_lib);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_ClassDevNotify()
|
|
*
|
|
* Description : Handle device state change notification.
|
|
*
|
|
* Argument(s) : p_class_dev, Pointer to FTDI device.
|
|
*
|
|
* state, State of the FTDI device.
|
|
*
|
|
* p_ctx Pointer to FTDI functions.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_ClassDevNotify (void *p_class_dev,
|
|
CPU_INT08U state,
|
|
void *p_ctx)
|
|
{
|
|
USBH_FTDI_CALLBACKS *p_ftdi_callbacks;
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
|
|
|
|
p_ftdi_callbacks = (USBH_FTDI_CALLBACKS *)p_ctx;
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_class_dev;
|
|
|
|
switch (state) {
|
|
case USBH_CLASS_DEV_STATE_CONN:
|
|
p_ftdi_callbacks->ConnNotifyPtr(p_ftdi_fnct->Handle);
|
|
break;
|
|
|
|
|
|
case USBH_CLASS_DEV_STATE_DISCONN:
|
|
p_ftdi_callbacks->DisconnNotifyPtr(p_ftdi_fnct->Handle);
|
|
break;
|
|
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_StdReq()
|
|
*
|
|
* Description : Send standard FTDI control request to device.
|
|
*
|
|
* Argument(s) : ftdi_handle, Pointer to FTDI device.
|
|
*
|
|
* request, FTDI control request type.
|
|
*
|
|
* value, Value of the wValue field.
|
|
*
|
|
* h_index, High-Byte value of the wIndex field.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE, Control transfer successfully transmitted.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'ftdi_handle'.
|
|
* USBH_ERR_DEV_NOT_READY, Device is not ready.
|
|
*
|
|
* ----- RETURNED BY USBH_CtrlTx() : -----
|
|
* USBH_ERR_NONE, Control transfer successfully completed.
|
|
* USBH_ERR_UNKNOWN, Unknown error occurred.
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_STATE, Endpoint is not opened.
|
|
* USBH_ERR_HC_IO, Root hub input/output error.
|
|
* USBH_ERR_EP_STALL, Root hub does not support request.
|
|
* Host controller drivers error code Otherwise.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_StdReq (USBH_FTDI_HANDLE ftdi_handle,
|
|
CPU_INT08U request,
|
|
CPU_INT16U value,
|
|
CPU_INT08U h_index,
|
|
USBH_ERR *p_err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U ftdi_ix;
|
|
CPU_INT16U index;
|
|
|
|
|
|
ftdi_ix = USBH_FTDI_HANDLE_IX_GET(ftdi_handle);
|
|
if (ftdi_ix >= USBH_FTDI_CFG_MAX_DEV) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
p_ftdi_fnct = &USBH_FTDI_DevTbl[ftdi_ix];
|
|
if (p_ftdi_fnct->DevPtr == (void *)0) {
|
|
*p_err = USBH_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if (p_ftdi_fnct->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
*p_err = USBH_ERR_DEV_NOT_READY;
|
|
return;
|
|
}
|
|
|
|
index = (CPU_INT16U)(((CPU_INT16U)h_index << 8u) | p_ftdi_fnct->Port);
|
|
|
|
(void)USBH_CtrlTx( p_ftdi_fnct->DevPtr, /* Send ctrl req. */
|
|
request,
|
|
(USBH_REQ_DIR_HOST_TO_DEV | USBH_REQ_TYPE_VENDOR | USBH_REQ_RECIPIENT_DEV),
|
|
value,
|
|
index,
|
|
(void *)0,
|
|
0u,
|
|
USBH_CFG_STD_REQ_TIMEOUT,
|
|
p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_DataTxCmpl()
|
|
*
|
|
* Description : Asynchronous data transfer completion function.
|
|
*
|
|
* Argument(s) : p_ep Pointer to endpoint.
|
|
*
|
|
* p_buf Pointer to transmit buffer.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* xfer_len Number of octets transferred.
|
|
*
|
|
* p_arg Asynchronous function argument.
|
|
*
|
|
* err Status of transaction.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_DataTxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_arg;
|
|
|
|
if (err != USBH_ERR_NONE) { /* Chk status of transaction. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
p_ep);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(p_ep);
|
|
}
|
|
}
|
|
|
|
p_ftdi_fnct->DataTxNotifyPtr(p_ftdi_fnct->Handle, /* Notify the app. */
|
|
p_ftdi_fnct->DataTxNotifyArgPtr,
|
|
p_buf,
|
|
xfer_len,
|
|
err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_FTDI_DataRxCmpl()
|
|
*
|
|
* Description : Asynchronous data receive completion function.
|
|
*
|
|
* Argument(s) : p_ep Pointer to endpoint.
|
|
*
|
|
* p_buf Pointer to transmit buffer.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* xfer_len Number of octets transferred.
|
|
*
|
|
* p_arg Asynchronous function argument.
|
|
*
|
|
* err Status of transaction.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : (1) The received data in 'p_buf' is in little-endian.
|
|
*
|
|
* (2) The FTDI device always add a status of two bytes at the beginning of every packet.
|
|
* This function manage those status bytes in order to get the latest status followed
|
|
* by the data in 'p_buf'.
|
|
* This only applies when the application requests more than max packet size (MPS) - 2 bytes of data.
|
|
*
|
|
* +----+----+----+----+-----+---------+---------+-----+-----
|
|
* (a) Receive first pkt in buffer. | S0 | S1 | D0 | D1 | ... | MPS - 2 | MPS - 1 | MPS | ...
|
|
* +----+----+----+----+-----+---------+---------+-----+-----
|
|
* | |
|
|
* v v
|
|
* +---------+-----+
|
|
* (b) Save the last two bytes of data. | MPS - 1 | MPS |
|
|
* +---------+-----+
|
|
*
|
|
* +----+----+----+----+-----+---------+-----+-----+---------+---------+-----
|
|
* (c) Receive next pkt in buffer. | S0 | S1 | D0 | D1 | ... | MPS - 2 | S2 | S3 | MPS + 1 | MPS + 2 | ...
|
|
* +----+----+----+----+-----+---------+-----+-----+---------+---------+-----
|
|
*
|
|
* +----+----+----+----+-----+---------+---------+-----+---------+---------+-----
|
|
* (d) Update the status. | S2 | S3 | D0 | D1 | ... | MPS - 2 | S2 | S3 | MPS + 1 | MPS + 2 | ...
|
|
* +----+----+----+----+-----+---------+---------+-----+---------+---------+-----
|
|
* ^ ^
|
|
* | |
|
|
* +---------+-----+
|
|
* (e) Restore the two bytes of data. | MPS - 1 | MPS |
|
|
* +---------+-----+
|
|
*
|
|
* (f) Repeat step (b) to (e) until the end of the buffer is reached or the last transfer size is
|
|
* smaller than maxPktSize.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_FTDI_DataRxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err)
|
|
{
|
|
USBH_FTDI_FNCT *p_ftdi_fnct;
|
|
CPU_INT08U *p_buf_cur;
|
|
CPU_INT32U rem_buf_size;
|
|
USBH_FTDI_SERIAL_STATUS *p_serial_status;
|
|
|
|
|
|
p_ftdi_fnct = (USBH_FTDI_FNCT *)p_arg;
|
|
|
|
if (err == USBH_ERR_NONE) {
|
|
p_serial_status = p_ftdi_fnct->SerialStatusPtr;
|
|
p_buf_cur = (CPU_INT08U *)p_buf;
|
|
|
|
if (p_serial_status != (void *)0) {
|
|
p_serial_status->ModemStatus = *(p_buf_cur);
|
|
p_serial_status->LineStatus = *(p_buf_cur + 1u);
|
|
/* Chk line status. */
|
|
if ((DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_RX_OVERFLOW_ERROR) == DEF_YES) ||
|
|
(DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_PARITY_ERROR) == DEF_YES) ||
|
|
(DEF_BIT_IS_SET(p_serial_status->LineStatus, USBH_FTDI_LINE_STATUS_FRAMING_ERROR) == DEF_YES)) {
|
|
|
|
MEM_VAL_COPY_16(p_ftdi_fnct->DataRxBuf, p_buf_cur);
|
|
err = USBH_ERR_FTDI_LINE;
|
|
}
|
|
}
|
|
} else { /* Chk status of transaction. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
p_ep);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(p_ep);
|
|
}
|
|
}
|
|
|
|
if (err == USBH_ERR_NONE) { /* Organize data to get last two bytes status followed */
|
|
/* by raw data rx'd. */
|
|
if (p_ftdi_fnct->XferLen > (p_ftdi_fnct->MaxPktSize - 1u)) {
|
|
MEM_VAL_COPY_16(p_ftdi_fnct->DataRxBuf, p_buf_cur); /* Update status. */
|
|
MEM_VAL_COPY_16(p_buf_cur, &p_ftdi_fnct->LastBytes);/* Restore two bytes of data. */
|
|
p_ftdi_fnct->XferLen += (xfer_len - USBH_FTDI_SERIAL_STATUS_LEN);
|
|
|
|
} else {
|
|
p_ftdi_fnct->XferLen += xfer_len;
|
|
}
|
|
|
|
p_buf_cur += p_ftdi_fnct->MaxPktSize;
|
|
rem_buf_size = (p_ftdi_fnct->RxBufLen - p_ftdi_fnct->XferLen);
|
|
|
|
if ((xfer_len == p_ftdi_fnct->MaxPktSize) &&
|
|
(p_ftdi_fnct->MaxPktSize <= rem_buf_size)) {
|
|
/* Save last two bytes of data. */
|
|
MEM_VAL_COPY_16(&p_ftdi_fnct->LastBytes, (p_buf_cur - USBH_FTDI_SERIAL_STATUS_LEN));
|
|
/* Req following pkt. */
|
|
err = USBH_BulkRxAsync( &p_ftdi_fnct->BulkInEP,
|
|
(p_buf_cur - USBH_FTDI_SERIAL_STATUS_LEN),
|
|
buf_len,
|
|
USBH_FTDI_DataRxCmpl,
|
|
(void *)p_ftdi_fnct);
|
|
if (err != USBH_ERR_NONE) { /* Reset EP if an err occurred. */
|
|
(void)USBH_EP_Reset(p_ftdi_fnct->DevPtr,
|
|
&p_ftdi_fnct->BulkOutEP);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_ftdi_fnct->BulkOutEP);
|
|
}
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
p_ftdi_fnct->DataRxNotifyPtr(p_ftdi_fnct->Handle, /* Notify the app. */
|
|
p_ftdi_fnct->DataRxNotifyArgPtr,
|
|
p_ftdi_fnct->DataRxBuf,
|
|
p_ftdi_fnct->XferLen,
|
|
p_ftdi_fnct->SerialStatusPtr,
|
|
err);
|
|
}
|
|
|
|
|