1426 lines
52 KiB
C
1426 lines
52 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.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*
|
|
* COMMUNICATIONS DEVICE CLASS (CDC)
|
|
*
|
|
* Filename : usbh_cdc.c
|
|
* Version : V3.42.01
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_CDC_MODULE
|
|
#define MICRIUM_SOURCE
|
|
#include "usbh_cdc.h"
|
|
#include "../../Source/usbh_core.h"
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* UNION DESCRIPTOR DATA TYPE
|
|
*
|
|
* Note(s) : (1) See 'USB Class Definitions for Communication Devices Revision 1.1', Section 5.2.3.8, Table 33.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbh_cdc_union_desc {
|
|
CPU_INT08U bFunctionLength; /* Size of desc in bytes. */
|
|
CPU_INT08U bDescriptorType; /* IF desc type. */
|
|
CPU_INT08U bDescriptorSubtype; /* Union functional desc subtype. */
|
|
CPU_INT08U bMasterInterface; /* Nbr of comm or Data Class IF, designated as master. */
|
|
CPU_INT08U bSlaveInterface0; /* IF nbr of first slave or associated IF in union. */
|
|
} USBH_CDC_UNION_DESC;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL TABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_CDC_DEV USBH_CDC_DevArr[USBH_CDC_CFG_MAX_DEV];
|
|
static MEM_POOL USBH_CDC_DevPool;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_GlobalInit (USBH_ERR *p_err);
|
|
|
|
static void *USBH_CDC_ProbeDev (USBH_DEV *p_dev,
|
|
USBH_ERR *p_err);
|
|
|
|
static USBH_ERR USBH_CDC_EP_Open (USBH_CDC_DEV *p_cdc_dev);
|
|
|
|
static USBH_ERR USBH_CDC_UnionDescParse (USBH_CDC_UNION_DESC *p_union_desc,
|
|
USBH_IF *p_if);
|
|
|
|
static void USBH_CDC_Suspend (void *p_class_dev);
|
|
|
|
static void USBH_CDC_Resume (void *p_class_dev);
|
|
|
|
static void USBH_CDC_Disconn (void *p_class_dev);
|
|
|
|
static void USBH_CDC_DIC_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_CDC_DIC_DataRxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err);
|
|
|
|
static USBH_ERR USBH_CDC_EventRxAsync (USBH_CDC_DEV *p_cdc_dev);
|
|
|
|
static void USBH_CDC_CIC_EventRxCmpl(USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONFIGURATION ERRORS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* CDC CLASS DRIVER
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_CLASS_DRV USBH_CDC_ClassDrv = {
|
|
(CPU_INT08U *)"CDC",
|
|
USBH_CDC_GlobalInit,
|
|
USBH_CDC_ProbeDev,
|
|
0,
|
|
USBH_CDC_Suspend,
|
|
USBH_CDC_Resume,
|
|
USBH_CDC_Disconn
|
|
};
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_RefAdd()
|
|
*
|
|
* Description : Increment application reference count to CDC device.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if reference added successfully.
|
|
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_cdc_dev'.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_RefAdd (USBH_CDC_DEV *p_cdc_dev)
|
|
{
|
|
if (p_cdc_dev == (USBH_CDC_DEV *)0) {
|
|
return (USBH_ERR_INVALID_ARG);
|
|
}
|
|
|
|
(void)USBH_OS_MutexLock(p_cdc_dev->HMutex);
|
|
p_cdc_dev->RefCnt++; /* Increment app ref cnt to CDC dev. */
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_RefRel()
|
|
*
|
|
* Description : Decrement application reference count to CDC device. Free device if there is no more
|
|
* reference to it.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if reference released successfully.
|
|
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_cdc_dev'.
|
|
* USBH_ERR_FREE, if device not successfully freed.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_RefRel (USBH_CDC_DEV *p_cdc_dev)
|
|
{
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
if (p_cdc_dev == (USBH_CDC_DEV *)0) {
|
|
return (USBH_ERR_INVALID_ARG);
|
|
}
|
|
|
|
(void)USBH_OS_MutexLock(p_cdc_dev->HMutex);
|
|
|
|
if (p_cdc_dev->RefCnt > 0) {
|
|
p_cdc_dev->RefCnt--;
|
|
|
|
if ((p_cdc_dev->RefCnt == 0u) &&
|
|
(p_cdc_dev->State == USBH_CLASS_DEV_STATE_DISCONN)) {
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
|
|
Mem_PoolBlkFree( &USBH_CDC_DevPool,
|
|
(void *)p_cdc_dev,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
return (USBH_ERR_FREE);
|
|
} else {
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
}
|
|
}
|
|
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_EvtNotifyReg()
|
|
*
|
|
* Description : Register application / subclass event callback functions.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_evt_notify Pointer to application's / sublasse's notify function.
|
|
*
|
|
* Return(s) : USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_cdc_dev' / 'p_evt_notify'.
|
|
*
|
|
* ---- RETURNED BY USBH_CDC_EventRxAsync ----
|
|
* USBH_ERR_INVALID_ARG If invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE If endpoint type is not interrupt 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_EventNotifyReg (USBH_CDC_DEV *p_cdc_dev,
|
|
SUBCLASS_NOTIFY p_evt_notify,
|
|
void *p_arg)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
if ((p_cdc_dev == (USBH_CDC_DEV *)0) ||
|
|
(p_evt_notify == (SUBCLASS_NOTIFY)0)) {
|
|
return (USBH_ERR_INVALID_ARG);
|
|
}
|
|
|
|
p_cdc_dev->EvtNotifyPtr = p_evt_notify; /* Reg callback fnct provided by subclass. */
|
|
p_cdc_dev->EvtNotifyArgPtr = p_arg;
|
|
|
|
err = USBH_CDC_EventRxAsync(p_cdc_dev);
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_CmdTx()
|
|
*
|
|
* Description : Send CDC control command.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* b_req One-byte value that specifies request.
|
|
*
|
|
* bm_req_type One-byte value that specifies direction, type and the recipient of
|
|
* request.
|
|
*
|
|
* w_val Two-byte value used to pass information to device.
|
|
*
|
|
* p_buf Pointer to data buffer to transmit.
|
|
*
|
|
* buf_len Two-byte value containing buffer length in octets.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if control command successfully sent.
|
|
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_cdc_dev'.
|
|
* USBH_ERR_DEV_NOT_READY, if device is not connected.
|
|
*
|
|
* ----- RETURNED BY USBH_CtrlTx() : -----
|
|
* 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_CmdTx (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U b_req,
|
|
CPU_INT08U bm_req_type,
|
|
CPU_INT16U w_val,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
if (p_cdc_dev == (USBH_CDC_DEV *)0) {
|
|
return (USBH_ERR_INVALID_ARG);
|
|
}
|
|
|
|
if (p_cdc_dev->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
return (USBH_ERR_DEV_NOT_READY);
|
|
}
|
|
|
|
USBH_CtrlTx(p_cdc_dev->DevPtr, /* Issue req to dev. */
|
|
b_req,
|
|
bm_req_type,
|
|
w_val,
|
|
p_cdc_dev->CIC_IF_Nbr,
|
|
p_buf,
|
|
buf_len,
|
|
USBH_CFG_STD_REQ_TIMEOUT,
|
|
&err);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset( p_cdc_dev->DevPtr,
|
|
(USBH_EP *)0);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_RespRx()
|
|
*
|
|
* Description : Send CDC control rx request.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* b_req One-byte value that specifies request.
|
|
*
|
|
* bm_req_type One-byte value that specifies direction, type and the recipient of
|
|
* request.
|
|
*
|
|
* w_val Two-byte value used to pass information to device.
|
|
*
|
|
* p_buf Pointer to data buffer to hold received data.
|
|
*
|
|
* buf_len Two-byte value containing buffer length in octets.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if control command successfully received.
|
|
* USBH_ERR_INVALID_ARG, if invalid argument passed to 'p_cdc_dev'.
|
|
* USBH_ERR_DEV_NOT_READY, if device is not connected.
|
|
*
|
|
* ----- RETURNED BY USBH_CtrlRx() : -----
|
|
* 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_RespRx (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U b_req,
|
|
CPU_INT08U bm_req_type,
|
|
CPU_INT16U w_val,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
if (p_cdc_dev == (USBH_CDC_DEV *)0) {
|
|
return (USBH_ERR_INVALID_ARG);
|
|
}
|
|
|
|
if (p_cdc_dev->State != USBH_CLASS_DEV_STATE_CONN) {
|
|
return (USBH_ERR_DEV_NOT_READY);
|
|
}
|
|
|
|
USBH_CtrlRx(p_cdc_dev->DevPtr,
|
|
b_req,
|
|
bm_req_type,
|
|
w_val,
|
|
p_cdc_dev->CIC_IF_Nbr,
|
|
p_buf,
|
|
buf_len,
|
|
USBH_CFG_STD_REQ_TIMEOUT,
|
|
&err);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset( p_cdc_dev->DevPtr,
|
|
(USBH_EP *)0);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DataTx()
|
|
*
|
|
* Description : Transfer raw buffer to device.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_buf Pointer to buffer of data that will be sent.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* ----- 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.
|
|
* USBH_ERR_NONE, URB is successfully submitted to host controller.
|
|
* Host controller drivers error code, Otherwise.
|
|
*
|
|
* Return(s) : Number of octets transferred.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT32U USBH_CDC_DataTx (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_buf,
|
|
CPU_INT32U buf_len,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_INT32U xfer_len;
|
|
|
|
|
|
xfer_len = USBH_BulkTx( &p_cdc_dev->DIC_BulkOut,
|
|
(void *)p_buf,
|
|
buf_len,
|
|
0u,
|
|
p_err);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
&p_cdc_dev->DIC_BulkOut);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
USBH_EP_StallClr(&p_cdc_dev->DIC_BulkOut);
|
|
}
|
|
|
|
return (0u);
|
|
}
|
|
|
|
return (xfer_len);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DataTxAsync()
|
|
*
|
|
* Description : Transfer raw buffer to device asynchronously.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC 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'.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if data successfully transmitted.
|
|
*
|
|
* ----- 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_DataTxAsync (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_buf,
|
|
CPU_INT32U buf_len,
|
|
SUBCLASS_NOTIFY tx_cmpl_notify,
|
|
void *p_arg)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
p_cdc_dev->DataTxNotifyPtr = tx_cmpl_notify;
|
|
p_cdc_dev->DataTxNotifyArgPtr = p_arg;
|
|
|
|
err = USBH_BulkTxAsync( &p_cdc_dev->DIC_BulkOut,
|
|
(void *)p_buf,
|
|
buf_len,
|
|
USBH_CDC_DIC_DataTxCmpl,
|
|
(void *)p_cdc_dev);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
&p_cdc_dev->DIC_BulkOut);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_cdc_dev->DIC_BulkOut);
|
|
}
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DataRx()
|
|
*
|
|
* Description : Receive raw data from device.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_buf Pointer to data buffer to hold received data.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* ----- 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.
|
|
* USBH_ERR_NONE, URB is successfully submitted to host controller.
|
|
* Host controller drivers error code, Otherwise.
|
|
*
|
|
* Return(s) : Number of octets received.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT32U USBH_CDC_DataRx (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_buf,
|
|
CPU_INT32U buf_len,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_INT32U xfer_len;
|
|
|
|
|
|
xfer_len = USBH_BulkRx( &p_cdc_dev->DIC_BulkIn,
|
|
(void *)p_buf,
|
|
buf_len,
|
|
0u,
|
|
p_err);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
&p_cdc_dev->DIC_BulkIn);
|
|
|
|
if (*p_err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_cdc_dev->DIC_BulkIn);
|
|
}
|
|
|
|
return (0u);
|
|
}
|
|
|
|
return (xfer_len);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DataRxAsync()
|
|
*
|
|
* Description : Receive raw data from device asynchronously.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_buf Pointer to data buffer to hold received data.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* 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 'tx_cmpl_notify'.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if data successfully received.
|
|
*
|
|
* ----- 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_DataRxAsync (USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_buf,
|
|
CPU_INT32U buf_len,
|
|
SUBCLASS_NOTIFY rx_cmpl_notify,
|
|
void *p_arg)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
p_cdc_dev->DataRxNotifyPtr = rx_cmpl_notify;
|
|
p_cdc_dev->DataRxNotifyArgPtr = p_arg;
|
|
|
|
err = USBH_BulkRxAsync( &p_cdc_dev->DIC_BulkIn,
|
|
(void *)p_buf,
|
|
buf_len,
|
|
USBH_CDC_DIC_DataRxCmpl,
|
|
(void *)p_cdc_dev);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
&p_cdc_dev->DIC_BulkIn);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_cdc_dev->DIC_BulkIn);
|
|
}
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_EventRxAsync()
|
|
*
|
|
* Description : Receive serial state of device.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to the CDC device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if data successfully received.
|
|
*
|
|
* ----- RETURNED BY USBH_IntrRxAsync() : -----
|
|
* USBH_ERR_INVALID_ARG If invalid argument passed to 'p_ep'.
|
|
* USBH_ERR_EP_INVALID_TYPE If endpoint type is not interrupt 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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_CDC_EventRxAsync (USBH_CDC_DEV *p_cdc_dev)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
err = USBH_IntrRxAsync( &p_cdc_dev->CIC_IntrIn,
|
|
(void *)p_cdc_dev->EventNotifyBuf,
|
|
USBH_CDC_LEN_EVENT_BUF,
|
|
USBH_CDC_CIC_EventRxCmpl,
|
|
(void *)p_cdc_dev);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
&p_cdc_dev->CIC_IntrIn);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(&p_cdc_dev->CIC_IntrIn);
|
|
}
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_CommIF_Get()
|
|
*
|
|
* Description : Get pointer to communication interface.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : Pointer to communication interface.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_IF *USBH_CDC_CommIF_Get (USBH_CDC_DEV *p_cdc_dev)
|
|
{
|
|
return (p_cdc_dev->CIC_IF_Ptr);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_SubclassGet()
|
|
*
|
|
* Description : Get subclass code.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_subclass Pointer to variable that will receive subclass code.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if subclass code successfully fetched.
|
|
*
|
|
* ----- RETURNED BY USBH_IF_DescGet() : -----
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'alt_ix'.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_SubclassGet(USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_subclass)
|
|
{
|
|
USBH_IF_DESC if_desc;
|
|
USBH_ERR err;
|
|
|
|
|
|
err = USBH_IF_DescGet(p_cdc_dev->CIC_IF_Ptr,
|
|
0u,
|
|
&if_desc);
|
|
if (err != USBH_ERR_NONE) {
|
|
*p_subclass = 0u;
|
|
return (err);
|
|
}
|
|
|
|
*p_subclass = if_desc.bInterfaceSubClass;
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_ProtocolGet()
|
|
*
|
|
* Description : Get protocol code.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* p_protocol Pointer to variable that will receive protocol code.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if protocol code successfully fetched.
|
|
*
|
|
* ----- RETURNED BY USBH_IF_DescGet() : -----
|
|
* USBH_ERR_INVALID_ARG, Invalid argument passed to 'alt_ix'.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_CDC_ProtocolGet(USBH_CDC_DEV *p_cdc_dev,
|
|
CPU_INT08U *p_protocol)
|
|
{
|
|
USBH_IF_DESC if_desc;
|
|
USBH_ERR err;
|
|
|
|
|
|
err = USBH_IF_DescGet(p_cdc_dev->CIC_IF_Ptr,
|
|
0u,
|
|
&if_desc);
|
|
if (err != USBH_ERR_NONE) {
|
|
*p_protocol = 0u;
|
|
return (err);
|
|
}
|
|
|
|
*p_protocol = if_desc.bInterfaceProtocol;
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_GlobalInit()
|
|
*
|
|
* Description : Initialize the internal variables and structure required by CDC.
|
|
*
|
|
* Argument(s) : p_err Variable that will receive the return error code from this function.
|
|
* USBH_ERR_NONE, Initialization was succesfull.
|
|
* USBH_ERR_ALLOC, Memory pool creation failed.
|
|
*
|
|
* ----- RETURNED BY USBH_OS_MutexCreate() : -----
|
|
* USBH_ERR_OS_SIGNAL_CREATE, if mutex creation failed.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_GlobalInit (USBH_ERR *p_err)
|
|
{
|
|
CPU_INT08U ix;
|
|
CPU_SIZE_T octets_reqd;
|
|
CPU_SIZE_T cdc_len;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
cdc_len = sizeof(USBH_CDC_DEV) * USBH_CDC_CFG_MAX_DEV;
|
|
|
|
Mem_Clr((void *)USBH_CDC_DevArr,
|
|
cdc_len);
|
|
|
|
for (ix = 0u; ix < USBH_CDC_CFG_MAX_DEV; ix++) { /* --------------- INIT CDC DEV STRUCT ---------------- */
|
|
|
|
*p_err = USBH_OS_MutexCreate(&USBH_CDC_DevArr[ix].HMutex);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return;
|
|
}
|
|
|
|
USBH_CDC_DevArr[ix].State = USBH_CLASS_DEV_STATE_NONE;
|
|
|
|
Mem_Clr((void *)USBH_CDC_DevArr[ix].EventNotifyBuf,
|
|
USBH_CDC_LEN_RESPONSE_AVAIL);
|
|
}
|
|
|
|
Mem_PoolCreate ( &USBH_CDC_DevPool,
|
|
(void *)USBH_CDC_DevArr,
|
|
cdc_len,
|
|
USBH_CDC_CFG_MAX_DEV,
|
|
sizeof(USBH_CDC_DEV),
|
|
sizeof(CPU_ALIGN),
|
|
&octets_reqd,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBH_ERR_ALLOC;
|
|
} else {
|
|
*p_err = USBH_ERR_NONE;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_ProbeDev()
|
|
*
|
|
* Description : Determine if device implements CDC.
|
|
*
|
|
* Argument(s) : p_dev Pointer to device.
|
|
*
|
|
* p_err Variable that will receive the return error code from this function.
|
|
*
|
|
* USBH_ERR_NONE Device is CDC.
|
|
* USBH_ERR_CLASS_PROBE_FAIL Device is not CDC.
|
|
* USBH_ERR_ALLOC Cannot allocate CDC structure.
|
|
* USBH_ERR_DESC_INVALID Invalid union descriptor.
|
|
*
|
|
* ----- RETURNED BY USBH_CfgSet() : -----
|
|
* 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.
|
|
*
|
|
* ---- RETURNED BY USBH_CDC_EP_Open ----
|
|
* 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_CDC_UnionDescParse ----
|
|
* USBH_ERR_DESC_INVALID, if union descriptor is invalid.
|
|
*
|
|
* Return(s) : pcdc_acm_dev, if device implements CDC.
|
|
* 0, otherwise.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void *USBH_CDC_ProbeDev (USBH_DEV *p_dev,
|
|
USBH_ERR *p_err)
|
|
{
|
|
CPU_INT08U if_ix;
|
|
CPU_INT08U cic_if_nbr = 0u;
|
|
CPU_INT08U dic_if_nbr = 0u;
|
|
CPU_INT08U nbr_ifs;
|
|
USBH_CFG *p_cfg;
|
|
USBH_DEV_DESC dev_desc;
|
|
USBH_IF_DESC if_desc;
|
|
USBH_IF *p_if;
|
|
USBH_IF *p_cic_if;
|
|
USBH_IF *p_dic_if;
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
USBH_CDC_UNION_DESC union_desc;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
p_cic_if = (USBH_IF *)0;
|
|
p_dic_if = (USBH_IF *)0;
|
|
|
|
USBH_DevDescGet(p_dev, &dev_desc);
|
|
if (dev_desc.bDeviceClass != USBH_CLASS_CODE_CDC_CTRL) {
|
|
*p_err = USBH_ERR_CLASS_PROBE_FAIL;
|
|
return ((void *)0);
|
|
}
|
|
|
|
p_cfg = USBH_CfgGet(p_dev, 0u);
|
|
if (p_cfg == (USBH_CFG *) 0) {
|
|
*p_err = USBH_ERR_CLASS_PROBE_FAIL;
|
|
return ((void *)0);
|
|
}
|
|
|
|
nbr_ifs = USBH_CfgIF_NbrGet(p_cfg);
|
|
for (if_ix = 0u; if_ix < nbr_ifs; if_ix++) {
|
|
|
|
p_if = USBH_IF_Get(p_cfg, if_ix);
|
|
USBH_IF_DescGet(p_if, /* Get IF desc from IF. */
|
|
0u,
|
|
&if_desc);
|
|
|
|
switch (if_desc.bInterfaceClass) {
|
|
case USBH_CLASS_CODE_CDC_CTRL:
|
|
p_cic_if = p_if;
|
|
cic_if_nbr = if_desc.bInterfaceNumber;
|
|
|
|
*p_err = USBH_CDC_UnionDescParse(&union_desc, p_if);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return ((void *)0);
|
|
}
|
|
|
|
if (union_desc.bMasterInterface != cic_if_nbr) {
|
|
*p_err = USBH_ERR_DESC_INVALID;
|
|
return ((void *)0);
|
|
}
|
|
|
|
dic_if_nbr = union_desc.bSlaveInterface0;
|
|
break;
|
|
|
|
case USBH_CLASS_CODE_CDC_DATA:
|
|
if (p_cic_if != (USBH_IF *)0) {
|
|
if (if_desc.bInterfaceNumber == dic_if_nbr) {
|
|
p_dic_if = p_if;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((p_cic_if != (USBH_IF *)0) &&
|
|
(p_dic_if != (USBH_IF *)0)) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((p_cic_if == (USBH_IF *)0) ||
|
|
(p_dic_if == (USBH_IF *)0)) {
|
|
*p_err = USBH_ERR_CLASS_PROBE_FAIL;
|
|
return ((void *)0);
|
|
}
|
|
|
|
*p_err = USBH_CfgSet(p_dev, 1u); /* Select 1st cfg. */
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
return ((void *)0);
|
|
}
|
|
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("CDC device connected\r\n");
|
|
#endif
|
|
/* Alloc a dev from CDC dev pool. */
|
|
p_cdc_dev = (USBH_CDC_DEV *)Mem_PoolBlkGet(&USBH_CDC_DevPool,
|
|
sizeof(USBH_CDC_DEV),
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBH_ERR_ALLOC;
|
|
return ((void *)0);
|
|
}
|
|
|
|
p_cdc_dev->DevPtr = p_dev;
|
|
p_cdc_dev->CIC_IF_Nbr = cic_if_nbr;
|
|
p_cdc_dev->CIC_IF_Ptr = p_cic_if;
|
|
p_cdc_dev->DIC_IF_Nbr = dic_if_nbr;
|
|
p_cdc_dev->DIC_IF_Ptr = p_dic_if;
|
|
|
|
*p_err = USBH_CDC_EP_Open(p_cdc_dev);
|
|
if (*p_err != USBH_ERR_NONE) {
|
|
Mem_PoolBlkFree( &USBH_CDC_DevPool,
|
|
(void *)p_cdc_dev,
|
|
&err_lib);
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)0;
|
|
return ((void *)p_cdc_dev);
|
|
}
|
|
|
|
p_cdc_dev->State = USBH_CLASS_DEV_STATE_CONN;
|
|
|
|
return ((void *)p_cdc_dev);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_Disconn()
|
|
*
|
|
* Description : Handle disconnection of a CDC device.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_Disconn (void *p_class_dev)
|
|
{
|
|
LIB_ERR err_lib;
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)p_class_dev;
|
|
|
|
(void)USBH_OS_MutexLock(p_cdc_dev->HMutex);
|
|
|
|
p_cdc_dev->State = USBH_CLASS_DEV_STATE_DISCONN;
|
|
|
|
USBH_EP_Close(&p_cdc_dev->CIC_IntrIn); /* Close EPs. */
|
|
USBH_EP_Close(&p_cdc_dev->DIC_BulkIn);
|
|
USBH_EP_Close(&p_cdc_dev->DIC_BulkOut);
|
|
|
|
if (p_cdc_dev->RefCnt == 0) { /* Release CDC dev if app ref cnt is 0. */
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
|
|
Mem_PoolBlkFree( &USBH_CDC_DevPool,
|
|
(void *)p_cdc_dev,
|
|
&err_lib);
|
|
return;
|
|
}
|
|
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_Suspend()
|
|
*
|
|
* Description : Put CDC device in suspended state.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_Suspend (void *p_class_dev)
|
|
{
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)p_class_dev;
|
|
|
|
(void)USBH_OS_MutexLock(p_cdc_dev->HMutex);
|
|
p_cdc_dev->State = USBH_CLASS_DEV_STATE_SUSPEND;
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_Resume()
|
|
*
|
|
* Description : Put CDC device back to "connected" state.
|
|
*
|
|
* Argument(s) : p_class_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : None..
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_Resume (void *p_class_dev)
|
|
{
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)p_class_dev;
|
|
|
|
(void)USBH_OS_MutexLock(p_cdc_dev->HMutex);
|
|
p_cdc_dev->State = USBH_CLASS_DEV_STATE_CONN;
|
|
(void)USBH_OS_MutexUnlock(p_cdc_dev->HMutex);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_EP_Open()
|
|
*
|
|
* Description : Open device endpoints.
|
|
*
|
|
* Argument(s) : p_cdc_dev Pointer to CDC device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE. If endpoints opened successfully.
|
|
*
|
|
* ----- RETURNED BY USBH_IntrInOpen() : -----
|
|
* 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_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.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_CDC_EP_Open (USBH_CDC_DEV *p_cdc_dev)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
err = USBH_IntrInOpen(p_cdc_dev->DevPtr,
|
|
p_cdc_dev->CIC_IF_Ptr,
|
|
&p_cdc_dev->CIC_IntrIn);
|
|
if (err != USBH_ERR_NONE) {
|
|
return (err);
|
|
}
|
|
|
|
err = USBH_BulkInOpen(p_cdc_dev->DevPtr,
|
|
p_cdc_dev->DIC_IF_Ptr,
|
|
&p_cdc_dev->DIC_BulkIn);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Close(&p_cdc_dev->CIC_IntrIn);
|
|
return (err);
|
|
}
|
|
|
|
err = USBH_BulkOutOpen(p_cdc_dev->DevPtr,
|
|
p_cdc_dev->DIC_IF_Ptr,
|
|
&p_cdc_dev->DIC_BulkOut);
|
|
if (err != USBH_ERR_NONE) {
|
|
(void)USBH_EP_Close(&p_cdc_dev->CIC_IntrIn);
|
|
(void)USBH_EP_Close(&p_cdc_dev->DIC_BulkIn);
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_UnionDescParse()
|
|
*
|
|
* Description : Parse union functional descriptor into USBH_CDC_UNION_DESC structure.
|
|
*
|
|
* Argument(s) : p_union_desc Variable that will receive union descriptor.
|
|
*
|
|
* p_if Pointer to interface.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE. if parsing is successful.
|
|
* USBH_ERR_DESC_INVALID, if union descriptor is invalid.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_CDC_UnionDescParse (USBH_CDC_UNION_DESC *p_union_desc,
|
|
USBH_IF *p_if)
|
|
{
|
|
USBH_ERR err;
|
|
CPU_INT08U *p_if_desc;
|
|
|
|
|
|
err = USBH_ERR_DESC_INVALID;
|
|
p_if_desc = (CPU_INT08U *)p_if->IF_DataPtr;
|
|
|
|
while (p_if_desc[1] != USBH_DESC_TYPE_EP) {
|
|
|
|
if (p_if_desc[2] == USBH_CDC_FNCTL_DESC_SUB_UFD) {
|
|
p_union_desc->bFunctionLength = p_if_desc[0];
|
|
p_union_desc->bDescriptorType = p_if_desc[1];
|
|
p_union_desc->bDescriptorSubtype = p_if_desc[2];
|
|
p_union_desc->bMasterInterface = p_if_desc[3];
|
|
p_union_desc->bSlaveInterface0 = p_if_desc[4];
|
|
err = USBH_ERR_NONE;
|
|
break;
|
|
|
|
} else {
|
|
p_if_desc += p_if_desc[0];
|
|
}
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DIC_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_CDC_DIC_DataTxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err)
|
|
{
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
(void)buf_len;
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)p_arg;
|
|
|
|
if (err != USBH_ERR_NONE) { /* Chk status of transaction. */
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
p_ep);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(p_ep);
|
|
}
|
|
}
|
|
|
|
p_cdc_dev->DataTxNotifyPtr( p_cdc_dev->DataTxNotifyArgPtr,
|
|
(CPU_INT08U *)p_buf,
|
|
xfer_len,
|
|
err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_DIC_DataRxCmpl()
|
|
*
|
|
* Description : Asynchronous data receive completion function.
|
|
*
|
|
* Argument(s) : p_ep Pointer to endpoint.
|
|
*
|
|
* p_buf Pointer to receive buffer.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* xfer_len Number of octets received.
|
|
*
|
|
* p_arg Asynchronous function argument.
|
|
*
|
|
* err Status of transaction.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_DIC_DataRxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err)
|
|
{
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
(void)buf_len;
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV *)p_arg;
|
|
|
|
if (err != USBH_ERR_NONE) { /* Check status of transaction. */
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr,
|
|
p_ep);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(p_ep);
|
|
}
|
|
}
|
|
|
|
p_cdc_dev->DataRxNotifyPtr( p_cdc_dev->DataRxNotifyArgPtr,
|
|
(CPU_INT08U *)p_buf,
|
|
xfer_len,
|
|
err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_CDC_CIC_EventRxCmpl()
|
|
*
|
|
* Description : Asynchronous serial state receive completion function.
|
|
*
|
|
* Argument(s) : p_ep Pointer to endpoint.
|
|
*
|
|
* p_buf Pointer to receive buffer.
|
|
*
|
|
* buf_len Buffer length in octets.
|
|
*
|
|
* xfer_len Number of octets received.
|
|
*
|
|
* p_arg Asynchronous function argument.
|
|
*
|
|
* err Status of transaction.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_CDC_CIC_EventRxCmpl (USBH_EP *p_ep,
|
|
void *p_buf,
|
|
CPU_INT32U buf_len,
|
|
CPU_INT32U xfer_len,
|
|
void *p_arg,
|
|
USBH_ERR err)
|
|
{
|
|
USBH_CDC_DEV *p_cdc_dev;
|
|
|
|
|
|
(void)buf_len;
|
|
|
|
p_cdc_dev = (USBH_CDC_DEV*)p_arg;
|
|
|
|
if (err != USBH_ERR_NONE) { /* Chk status of transaction. */
|
|
(void)USBH_EP_Reset(p_cdc_dev->DevPtr, p_ep);
|
|
|
|
if (err == USBH_ERR_EP_STALL) {
|
|
(void)USBH_EP_StallClr(p_ep);
|
|
}
|
|
}
|
|
|
|
if (p_cdc_dev->EvtNotifyPtr != (SUBCLASS_NOTIFY)0) {
|
|
p_cdc_dev->EvtNotifyPtr( p_cdc_dev->EvtNotifyArgPtr,
|
|
(CPU_INT08U *)p_buf,
|
|
xfer_len,
|
|
err);
|
|
}
|
|
|
|
(void)USBH_CDC_EventRxAsync(p_cdc_dev);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* END
|
|
*********************************************************************************************************
|
|
*/
|