2427 lines
100 KiB
C
2427 lines
100 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* uC/USB-Device
|
|
* The Embedded USB Device 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.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
*
|
|
* USB DEVICE PHDC CLASS
|
|
*
|
|
* Filename : usbd_phdc.c
|
|
* Version : V4.06.01
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* INCLUDE FILES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
#define MICRIUM_SOURCE
|
|
#define USBD_PHDC_MODULE
|
|
#include "usbd_phdc.h"
|
|
#include "usbd_phdc_os.h"
|
|
#include <lib_math.h>
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* MODULE
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_COM_NBR_MAX (USBD_PHDC_CFG_MAX_NBR_DEV * \
|
|
USBD_PHDC_CFG_MAX_NBR_CFG)
|
|
|
|
#define USBD_PHDC_CLASS_FNCT_DESC_LEN 4
|
|
#define USBD_PHDC_FUNCT_EXTN_DESC_DFLT_LEN 4
|
|
#define USBD_PHDC_EXTRA_EP_DESC_MAX_LEN (USBD_PHDC_QOS_DESC_LEN + \
|
|
USBD_PHDC_CFG_DATA_OPAQUE_MAX_LEN + \
|
|
USBD_PHDC_METADATA_DESC_LEN)
|
|
|
|
#define USBD_PHDC_QOS_DESC_LEN 4u
|
|
#define USBD_PHDC_QOS_ENCOD_VER 0x01u
|
|
#define USBD_PHDC_QOS_VER_OFFSET 17u
|
|
|
|
|
|
#define USBD_PHDC_QOS_SIGNATURE "PhdcQoSSignature"
|
|
#define USBD_PHDC_QOS_SIGNATURE_LEN 16u
|
|
|
|
#define USBD_PHDC_METADATA_MSG_PREAMBLE_DFLT_LEN 20
|
|
#define USBD_PHDC_METADATA_MSG_PREAMBLE_MAX_LEN (USBD_PHDC_CFG_DATA_OPAQUE_MAX_LEN + \
|
|
USBD_PHDC_METADATA_MSG_PREAMBLE_DFLT_LEN)
|
|
|
|
#define USBD_PHDC_METADATA_DESC_LEN 2
|
|
|
|
#define USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_IN (USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST | \
|
|
USBD_PHDC_LATENCY_HIGH_RELY_BEST | \
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BEST | \
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BETTER | \
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_GOOD)
|
|
#define USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_OUT (USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST | \
|
|
USBD_PHDC_LATENCY_HIGH_RELY_BEST | \
|
|
USBD_PHDC_LATENCY_MEDIUM_RELY_BEST)
|
|
#define USBD_PHDC_RELY_LATENCY_FLAGS_EP_INTR_IN (USBD_PHDC_LATENCY_LOW_RELY_GOOD)
|
|
|
|
#define USBD_PHDC_XFER_PRIO_MAX 6
|
|
#define USBD_PHDC_XFER_PRIO_LOW_LATENCY 0u
|
|
|
|
#define USBD_PHDC_CTRL_REQ_TIMEOUT_mS 5000u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC NBR EP
|
|
*
|
|
* Note(s) : (1) PHDC require 2 bulk endpoints (IN and OUT) for very high, high and medium latency
|
|
* transfers. It optionally needs 1 interrupt IN endpoint for low latency transfer. See
|
|
* 'USB PHDC Class Specification Overview', Revision 1.0, Section 4.4.1.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_NBR_EP 3u
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* DESCRIPTOR TYPES
|
|
*
|
|
* Note(s) : (1) See 'USB PHDC Class Specification Overview', Revision 1.0, Section 8 and Appendix A.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_DESC_TYPE_CLASS_FNCT 0x20u
|
|
#define USBD_PHDC_DESC_TYPE_FUNCT_EXTN_11073 0x30u
|
|
#define USBD_PHDC_DESC_TYPE_QOS 0x21u
|
|
#define USBD_PHDC_DESC_TYPE_METADATA 0x22u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* DATA FORMAT
|
|
*
|
|
* Note(s) : (1) See 'USB PHDC Class Specification Overview', Revision 1.0, Appendix A.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_DATA_FMT_VENDOR 0x01u
|
|
#define USBD_PHDC_DATA_FMT_11073_20601 0x02u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC CAPABILITY
|
|
*
|
|
* Note(s) : (1) See 'USB PHDC Class Specification Overview', Revision 1.0, Section 5.2.1.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_PREAMBLE_CAPABLE DEF_BIT_00
|
|
#define USBD_PHDC_PREAMBLE_NOT_CAPABLE DEF_BIT_NONE
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* SUBCLASS CODES
|
|
*
|
|
* Note(s) : (1) See 'USB PHDC Class Specification Overview', Revision 1.0, Section 5.1.1.
|
|
* The PHDC does not assign a SUBCLASS CODE.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_SUBCLASS_CODE_NONE 0x00
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PROTOCOL CODES
|
|
*
|
|
* Note(s) : (1) See 'USB PHDC Class Specification Overview', Revision 1.0, Section 5.1.1.
|
|
* The PHDC does not assign a PROTOCOL CODE.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_PROTOCOL_CODE_NONE 0x00
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* FEATURE SELECTORS
|
|
*
|
|
* Note(s) : (1) See 'Universal Serial Bus Specification Revision 2.0', Section 9.4, Table 9-6, and
|
|
* Section 9.4.1.
|
|
*
|
|
* (2) For a 'clear feature' setup request, the 'wValue' field may contain one of these values.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBD_PHDC_CLASS_SPEC_FEATURE_PHDC_QOS 0x01u
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* ENDPOINT IDENTIFIERS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef enum usbd_phdc_ep_id {
|
|
USBD_PHDC_EP_BULK_IN = 0x00,
|
|
USBD_PHDC_EP_BULK_OUT,
|
|
USBD_PHDC_EP_INTR_IN
|
|
} USBD_PHDC_EP_ID;
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC STATE
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef enum usbd_phdc_state {
|
|
USBD_PHDC_STATE_NONE = 0,
|
|
USBD_PHDC_STATE_INIT,
|
|
USBD_PHDC_STATE_CFG
|
|
} USBD_PHDC_STATE;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC EP PARAMS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbd_phdc_ep_params {
|
|
const CPU_INT08U *DataOpaquePtr; /* Opaque data written in metadata desc. */
|
|
CPU_INT16U DataOpaqueLen;
|
|
} USBD_PHDC_EP_PARAMS;
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC PARAMS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbd_phdc_params {
|
|
CPU_BOOLEAN DataFmt11073; /* DEF_TRUE if dev use 11073 data format. */
|
|
CPU_BOOLEAN PreambleCapable; /* DEF_TRUE if dev can send metadata preamble. */
|
|
CPU_INT16U *DevSpecialization; /* Array of dev specialization codes. */
|
|
CPU_INT16U NbrDevSpecialization;
|
|
} USBD_PHDC_PARAMS;
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* FORWARD DECLARATIONS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbd_phdc_ctrl USBD_PHDC_CTRL;
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* PRIORITY Q PREAMBLE
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* PHDC COMM INFO
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
typedef struct usbd_phdc_comm {
|
|
USBD_PHDC_CTRL *CtrlPtr;
|
|
CPU_INT08U DataBulkOut;
|
|
CPU_INT08U DataBulkIn;
|
|
CPU_INT08U DataIntrIn;
|
|
} USBD_PHDC_COMM;
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* PHDC CTRL INFO
|
|
*
|
|
* Note(s) : (1) Rx and Tx DataXfersTotal holds the value of following tranfers to which QoS settings of a
|
|
* preamble applies. Rx and Tx DataXfersCur indicates what is the count of the current
|
|
* processed transfer.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
struct usbd_phdc_ctrl {
|
|
CPU_INT08U Nbr; /* PHDC class instance number. */
|
|
CPU_INT08U DevNbr; /* Device number. */
|
|
USBD_PHDC_STATE State; /* PHDC state. */
|
|
USBD_PHDC_COMM *CommPtr; /* PHDC communication information ptr. */
|
|
|
|
USBD_PHDC_PARAMS IF_Params;
|
|
|
|
USBD_PHDC_EP_PARAMS EP_Params[USBD_PHDC_NBR_EP];
|
|
CPU_INT16U EP_DataStatus; /* See 'PHDC specifications Revision 1.0', Section 7.1.2*/
|
|
CPU_INT08U *CtrlStatusBufPtr; /* Buf used for ctrl status xfers. */
|
|
|
|
CPU_INT08U RxDataXfersTotal; /* See note 1. */
|
|
CPU_INT08U RxDataXfersCur;
|
|
LATENCY_RELY_FLAGS RxLatencyRelyBitmap;
|
|
|
|
CPU_INT08U TxDataXfersTotal[USBD_PHDC_XFER_PRIO_MAX - 1u];
|
|
CPU_INT08U TxDataXfersCur[USBD_PHDC_XFER_PRIO_MAX - 1u];
|
|
LATENCY_RELY_FLAGS TxLatencyRelyBitmap;
|
|
CPU_INT16U TxLowLatencyInterval; /* Intr EP interval in frames or micro-frames. */
|
|
|
|
CPU_INT08U *PreambleBufTxPtr;
|
|
CPU_INT08U *PreambleBufRxPtr;
|
|
CPU_BOOLEAN PreambleEn; /* Indicate if host enabled preamble or not. */
|
|
USBD_PHDC_PREAMBLE_EN_NOTIFY PreambleEnNotify;
|
|
};
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL TABLES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static USBD_PHDC_CTRL USBD_PHDC_CtrlTbl[USBD_PHDC_CFG_MAX_NBR_DEV];
|
|
static CPU_INT08U USBD_PHDC_CtrlNbrNext;
|
|
|
|
static USBD_PHDC_COMM USBD_PHDC_CommTbl[USBD_PHDC_COM_NBR_MAX];
|
|
static CPU_INT16U USBD_PHDC_CommNbrNext;
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_Conn ( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
void *p_if_class_arg);
|
|
|
|
static void USBD_PHDC_Disconn ( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
void *p_if_class_arg);
|
|
|
|
static void USBD_PHDC_SettingUpdate ( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg);
|
|
|
|
static void USBD_PHDC_IF_Desc ( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg);
|
|
|
|
static CPU_INT16U USBD_PHDC_IF_DescSizeGet( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg);
|
|
|
|
static void USBD_PHDC_EP_Desc ( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
CPU_INT08U ep_addr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg);
|
|
|
|
static CPU_INT16U USBD_PHDC_EP_DescSizeGet( CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
CPU_INT08U ep_addr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg);
|
|
|
|
static CPU_BOOLEAN USBD_PHDC_ClassReq ( CPU_INT08U dev_nbr,
|
|
const USBD_SETUP_REQ *p_setup_req,
|
|
void *p_if_class_arg);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* PHDC CLASS DRIVER
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBD_CLASS_DRV USBD_PHDC_Drv = {
|
|
USBD_PHDC_Conn,
|
|
USBD_PHDC_Disconn,
|
|
USBD_PHDC_SettingUpdate,
|
|
DEF_NULL,
|
|
USBD_PHDC_IF_Desc,
|
|
USBD_PHDC_IF_DescSizeGet,
|
|
USBD_PHDC_EP_Desc,
|
|
USBD_PHDC_EP_DescSizeGet,
|
|
DEF_NULL,
|
|
USBD_PHDC_ClassReq,
|
|
DEF_NULL,
|
|
|
|
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
|
|
DEF_NULL,
|
|
DEF_NULL
|
|
#endif
|
|
};
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* LOCAL CONFIGURATION ERRORS
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* GLOBAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_Init()
|
|
*
|
|
* Description : Initialize PHDC.
|
|
*
|
|
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE PHDC initialized successfully.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
void USBD_PHDC_Init (USBD_ERR *p_err)
|
|
{
|
|
CPU_INT08U ix;
|
|
CPU_INT08U i;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_SIZE_T ctrl_buf_len;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
#endif
|
|
|
|
for (ix = 0u; ix < USBD_PHDC_CFG_MAX_NBR_DEV; ix++) { /* Init PHDC ctrl struct. */
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[ix];
|
|
p_ctrl->Nbr = ix;
|
|
p_ctrl->DevNbr = USBD_DEV_NBR_NONE;
|
|
p_ctrl->State = USBD_PHDC_STATE_NONE;
|
|
p_ctrl->CommPtr = (USBD_PHDC_COMM *)0;
|
|
|
|
p_ctrl->EP_Params[0].DataOpaquePtr = (const CPU_INT08U *)0;
|
|
p_ctrl->EP_Params[1].DataOpaquePtr = (const CPU_INT08U *)0;
|
|
p_ctrl->EP_Params[2].DataOpaquePtr = (const CPU_INT08U *)0;
|
|
p_ctrl->EP_Params[0].DataOpaqueLen = 0;
|
|
p_ctrl->EP_Params[1].DataOpaqueLen = 0;
|
|
p_ctrl->EP_Params[2].DataOpaqueLen = 0;
|
|
p_ctrl->EP_DataStatus = DEF_BIT_NONE;
|
|
|
|
p_ctrl->RxDataXfersTotal = 0u;
|
|
p_ctrl->RxDataXfersCur = 0u;
|
|
p_ctrl->RxLatencyRelyBitmap = DEF_BIT_NONE;
|
|
|
|
p_ctrl->TxLatencyRelyBitmap = DEF_BIT_NONE;
|
|
p_ctrl->TxLowLatencyInterval = 0u;
|
|
p_ctrl->PreambleEn = DEF_DISABLED;
|
|
|
|
for (i = 0; i < (USBD_PHDC_XFER_PRIO_MAX - 1u); i++) {
|
|
p_ctrl->TxDataXfersTotal[i] = 0u;
|
|
p_ctrl->TxDataXfersCur[i] = 0u;
|
|
}
|
|
|
|
p_ctrl->PreambleBufTxPtr = (CPU_INT08U *)Mem_HeapAlloc( USBD_PHDC_METADATA_MSG_PREAMBLE_MAX_LEN,
|
|
USBD_CFG_BUF_ALIGN_OCTETS,
|
|
(CPU_SIZE_T *)DEF_NULL,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBD_ERR_ALLOC;
|
|
return;
|
|
}
|
|
|
|
p_ctrl->PreambleBufRxPtr = (CPU_INT08U *)Mem_HeapAlloc( USBD_PHDC_METADATA_MSG_PREAMBLE_MAX_LEN,
|
|
USBD_CFG_BUF_ALIGN_OCTETS,
|
|
(CPU_SIZE_T *)DEF_NULL,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBD_ERR_ALLOC;
|
|
return;
|
|
}
|
|
|
|
Mem_Copy((void *)p_ctrl->PreambleBufTxPtr, /* Init preamble template. */
|
|
(void *)USBD_PHDC_QOS_SIGNATURE,
|
|
USBD_PHDC_QOS_SIGNATURE_LEN);
|
|
p_ctrl->PreambleBufTxPtr[17] = USBD_PHDC_QOS_ENCOD_VER;
|
|
|
|
ctrl_buf_len = sizeof(CPU_ADDR);
|
|
if (sizeof(CPU_ADDR) < 2u) {
|
|
ctrl_buf_len = 2u;
|
|
}
|
|
p_ctrl->CtrlStatusBufPtr = (CPU_INT08U *)Mem_HeapAlloc( ctrl_buf_len,
|
|
USBD_CFG_BUF_ALIGN_OCTETS,
|
|
(CPU_SIZE_T *)DEF_NULL,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
*p_err = USBD_ERR_ALLOC;
|
|
return;
|
|
}
|
|
|
|
p_ctrl->IF_Params.NbrDevSpecialization = 0;
|
|
p_ctrl->IF_Params.DataFmt11073 = DEF_NO;
|
|
p_ctrl->IF_Params.PreambleCapable = DEF_NO;
|
|
}
|
|
|
|
for (ix = 0u; ix < USBD_PHDC_COM_NBR_MAX; ix++) { /* Init PHDC comm tbl. */
|
|
p_comm = &USBD_PHDC_CommTbl[ix];
|
|
|
|
p_comm->DataBulkIn = USBD_EP_ADDR_NONE;
|
|
p_comm->DataBulkOut = USBD_EP_ADDR_NONE;
|
|
p_comm->DataIntrIn = USBD_EP_ADDR_NONE;
|
|
p_comm->CtrlPtr = (USBD_PHDC_CTRL *)0;
|
|
}
|
|
|
|
USBD_PHDC_CtrlNbrNext = 0;
|
|
USBD_PHDC_CommNbrNext = 0;
|
|
|
|
USBD_PHDC_OS_Init(p_err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_Add()
|
|
*
|
|
* Description : Add a new instance of PHDC.
|
|
*
|
|
* Argument(s) : data_fmt_11073 Class instance use ieee 11073 protocol if set to DEF_YES.
|
|
* Otherwise, vendor defined protocol is used.
|
|
*
|
|
* preamble_capable Class instance support metadata message preamble if set
|
|
* to DEF_YES.
|
|
*
|
|
* preamble_en_notify Pointer to a callback function that notify application if
|
|
* metadata message preambles are enabled.
|
|
*
|
|
* low_latency_interval Interrupt endpoint interval in milliseconds. Can be 0
|
|
* if PHDC device will not send low latency data. When the value
|
|
* is different from 0, it must be a power of 2.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error
|
|
* code from this function :
|
|
*
|
|
* USBD_ERR_NONE PHDC instance successfully added.
|
|
* USBD_ERR_ALLOC No more class instance structure available.
|
|
*
|
|
* Return(s) : PHDC device number, if NO error(s).
|
|
*
|
|
* USBD_PHDC_NBR_NONE, otherwise.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT08U USBD_PHDC_Add (CPU_BOOLEAN data_fmt_11073,
|
|
CPU_BOOLEAN preamble_capable,
|
|
USBD_PHDC_PREAMBLE_EN_NOTIFY preamble_en_notify,
|
|
CPU_INT16U low_latency_interval,
|
|
USBD_ERR *p_err)
|
|
{
|
|
CPU_INT08U phdc_nbr;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if ((low_latency_interval != 0u) &&
|
|
(MATH_IS_PWR2(low_latency_interval) == DEF_NO)) { /* Interval must be a power of 2. */
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return (USBD_CLASS_NBR_NONE);
|
|
}
|
|
#endif
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
phdc_nbr = USBD_PHDC_CtrlNbrNext; /* Alloc new PHDC instance. */
|
|
|
|
if (phdc_nbr >= USBD_PHDC_CFG_MAX_NBR_DEV) {
|
|
CPU_CRITICAL_EXIT();
|
|
*p_err = USBD_ERR_PHDC_INSTANCE_ALLOC;
|
|
return (USBD_CLASS_NBR_NONE);
|
|
}
|
|
|
|
USBD_PHDC_CtrlNbrNext++;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[phdc_nbr];
|
|
|
|
p_ctrl->IF_Params.DataFmt11073 = data_fmt_11073;
|
|
p_ctrl->IF_Params.PreambleCapable = preamble_capable;
|
|
p_ctrl->PreambleEnNotify = preamble_en_notify;
|
|
p_ctrl->TxLowLatencyInterval = low_latency_interval;
|
|
|
|
return (phdc_nbr);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_CfgAdd()
|
|
*
|
|
* Description : Add PHDC instance into USB device configuration.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* dev_nbr Device number.
|
|
*
|
|
* cfg_nbr Configuration index to add new PHDC interface to.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE PHDC instance successfully added.
|
|
* USBD_ERR_INVALID_ARG, if invalid argument(s) passed to class_nbr.
|
|
* USBD_ERR_ALLOC No more class communication structure available.
|
|
*
|
|
* --------- RETURNED BY USBD_IF_Add() : ---------
|
|
* USBD_ERR_NULL_PTR Invalid NULL pointer was passed to 3rd argument.
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_IF_ALLOC NO available device interfaces.
|
|
*
|
|
* -------- RETURNED BY USBD_BulkAdd() : --------
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_CFG_INVALID_NBR Invalid configuration number.
|
|
* USBD_ERR_IF_ALTINVALID_NBR Invalid interface alternative setting number.
|
|
* USBD_ERR_IF_INVALID_NBR Invalid interface number.
|
|
*
|
|
* --------- RETURNED BY USBD_IF_Add() : ---------
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_CFG_INVALID_NBR Invalid configuration number.
|
|
* USBD_ERR_IF_ALTINVALID_NBR Invalid interface alternative setting number.
|
|
* USBD_ERR_IF_INVALID_NBR Invalid interface number.
|
|
*
|
|
* Return(s) : DEF_YES, if PHDC instance added to USB device configuration successfully.
|
|
*
|
|
* DEF_NO, otherwise.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN USBD_PHDC_CfgAdd (CPU_INT08U class_nbr,
|
|
CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
USBD_ERR *p_err)
|
|
{
|
|
CPU_BOOLEAN ep_intr_en;
|
|
CPU_INT08U if_nbr;
|
|
CPU_INT08U ep_addr;
|
|
CPU_INT16U comm_nbr;
|
|
CPU_INT16U tx_low_latency_interval;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(DEF_NO);
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return (DEF_NO);
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
|
|
if ((p_ctrl->RxLatencyRelyBitmap == (LATENCY_RELY_FLAGS)0) ||
|
|
(p_ctrl->TxLatencyRelyBitmap == (LATENCY_RELY_FLAGS)0)) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return (DEF_NO);
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
comm_nbr = USBD_PHDC_CommNbrNext; /* Alloc new PHDC comm info. */
|
|
|
|
if (comm_nbr >= USBD_PHDC_COM_NBR_MAX) {
|
|
USBD_PHDC_CtrlNbrNext--;
|
|
CPU_CRITICAL_EXIT();
|
|
*p_err = USBD_ERR_PHDC_INSTANCE_ALLOC;
|
|
return (DEF_NO);
|
|
}
|
|
|
|
USBD_PHDC_CommNbrNext++;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
p_comm = &USBD_PHDC_CommTbl[comm_nbr];
|
|
|
|
if_nbr = USBD_IF_Add( dev_nbr, /* Add PHDC to cfg. */
|
|
cfg_nbr,
|
|
&USBD_PHDC_Drv,
|
|
(void *)p_comm,
|
|
(void *)0,
|
|
USBD_CLASS_CODE_PERSONAL_HEALTHCARE,
|
|
USBD_PHDC_SUBCLASS_CODE_NONE,
|
|
USBD_PHDC_PROTOCOL_CODE_NONE,
|
|
"Personal Healthcare Device Class",
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (DEF_NO);
|
|
}
|
|
|
|
/* --------- ADD ENPOINTS TO DEFAULT INTERFACE -------- */
|
|
ep_addr = USBD_BulkAdd(dev_nbr, /* Add bulk (IN) EP. */
|
|
cfg_nbr,
|
|
if_nbr,
|
|
0u,
|
|
DEF_YES,
|
|
0u,
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (DEF_NO);
|
|
}
|
|
|
|
p_comm->DataBulkIn = ep_addr; /* Store bulk (IN) EP address. */
|
|
|
|
|
|
ep_addr = USBD_BulkAdd(dev_nbr, /* Add bulk (OUT) EP. */
|
|
cfg_nbr,
|
|
if_nbr,
|
|
0u,
|
|
DEF_NO,
|
|
0u,
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (DEF_NO);
|
|
}
|
|
|
|
p_comm->DataBulkOut = ep_addr;
|
|
|
|
|
|
ep_intr_en = DEF_BIT_IS_SET(p_ctrl->TxLatencyRelyBitmap, USBD_PHDC_RELY_LATENCY_FLAGS_EP_INTR_IN);
|
|
if (ep_intr_en == DEF_TRUE) {
|
|
|
|
if (DEF_BIT_IS_CLR(cfg_nbr, USBD_CFG_NBR_SPD_BIT) == DEF_YES) {
|
|
/* In FS, bInterval in frames. */
|
|
tx_low_latency_interval = p_ctrl->TxLowLatencyInterval;
|
|
} else { /* In HS, bInterval in microframes. */
|
|
tx_low_latency_interval = p_ctrl->TxLowLatencyInterval * 8u;
|
|
}
|
|
|
|
ep_addr = USBD_IntrAdd(dev_nbr, /* Add intr (IN) EP. */
|
|
cfg_nbr,
|
|
if_nbr,
|
|
0u,
|
|
DEF_YES,
|
|
0u,
|
|
tx_low_latency_interval,
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (DEF_NO);
|
|
}
|
|
|
|
p_comm->DataIntrIn = ep_addr; /* Store intr (IN) EP address. */
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
p_comm->CtrlPtr = p_ctrl;
|
|
p_ctrl->State = USBD_PHDC_STATE_INIT;
|
|
p_ctrl->DevNbr = dev_nbr;
|
|
p_ctrl->CommPtr = (USBD_PHDC_COMM *)0;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
|
|
return (DEF_YES);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_IsConn()
|
|
*
|
|
* Description : Get PHDC connection state.
|
|
*
|
|
* Argument(s) : class_nbr Class instance number.
|
|
*
|
|
* Return(s) : DEF_YES, if PHDC is connected.
|
|
*
|
|
* DEF_NO, otherwise.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
CPU_BOOLEAN USBD_PHDC_IsConn (CPU_INT08U class_nbr)
|
|
{
|
|
USBD_ERR err;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_DEV_STATE state;
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED)
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
return (DEF_NO);
|
|
}
|
|
#endif
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
state = USBD_DevStateGet(p_ctrl->DevNbr, &err); /* Get dev state. */
|
|
|
|
if ((err == USBD_ERR_NONE ) &&
|
|
(state == USBD_DEV_STATE_CONFIGURED) &&
|
|
(p_ctrl->State == USBD_PHDC_STATE_CFG )) {
|
|
return (DEF_YES);
|
|
}
|
|
|
|
return (DEF_NO);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_RdCfg()
|
|
*
|
|
* Description : Configure read communication pipe parameters.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* latency_rely Latency / reliability flags. Can be one or more of these values:
|
|
*
|
|
* USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST Very high latency, best reliability
|
|
* USBD_PHDC_LATENCY_HIGH_RELY_BEST, High latency, best reliability
|
|
* USBD_PHDC_LATENCY_MEDIUM_RELY_BEST, Medium latency, best reliability
|
|
*
|
|
* p_data_opaque Pointer to a buffer that contains opaque data.
|
|
*
|
|
* data_opaque_len Opaque data length. If 0, no metadata descriptor will be written.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE if communication pipe has been succesfully initialized.
|
|
* USBD_ERR_INVALID_ARG if invalid argument(s) passed to class_nbr or latency_rely.
|
|
* USBD_ERR_NULL_PTR if p_data_opaque is an invalid null pointer.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_RdCfg ( CPU_INT08U class_nbr,
|
|
LATENCY_RELY_FLAGS latency_rely,
|
|
const CPU_INT08U *p_data_opaque,
|
|
CPU_INT08U data_opaque_len,
|
|
USBD_ERR *p_err)
|
|
{
|
|
LATENCY_RELY_FLAGS other_latency_rely;
|
|
LATENCY_RELY_FLAGS latency_rely_test;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
CPU_INT08U latency_rely_bit;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if ((p_data_opaque == (CPU_INT08U *)0 ) &&
|
|
(data_opaque_len != 0u)) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
if (latency_rely == DEF_BIT_NONE) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
|
|
if (p_ctrl->State != USBD_PHDC_STATE_NONE) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
}
|
|
|
|
if (p_ctrl->IF_Params.PreambleCapable == DEF_NO) { /* If device is not capable of preamble send/recv... */
|
|
latency_rely_test = latency_rely;
|
|
latency_rely_bit = CPU_CntTrailZeros08(latency_rely);
|
|
DEF_BIT_CLR(latency_rely_test, DEF_BIT(latency_rely_bit));
|
|
|
|
if (latency_rely_test != DEF_BIT_NONE) {
|
|
*p_err = USBD_ERR_INVALID_ARG; /* ... only one QoS bin shall be set. */
|
|
return;
|
|
}
|
|
}
|
|
/* Rx pipe can only have best rely. */
|
|
other_latency_rely = latency_rely;
|
|
DEF_BIT_CLR(other_latency_rely, USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_OUT);
|
|
if (other_latency_rely != DEF_BIT_NONE) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_BULK_OUT].DataOpaquePtr = p_data_opaque;
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_BULK_OUT].DataOpaqueLen = data_opaque_len;
|
|
|
|
p_ctrl->RxLatencyRelyBitmap = latency_rely;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_WrCfg()
|
|
*
|
|
* Description : Configure write communication pipe parameters.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* latency_rely Latency / reliability flags. Can be one or more of these values:
|
|
*
|
|
* USBD_PHDC_LATENCY_VERYHIGH_RELY_BEST Very high latency, best reliability
|
|
* USBD_PHDC_LATENCY_HIGH_RELY_BEST High latency, best reliability
|
|
* USBD_PHDC_LATENCY_MEDIUM_RELY_BEST Medium latency, best reliability
|
|
* USBD_PHDC_LATENCY_MEDIUM_RELY_BETTER Medium latency, better reliability
|
|
* USBD_PHDC_LATENCY_MEDIUM_RELY_GOOD Medium latency, good reliability
|
|
* USBD_PHDC_LATENCY_LOW_RELY_GOOD Low latency, good reliability
|
|
*
|
|
* p_data_opaque Pointer to a buffer that contains opaque data.
|
|
*
|
|
* data_opaque_len Opaque data length. If 0, no metadata descriptor will be written.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE if communication pipe has been succesfully initialized.
|
|
* USBD_ERR_INVALID_ARG if invalid argument(s) passed to class_nbr or latency_rely.
|
|
* USBD_ERR_NULL_PTR if p_data_opaque is an invalid null pointer.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : (1) If application needs to have different opaque data for low latency pipe, than
|
|
* this function should be called twice. Once for pipe carrying medium /
|
|
* high / very high latency transfers, and once for pipe carrying low latency transfers.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_WrCfg ( CPU_INT08U class_nbr,
|
|
LATENCY_RELY_FLAGS latency_rely,
|
|
const CPU_INT08U *p_data_opaque,
|
|
CPU_INT08U data_opaque_len,
|
|
USBD_ERR *p_err)
|
|
{
|
|
CPU_BOOLEAN ep_bulk;
|
|
CPU_BOOLEAN ep_intr;
|
|
CPU_INT08U latency_rely_bit;
|
|
LATENCY_RELY_FLAGS latency_rely_test;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if ((p_data_opaque == (CPU_INT08U *)0) &&
|
|
(data_opaque_len != 0)) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
|
|
if (latency_rely == 0) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
|
|
if (p_ctrl->State != USBD_PHDC_STATE_NONE) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return;
|
|
}
|
|
|
|
if (p_ctrl->IF_Params.PreambleCapable == DEF_NO) {
|
|
latency_rely_test = latency_rely;
|
|
latency_rely_bit = CPU_CntTrailZeros08(latency_rely);
|
|
DEF_BIT_CLR(latency_rely_test, DEF_BIT(latency_rely_bit));
|
|
|
|
if (latency_rely_test != DEF_BIT_NONE) {
|
|
*p_err = USBD_ERR_INVALID_ARG; /* ... not preamble capable. */
|
|
return;
|
|
}
|
|
}
|
|
|
|
ep_bulk = DEF_BIT_IS_SET_ANY(latency_rely, USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_IN);
|
|
ep_intr = DEF_BIT_IS_SET_ANY(latency_rely, USBD_PHDC_RELY_LATENCY_FLAGS_EP_INTR_IN);
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
p_ctrl->TxLatencyRelyBitmap |= latency_rely;
|
|
/* Check if dev need intr EP */
|
|
if (ep_intr == DEF_TRUE) {
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_INTR_IN].DataOpaquePtr = p_data_opaque;
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_INTR_IN].DataOpaqueLen = data_opaque_len;
|
|
}
|
|
|
|
if (ep_bulk == DEF_TRUE) {
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_BULK_IN].DataOpaquePtr = p_data_opaque;
|
|
p_ctrl->EP_Params[USBD_PHDC_EP_BULK_IN].DataOpaqueLen = data_opaque_len;
|
|
}
|
|
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_11073_ExtCfg()
|
|
*
|
|
* Description : Configure function extension for given class instance.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* p_dev_specialization Pointer to an array that contains a list of device
|
|
* specializations. (See 'Personal Healthcare Device Class
|
|
* specifications Revision 1.0', Appendix A.)
|
|
*
|
|
* nbr_dev_specialization Number of device specialzations specified in p_fnct_ext array.
|
|
*
|
|
* p_err Pointer to variable that will receive the return error
|
|
* code from this function :
|
|
*
|
|
* USBD_ERR_NONE if function extensions successfully configured.
|
|
* USBD_ERR_INVALID_ARG if invalid argument(s) passed to class_nbr.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_11073_ExtCfg (CPU_INT08U class_nbr,
|
|
CPU_INT16U *p_dev_specialization,
|
|
CPU_INT08U nbr_dev_specialization,
|
|
USBD_ERR *p_err)
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
p_ctrl->IF_Params.DevSpecialization = p_dev_specialization;
|
|
p_ctrl->IF_Params.NbrDevSpecialization = nbr_dev_specialization;
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_PreambleRd()
|
|
*
|
|
* Description : Read metadata preamble. This function is blocking.
|
|
*
|
|
* Argument(s) : class_nbr PHDC class instance number.
|
|
*
|
|
* p_buf Pointer to buffer that will contain opaque data from metadata
|
|
* message preamble.
|
|
*
|
|
* buf_len Opaque data buffer length in octets.
|
|
*
|
|
* p_nbr_xfer Pointer to a variable that will contain number of transfer the preamble apply to.
|
|
* After this call, USBD_PHDC_Rd shall be called nbr_xfer times by the application.
|
|
*
|
|
* timeout Timeout (ms).
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE Data successfully received from host.
|
|
* USBD_ERR_INVALID_CLASS_STATE Invalid PHDC state.
|
|
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to class_nbr.
|
|
* USBD_ERR_NULL_PTR Invalid NULL receive buffer.
|
|
* USBD_ERR_RX No metadata preamble expected from host or
|
|
* invalid metadata preamble received.
|
|
*
|
|
* ------ RETURNED BY USBD_BulkRx() : ------
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_EP_INVALID_NBR Invalid endpoint number.
|
|
* USBD_ERR_DEV_INVALID_STATE Bulk transfer can ONLY be used after the
|
|
* device is in configured state.
|
|
* USBD_ERR_EP_INVALID_TYPE Invalid endpoint type.
|
|
*
|
|
* --- RETURNED BY USBD_PHDC_OS_RdLock() ---
|
|
* USBD_ERR_NONE OS signal successfully acquired.
|
|
* USBD_OS_ERR_TIMEOUT OS signal NOT successfully acquired in the time
|
|
* specified by 'timeout_ms'.
|
|
* USBD_OS_ERR_ABORT OS signal aborted.
|
|
* USBD_OS_ERR_FAIL OS signal not acquired because another error.
|
|
*
|
|
* Return(s) : Opaque data length in octets, if no error(s).
|
|
*
|
|
* 0, otherwise.
|
|
*
|
|
* Note(s) : (1) Metadata message preamble contains the following fields (see 'USB PHDC Class Specification
|
|
* Overview', Revision 1.0, Section 6.1.):
|
|
*
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | Offset | Field | Size | Description |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 0 | aSignature | 16 | Cst used to verify preamble. |
|
|
* | | | | Set to PhdcQoSSignature string. |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 16 | bNumTransfers | 1 | Cnt of following xfers to which |
|
|
* | | | | QoS setting applies. |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 17 | bQoSEncodingVersion | 1 | QoS info encoding version. Set to |
|
|
* | | | | 0x01 for the moment. |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 18 | bmLatencyReliability | 1 | Bitmap that refers to latency/rely|
|
|
* | | | | bin for data. Shall be set to one |
|
|
* | | | | of the value specified in section |
|
|
* | | | | LATENCY / RELIABILITY BITMAPS of |
|
|
* | | | | usbd_phdc.h. |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 19 | bOpaqueDataSize | 1 | Length, in bytes, of opaque data. |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
* | 20 | bOpaqueData | [0 .. | Opaque data. |
|
|
* | | | MaxPacketSize - 21] | |
|
|
* +--------+-----------------------+----------------------+-----------------------------------+
|
|
*
|
|
* (2) If host disable preamble while the application is pending on this function, the call will
|
|
* immediately return with error USBD_OS_ERR_ABORT.
|
|
*
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT08U USBD_PHDC_PreambleRd (CPU_INT08U class_nbr,
|
|
void *p_buf,
|
|
CPU_INT08U buf_len,
|
|
CPU_INT08U *p_nbr_xfer,
|
|
CPU_INT16U timeout,
|
|
USBD_ERR *p_err)
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_INT08U data_opaque_len;
|
|
CPU_INT16U xfer_len;
|
|
CPU_BOOLEAN preamble_valid;
|
|
CPU_BOOLEAN latency_rely_valid;
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if ((p_buf == (void *)0) &&
|
|
(buf_len != 0)) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return (0u);
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return (0u);
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
if (p_ctrl->State != USBD_PHDC_STATE_CFG) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_ctrl->PreambleEn == DEF_DISABLED) { /* Chk that preamble is expected from host. */
|
|
*p_err = USBD_ERR_RX;
|
|
return (0u);
|
|
}
|
|
|
|
if (p_ctrl->RxDataXfersTotal != 0) {
|
|
*p_err = USBD_ERR_RX;
|
|
return (0u);
|
|
}
|
|
|
|
USBD_PHDC_OS_RdLock(class_nbr, timeout, p_err); /* Lock rd xfer. */
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (0u);
|
|
}
|
|
if (p_ctrl->PreambleEn == DEF_DISABLED) { /* Make sure preamble not been disabled while pending. */
|
|
*p_err = USBD_ERR_RX;
|
|
USBD_PHDC_OS_RdUnlock(class_nbr);
|
|
return (0u);
|
|
}
|
|
|
|
p_comm = p_ctrl->CommPtr;
|
|
|
|
xfer_len = USBD_BulkRx(p_ctrl->DevNbr,
|
|
p_comm->DataBulkOut,
|
|
p_ctrl->PreambleBufRxPtr,
|
|
USBD_PHDC_METADATA_MSG_PREAMBLE_MAX_LEN,
|
|
timeout,
|
|
p_err);
|
|
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
if (*p_err == USBD_ERR_OS_ABORT) { /* Xfer is aborted when preamble status change. */
|
|
*p_err = USBD_ERR_RX;
|
|
}
|
|
USBD_PHDC_OS_RdUnlock(class_nbr);
|
|
return (0u);
|
|
}
|
|
|
|
preamble_valid = DEF_NO;
|
|
if (xfer_len >= USBD_PHDC_METADATA_MSG_PREAMBLE_DFLT_LEN) { /* Validate metadata msg preamble. */
|
|
preamble_valid = Mem_Cmp(p_ctrl->PreambleBufRxPtr, /* Chk if preamble contain signature. */
|
|
USBD_PHDC_QOS_SIGNATURE,
|
|
USBD_PHDC_QOS_SIGNATURE_LEN);
|
|
|
|
/* Chk QoS, QoS encoding version and nbr xfers is valid.*/
|
|
latency_rely_valid = DEF_BIT_IS_SET(p_ctrl->RxLatencyRelyBitmap, p_ctrl->PreambleBufRxPtr[18]);
|
|
preamble_valid = (p_ctrl->PreambleBufRxPtr[16] > 0u ) ? preamble_valid : DEF_NO;
|
|
preamble_valid = (p_ctrl->PreambleBufRxPtr[17] == USBD_PHDC_QOS_ENCOD_VER) ? preamble_valid : DEF_NO;
|
|
preamble_valid = (latency_rely_valid == DEF_YES ) ? preamble_valid : DEF_NO;
|
|
}
|
|
|
|
if (preamble_valid == DEF_NO) {
|
|
USBD_PHDC_OS_RdUnlock(class_nbr);
|
|
USBD_EP_Stall(p_ctrl->DevNbr,
|
|
p_comm->DataBulkOut,
|
|
DEF_SET,
|
|
p_err);
|
|
*p_err = USBD_ERR_RX;
|
|
return (0u);
|
|
}
|
|
|
|
p_ctrl->RxDataXfersTotal = p_ctrl->PreambleBufRxPtr[16]; /* Update xfers ctr. */
|
|
p_ctrl->RxDataXfersCur = 0u;
|
|
|
|
*p_nbr_xfer = p_ctrl->PreambleBufRxPtr[16]; /* Return nbr xfers and opaque data to app. */
|
|
data_opaque_len = DEF_MIN(p_ctrl->PreambleBufRxPtr[19], buf_len);
|
|
if (data_opaque_len > 0) {
|
|
Mem_Copy(p_buf, (void *)&p_ctrl->PreambleBufRxPtr[20], data_opaque_len);
|
|
}
|
|
|
|
USBD_PHDC_OS_RdUnlock(class_nbr); /* Unlock rd xfer. */
|
|
|
|
*p_err = USBD_ERR_NONE;
|
|
|
|
return (data_opaque_len);
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_Rd()
|
|
*
|
|
* Description : Read PHDC data. This function is blocking.
|
|
*
|
|
* Argument(s) : class_nbr PHDC class instance number.
|
|
*
|
|
* p_buf Pointer to buffer that will contain data.
|
|
*
|
|
* buf_len Receive buffer length in octets.
|
|
*
|
|
* timeout Timeout (ms).
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE Data successfully received from host.
|
|
* USBD_ERR_INVALID_CLASS_STATE Invalid PHDC state.
|
|
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to class_nbr.
|
|
* USBD_ERR_NULL_PTR Invalid NULL receive buffer.
|
|
* USBD_ERR_RX A preamble is expected. USBD_PHDC_PreambleRd
|
|
* shall be called instead.
|
|
*
|
|
* ------ RETURNED BY USBD_BulkRx() : ------
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_EP_INVALID_NBR Invalid endpoint number.
|
|
* USBD_ERR_DEV_INVALID_STATE Bulk transfer can ONLY be used after the
|
|
* device is in configured state.
|
|
* USBD_ERR_EP_INVALID_TYPE Invalid endpoint type.
|
|
*
|
|
* --- RETURNED BY USBD_PHDC_OS_RdLock() ---
|
|
* USBD_ERR_NONE OS signal successfully acquired.
|
|
* USBD_OS_ERR_TIMEOUT OS signal NOT successfully acquired in the time
|
|
* specified by 'timeout_ms'.
|
|
* USBD_OS_ERR_ABORT OS signal aborted.
|
|
* USBD_OS_ERR_FAIL OS signal not acquired because another error.
|
|
*
|
|
* Return(s) : Number of octets received, if no error(s).
|
|
*
|
|
* 0, otherwise.
|
|
*
|
|
* Note(s) : (1) If host enable preamble while the application is pending on this function, the call will
|
|
* immediately return with error USBD_OS_ERR_ABORT.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
CPU_INT16U USBD_PHDC_Rd (CPU_INT08U class_nbr,
|
|
void *p_buf,
|
|
CPU_INT16U buf_len,
|
|
CPU_INT16U timeout,
|
|
USBD_ERR *p_err)
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_INT16U xfer_len;
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(0);
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return (0u);
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return (0u);
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
if (p_ctrl->State != USBD_PHDC_STATE_CFG) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return (0u);
|
|
}
|
|
|
|
if ((p_ctrl->PreambleEn == DEF_ENABLED) &&
|
|
(p_ctrl->RxDataXfersTotal == 0u )) {
|
|
*p_err = USBD_ERR_RX;
|
|
return (0u);
|
|
}
|
|
|
|
USBD_PHDC_OS_RdLock(class_nbr, timeout, p_err); /* Lock rd pipe. */
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return (0u);
|
|
}
|
|
if ((p_ctrl->PreambleEn == DEF_ENABLED) && /* Make sure preamble status not changed while pending. */
|
|
(p_ctrl->RxDataXfersTotal == 0u )) {
|
|
*p_err = USBD_ERR_RX;
|
|
USBD_PHDC_OS_RdUnlock(class_nbr);
|
|
return (0u);
|
|
}
|
|
|
|
p_comm = p_ctrl->CommPtr;
|
|
xfer_len = USBD_BulkRx( p_ctrl->DevNbr,
|
|
p_comm->DataBulkOut,
|
|
(CPU_INT08U *)p_buf,
|
|
buf_len,
|
|
timeout,
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
if (*p_err == USBD_ERR_OS_ABORT) { /* Xfer is aborted when preamble status change. */
|
|
*p_err = USBD_ERR_RX;
|
|
}
|
|
USBD_PHDC_OS_RdUnlock(class_nbr);
|
|
return (0u);
|
|
}
|
|
|
|
if (p_ctrl->PreambleEn == DEF_ENABLED) {
|
|
p_ctrl->RxDataXfersCur++; /* Update internal ctr. */
|
|
|
|
if (p_ctrl->RxDataXfersCur == p_ctrl->RxDataXfersTotal) {
|
|
p_ctrl->RxDataXfersTotal = 0u;
|
|
}
|
|
}
|
|
|
|
USBD_PHDC_OS_RdUnlock(class_nbr); /* Unlock rd pipe. */
|
|
|
|
return (xfer_len);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_PreambleWr()
|
|
*
|
|
* Description : Add PHDC metadata preamble to transmit priority queue.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* p_data_opaque Pointer to buffer that will supply opaque data.
|
|
*
|
|
* data_opaque_len Length of opaque data in octets.
|
|
*
|
|
* latency_rely Latency / reliability to be specified in preamble.
|
|
*
|
|
* nbr_xfers Number of transfer this preamble will apply to.
|
|
*
|
|
* timeout Timeout (ms).
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE Data successfully added to priority queue.
|
|
* USBD_ERR_NULL_PTR Invalid NULL transmit buffer.
|
|
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to class_nbr,
|
|
* data_opaque_len, nbr_xfers or latency_rely.
|
|
* USBD_ERR_TX Host doesn't expect a preamble.
|
|
*
|
|
* ------ RETURNED BY USBD_BulkTx() : ------
|
|
* USBD_ERR_NONE Data successfully transmitted.
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_DEV_INVALID_STATE Transfer type only available if device is in
|
|
* configured state.
|
|
* USBD_ERR_EP_INVALID_ADDR Invalid endpoint address.
|
|
* USBD_ERR_EP_INVALID_STATE Invalid endpoint state.
|
|
* USBD_ERR_EP_INVALID_TYPE Invalid endpoint type.
|
|
*
|
|
* - RETURNED BY USBD_PHDC_OS_WrBulkLock() -
|
|
* USBD_ERR_NONE OS signal successfully acquired.
|
|
* USBD_OS_ERR_TIMEOUT OS signal NOT successfully acquired in the time
|
|
* specified by 'timeout_ms'.
|
|
* USBD_OS_ERR_ABORT OS signal aborted.
|
|
* USBD_OS_ERR_FAIL OS signal not acquired because another error.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_PreambleWr (CPU_INT08U class_nbr,
|
|
void *p_data_opaque,
|
|
CPU_INT08U data_opaque_len,
|
|
LATENCY_RELY_FLAGS latency_rely,
|
|
CPU_INT08U nbr_xfers,
|
|
CPU_INT16U timeout,
|
|
USBD_ERR *p_err)
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_INT16U preamble_len;
|
|
CPU_INT16U data_opaque_max_len;
|
|
LATENCY_RELY_FLAGS latency_rely_flag;
|
|
CPU_BOOLEAN bulk_ep_xfer;
|
|
CPU_INT08U prio;
|
|
CPU_INT08U ep_log_nbr;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (nbr_xfers == 0u) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
if ((p_data_opaque == (void *)0) &&
|
|
(data_opaque_len > 0u )) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) { /* -------------------- CHK ARG ----------------------- */
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
|
|
if (p_ctrl->State != USBD_PHDC_STATE_CFG) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return;
|
|
}
|
|
|
|
p_comm = p_ctrl->CommPtr;
|
|
|
|
data_opaque_max_len = USBD_EP_MaxPktSizeGet(p_ctrl->DevNbr,
|
|
p_comm->DataBulkIn,
|
|
p_err);
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return;
|
|
}
|
|
|
|
data_opaque_max_len -= (USBD_PHDC_METADATA_MSG_PREAMBLE_DFLT_LEN + 1u);
|
|
data_opaque_max_len = DEF_MIN(data_opaque_max_len, 255u); /* Opaque data len field makes 8 bits in preamble. */
|
|
|
|
if (data_opaque_len > data_opaque_max_len) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
latency_rely_flag = latency_rely; /* Validate EP support QoS and metadata preamble. */
|
|
latency_rely_flag &= p_ctrl->TxLatencyRelyBitmap;
|
|
|
|
bulk_ep_xfer = DEF_BIT_IS_SET_ANY(latency_rely_flag, USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_IN);
|
|
|
|
if (bulk_ep_xfer == DEF_NO) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
prio = CPU_CntTrailZeros08(latency_rely) - 1;
|
|
ep_log_nbr = USBD_EP_ADDR_TO_LOG(p_ctrl->CommPtr->DataBulkIn);
|
|
|
|
if (p_ctrl->PreambleEn == DEF_DISABLED) {
|
|
*p_err = USBD_ERR_TX; /* Host did not enable preamble. Call USBD_PHDC_Wr. */
|
|
return;
|
|
}
|
|
|
|
if (p_ctrl->TxDataXfersTotal[prio] != 0u) {
|
|
*p_err = USBD_ERR_TX; /* Preamble not expected by host, call USBD_PHDC_Wr. */
|
|
return;
|
|
}
|
|
|
|
USBD_PHDC_OS_WrBulkLock(class_nbr, prio, timeout, p_err); /* Lock bulk wr pipe. */
|
|
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
return;
|
|
}
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_SET(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
p_ctrl->TxDataXfersTotal[prio] = nbr_xfers;
|
|
p_ctrl->TxDataXfersCur[prio] = 0u;
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
p_ctrl->PreambleBufTxPtr[16] = nbr_xfers; /* Prepare metadata message preamble. See note 1 of... */
|
|
p_ctrl->PreambleBufTxPtr[18] = latency_rely; /* ...USBD_PHDC_PreambleRd(). */
|
|
p_ctrl->PreambleBufTxPtr[19] = data_opaque_len;
|
|
|
|
if (data_opaque_len > 0) {
|
|
Mem_Copy(&p_ctrl->PreambleBufTxPtr[20],
|
|
p_data_opaque,
|
|
data_opaque_len);
|
|
}
|
|
|
|
preamble_len = USBD_PHDC_METADATA_MSG_PREAMBLE_DFLT_LEN + data_opaque_len;
|
|
|
|
USBD_BulkTx( p_ctrl->DevNbr,
|
|
p_comm->DataBulkIn,
|
|
(void *)p_ctrl->PreambleBufTxPtr,
|
|
preamble_len,
|
|
timeout,
|
|
DEF_YES,
|
|
p_err);
|
|
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
p_ctrl->TxDataXfersTotal[prio] = 0u;
|
|
p_ctrl->TxDataXfersCur[prio] = 0u;
|
|
|
|
USBD_PHDC_OS_WrBulkUnlock(class_nbr);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_Wr()
|
|
*
|
|
* Description : Write PHDC data.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* p_buf Pointer to buffer that will supply data.
|
|
*
|
|
* buf_len Data length in octets.
|
|
*
|
|
* latency_rely Latency / reliability of this transfer.
|
|
*
|
|
* timeout Timeout (ms).
|
|
*
|
|
* p_err Pointer to variable that will receive the return error code from this function :
|
|
*
|
|
* USBD_ERR_NONE Data successfully added to priority queue.
|
|
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to class_nbr or latency_rely.
|
|
* USBD_ERR_NULL_PTR Invalid null buffer.
|
|
* USBD_ERR_TX USBD_PHDC_PreambleWr shall be called first.
|
|
* USBD_ERR_INVALID_CLASS_STATE Invalid PHDC state.
|
|
* USBD_ERR_ALLOC Data queue is full.
|
|
*
|
|
* ------ RETURNED BY USBD_BulkTx() : ------
|
|
* USBD_ERR_NONE Data successfully transmitted.
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_DEV_INVALID_STATE Transfer type only available if device is in
|
|
* configured state.
|
|
* USBD_ERR_EP_INVALID_ADDR Invalid endpoint address.
|
|
* USBD_ERR_EP_INVALID_STATE Invalid endpoint state.
|
|
* USBD_ERR_EP_INVALID_TYPE Invalid endpoint type.
|
|
*
|
|
* ------ RETURNED BY USBD_IntrTx() : ------
|
|
* USBD_ERR_NONE Data successfully transmitted.
|
|
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
|
|
* USBD_ERR_DEV_INVALID_STATE Transfer type only available if device is in
|
|
* configured state.
|
|
* USBD_ERR_EP_INVALID_ADDR Invalid endpoint address.
|
|
* USBD_ERR_EP_INVALID_STATE Invalid endpoint state.
|
|
* USBD_ERR_EP_INVALID_TYPE Invalid endpoint type.
|
|
*
|
|
* - RETURNED BY USBD_PHDC_OS_WrBulkLock() -
|
|
* USBD_ERR_NONE OS signal successfully acquired.
|
|
* USBD_OS_ERR_TIMEOUT OS signal NOT successfully acquired in the time
|
|
* specified by 'timeout_ms'.
|
|
* USBD_OS_ERR_ABORT OS signal aborted.
|
|
* USBD_OS_ERR_FAIL OS signal not acquired because another error.
|
|
*
|
|
* - RETURNED BY USBD_PHDC_OS_WrIntrLock() -
|
|
* USBD_ERR_NONE OS signal successfully acquired.
|
|
* USBD_OS_ERR_TIMEOUT OS signal NOT successfully acquired in the time
|
|
* specified by 'timeout_ms'.
|
|
* USBD_OS_ERR_ABORT OS signal aborted.
|
|
* USBD_OS_ERR_FAIL OS signal not acquired because another error.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_Wr (CPU_INT08U class_nbr,
|
|
void *p_buf,
|
|
CPU_INT16U buf_len,
|
|
LATENCY_RELY_FLAGS latency_rely,
|
|
CPU_INT16U timeout,
|
|
USBD_ERR *p_err)
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_INT08U latency_rely_test;
|
|
CPU_BOOLEAN qos_supported;
|
|
CPU_INT08U prio;
|
|
CPU_INT08U ep_log_nbr;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED) /* ---------------- VALIDATE ARGUMENTS ---------------- */
|
|
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
|
|
CPU_SW_EXCEPTION(;);
|
|
}
|
|
|
|
if (p_buf == (void *)0) {
|
|
*p_err = USBD_ERR_NULL_PTR;
|
|
return;
|
|
}
|
|
|
|
if (latency_rely == 0u) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) { /* -------------------- CHK ARG ----------------------- */
|
|
*p_err = USBD_ERR_CLASS_INVALID_NBR;
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
if (p_ctrl->State != USBD_PHDC_STATE_CFG) {
|
|
*p_err = USBD_ERR_INVALID_CLASS_STATE;
|
|
return;
|
|
}
|
|
prio = CPU_CntTrailZeros08(latency_rely);
|
|
|
|
if (prio >= USBD_PHDC_XFER_PRIO_MAX) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
latency_rely_test = latency_rely;
|
|
|
|
DEF_BIT_CLR(latency_rely_test, DEF_BIT(prio));
|
|
|
|
if (latency_rely_test != DEF_BIT_NONE) {
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
qos_supported = DEF_BIT_IS_SET(p_ctrl->TxLatencyRelyBitmap, latency_rely);
|
|
|
|
if (qos_supported != DEF_YES) { /* Validate EP support QoS. */
|
|
*p_err = USBD_ERR_INVALID_ARG;
|
|
return;
|
|
}
|
|
|
|
p_comm = p_ctrl->CommPtr;
|
|
|
|
if (latency_rely == USBD_PHDC_LATENCY_LOW_RELY_GOOD) { /* Low latency xfer use intr EP. */
|
|
ep_log_nbr = USBD_EP_ADDR_TO_LOG(p_comm->DataIntrIn);
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_SET(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
USBD_PHDC_OS_WrIntrLock(class_nbr, timeout, p_err); /* Lock intr EP. */
|
|
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
return;
|
|
}
|
|
|
|
USBD_IntrTx(p_ctrl->DevNbr,
|
|
p_comm->DataIntrIn,
|
|
p_buf,
|
|
buf_len,
|
|
timeout,
|
|
DEF_YES,
|
|
p_err);
|
|
|
|
USBD_PHDC_OS_WrIntrUnlock(class_nbr); /* Unlock intr EP. */
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
} else { /* Very high, high and medium latency xfer use bulk EP. */
|
|
ep_log_nbr = USBD_EP_ADDR_TO_LOG(p_comm->DataBulkIn);
|
|
prio--; /* There are 5 QoS level on bulk IN EP. */
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
if ((p_ctrl->PreambleEn == DEF_ENABLED) &&
|
|
(p_ctrl->TxDataXfersTotal[prio] == 0u )) {
|
|
CPU_CRITICAL_EXIT();
|
|
*p_err = USBD_ERR_TX; /* App need to call USBD_PHDC_PreambleWr first. */
|
|
return;
|
|
}
|
|
|
|
DEF_BIT_SET(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
if (p_ctrl->PreambleEn == DEF_DISABLED) {
|
|
USBD_PHDC_OS_WrBulkLock(class_nbr, prio, timeout, p_err);
|
|
|
|
if (*p_err != USBD_ERR_NONE) {
|
|
if (*p_err != USBD_ERR_OS_TIMEOUT) {
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
USBD_BulkTx(p_ctrl->DevNbr,
|
|
p_comm->DataBulkIn,
|
|
p_buf,
|
|
buf_len,
|
|
timeout,
|
|
DEF_YES,
|
|
p_err);
|
|
|
|
if (p_ctrl->PreambleEn == DEF_ENABLED) {
|
|
if (*p_err == USBD_ERR_NONE) {
|
|
p_ctrl->TxDataXfersCur[prio]++;
|
|
/* Update xfers ctr. */
|
|
if (p_ctrl->TxDataXfersCur[prio] == p_ctrl->TxDataXfersTotal[prio]) {
|
|
p_ctrl->TxDataXfersCur[prio] = 0u;
|
|
p_ctrl->TxDataXfersTotal[prio] = 0u;
|
|
USBD_PHDC_OS_WrBulkUnlock(class_nbr); /* Unlock bulk EP if all xfer cmpleted under preamble. */
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
}
|
|
} else {
|
|
CPU_CRITICAL_ENTER();
|
|
DEF_BIT_CLR(p_ctrl->EP_DataStatus, DEF_BIT(ep_log_nbr));
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
USBD_PHDC_OS_WrBulkUnlock(class_nbr);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_Reset()
|
|
*
|
|
* Description : Reset PHDC instance.
|
|
*
|
|
* Argument(s) : class_nbr PHDC instance number.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
void USBD_PHDC_Reset (CPU_INT08U class_nbr)
|
|
{
|
|
CPU_INT16U cnt;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_ERR err;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
if (class_nbr >= USBD_PHDC_CtrlNbrNext) {
|
|
return;
|
|
}
|
|
|
|
p_ctrl = &USBD_PHDC_CtrlTbl[class_nbr];
|
|
|
|
USBD_EP_Abort(p_ctrl->DevNbr,
|
|
p_ctrl->CommPtr->DataBulkIn,
|
|
&err);
|
|
USBD_EP_Abort(p_ctrl->DevNbr,
|
|
p_ctrl->CommPtr->DataIntrIn,
|
|
&err);
|
|
USBD_EP_Abort(p_ctrl->DevNbr,
|
|
p_ctrl->CommPtr->DataBulkOut,
|
|
&err);
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
|
|
if (p_ctrl->PreambleEn != DEF_DISABLED) {
|
|
p_ctrl->PreambleEn = DEF_DISABLED;
|
|
|
|
if (p_ctrl->PreambleEnNotify != (USBD_PHDC_PREAMBLE_EN_NOTIFY)0) {
|
|
p_ctrl->PreambleEnNotify(class_nbr, DEF_DISABLED);
|
|
}
|
|
}
|
|
|
|
for (cnt = 0; cnt < (USBD_PHDC_XFER_PRIO_MAX - 1u); cnt++) {
|
|
p_ctrl->TxDataXfersTotal[cnt] = 0u;
|
|
p_ctrl->TxDataXfersCur[cnt] = 0u;
|
|
}
|
|
p_ctrl->EP_DataStatus = DEF_BIT_NONE;
|
|
p_ctrl->RxDataXfersTotal = 0u;
|
|
p_ctrl->RxDataXfersCur = 0u;
|
|
|
|
CPU_CRITICAL_EXIT();
|
|
|
|
USBD_PHDC_OS_Reset(class_nbr);
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
**********************************************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
**********************************************************************************************************
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* INTERFACE DRIVER FUNCTIONS
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_Conn()
|
|
*
|
|
* Description : Notify class that configuration is active.
|
|
*
|
|
* Argument(s) : cfg_nbr Configuration ix to add the interface.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface..
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_Conn (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
void *p_if_class_arg)
|
|
{
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
(void)cfg_nbr;
|
|
(void)dev_nbr;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
CPU_CRITICAL_ENTER();
|
|
p_comm->CtrlPtr->CommPtr = p_comm;
|
|
p_comm->CtrlPtr->State = USBD_PHDC_STATE_CFG;
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_Disconn()
|
|
*
|
|
* Description : Notify class that configuration is not active.
|
|
*
|
|
* Argument(s) : cfg_nbr Configuration ix to add the interface.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface..
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_Disconn (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
void *p_if_class_arg)
|
|
{
|
|
USBD_PHDC_COMM *p_comm;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
(void)cfg_nbr;
|
|
(void)dev_nbr;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
|
|
USBD_PHDC_Reset(p_comm->CtrlPtr->Nbr);
|
|
|
|
CPU_CRITICAL_ENTER();
|
|
p_comm->CtrlPtr->CommPtr = (USBD_PHDC_COMM *)0;
|
|
p_comm->CtrlPtr->State = USBD_PHDC_STATE_INIT;
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_SettingUpdate()
|
|
*
|
|
* Description : Notify class that interface alternative setting has been updated.
|
|
*
|
|
* Argument(s) : cfg_nbr Configuration ix to add the interface.
|
|
*
|
|
* if_nbr Interface number.
|
|
*
|
|
* if_alt_nbr Interface alternate setting number.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* p_if_alt_class_arg Pointer to class argument specific to alternate interface.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_SettingUpdate (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg)
|
|
{
|
|
USBD_PHDC_COMM *p_comm;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
CPU_SR_ALLOC();
|
|
|
|
|
|
(void)cfg_nbr;
|
|
(void)if_nbr;
|
|
(void)if_alt_nbr;
|
|
(void)dev_nbr;
|
|
(void)p_if_alt_class_arg;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
CPU_CRITICAL_ENTER();
|
|
p_ctrl->CommPtr = p_comm;
|
|
CPU_CRITICAL_EXIT();
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_IF_Desc()
|
|
*
|
|
* Description : Write extra interface descriptor.
|
|
*
|
|
* Argument(s) : dev_nbr Device number.
|
|
*
|
|
* cfg_nbr Configuration number.
|
|
*
|
|
* if_nbr Interface number.
|
|
*
|
|
* if_alt_nbr Interface alternate setting number.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* p_if_alt_class_arg Pointer to class argument specific to alternate interface.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_IF_Desc (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg)
|
|
|
|
{
|
|
CPU_INT08U cnt;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
|
|
|
|
(void)cfg_nbr;
|
|
(void)if_nbr;
|
|
(void)if_alt_nbr;
|
|
(void)p_if_alt_class_arg;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
|
|
/* Class fnct desc */
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_CLASS_FNCT_DESC_LEN);
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DESC_TYPE_CLASS_FNCT);
|
|
|
|
if (p_ctrl->IF_Params.DataFmt11073 == DEF_YES) {
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DATA_FMT_11073_20601);
|
|
} else {
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DATA_FMT_VENDOR);
|
|
}
|
|
|
|
if (p_ctrl->IF_Params.PreambleCapable == DEF_YES) {
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_PREAMBLE_CAPABLE);
|
|
} else {
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_PREAMBLE_NOT_CAPABLE);
|
|
}
|
|
/* Fnct ext desc */
|
|
USBD_DescWr08(dev_nbr,
|
|
USBD_PHDC_FUNCT_EXTN_DESC_DFLT_LEN + (p_ctrl->IF_Params.NbrDevSpecialization * 2));
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DESC_TYPE_FUNCT_EXTN_11073);
|
|
USBD_DescWr08(dev_nbr, 0x00); /* Reserved */
|
|
USBD_DescWr08(dev_nbr, p_ctrl->IF_Params.NbrDevSpecialization);
|
|
|
|
for (cnt = 0; cnt < p_ctrl->IF_Params.NbrDevSpecialization; cnt++) {
|
|
USBD_DescWr16(dev_nbr, p_ctrl->IF_Params.DevSpecialization[cnt]);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_IF_DescSizeGet()
|
|
*
|
|
* Description : Return size of extra interface descriptor.
|
|
*
|
|
* Argument(s) : dev_nbr Device number.
|
|
*
|
|
* cfg_nbr Configuration number.
|
|
*
|
|
* if_nbr Interface number.
|
|
*
|
|
* if_alt_nbr Interface alternate setting number.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* p_if_alt_class_arg Pointer to class argument specific to alternate interface.
|
|
*
|
|
* Return(s) : Size of extra interface descriptor in octets.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_INT16U USBD_PHDC_IF_DescSizeGet (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg)
|
|
{
|
|
CPU_INT16U desc_len;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
|
|
|
|
(void)dev_nbr;
|
|
(void)cfg_nbr;
|
|
(void)if_nbr;
|
|
(void)if_alt_nbr;
|
|
(void)p_if_alt_class_arg;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
|
|
desc_len = USBD_PHDC_CLASS_FNCT_DESC_LEN +
|
|
USBD_PHDC_FUNCT_EXTN_DESC_DFLT_LEN +
|
|
(p_ctrl->IF_Params.NbrDevSpecialization * 2);
|
|
|
|
return (desc_len);
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_EP_Desc()
|
|
*
|
|
* Description : Write extra endpoint descriptor.
|
|
*
|
|
* Argument(s) : dev_nbr Device number.
|
|
*
|
|
* cfg_nbr Configuration number.
|
|
*
|
|
* if_nbr Interface number.
|
|
*
|
|
* if_alt_nbr Interface alternate setting number.
|
|
*
|
|
* ep_addr Endpoint address.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* p_if_alt_class_arg Pointer to class argument specific to alternate interface.
|
|
*
|
|
* Return(s) : none.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static void USBD_PHDC_EP_Desc (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
CPU_INT08U ep_addr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg)
|
|
|
|
{
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
USBD_PHDC_EP_PARAMS *ep_params;
|
|
LATENCY_RELY_FLAGS latency_rely_bitmap;
|
|
|
|
|
|
(void)cfg_nbr;
|
|
(void)if_nbr;
|
|
(void)if_alt_nbr;
|
|
(void)p_if_alt_class_arg;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
|
|
if (ep_addr == p_comm->DataBulkIn) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_BULK_IN];
|
|
latency_rely_bitmap = p_ctrl->TxLatencyRelyBitmap;
|
|
DEF_BIT_CLR(latency_rely_bitmap, USBD_PHDC_RELY_LATENCY_FLAGS_EP_INTR_IN);
|
|
} else if (ep_addr == p_comm->DataBulkOut) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_BULK_OUT];
|
|
latency_rely_bitmap = p_ctrl->RxLatencyRelyBitmap;
|
|
} else if (ep_addr == p_comm->DataIntrIn) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_INTR_IN];
|
|
latency_rely_bitmap = p_ctrl->TxLatencyRelyBitmap;
|
|
DEF_BIT_CLR(latency_rely_bitmap, USBD_PHDC_RELY_LATENCY_FLAGS_EP_BULK_IN);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_QOS_DESC_LEN); /* QoS desc */
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DESC_TYPE_QOS);
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_QOS_ENCOD_VER);
|
|
USBD_DescWr08(dev_nbr, latency_rely_bitmap);
|
|
|
|
if (ep_params->DataOpaqueLen > 0) {
|
|
USBD_DescWr08(dev_nbr, /* Metadata descriptor */
|
|
USBD_PHDC_METADATA_DESC_LEN + ep_params->DataOpaqueLen);
|
|
USBD_DescWr08(dev_nbr, USBD_PHDC_DESC_TYPE_METADATA);
|
|
|
|
USBD_DescWr(dev_nbr,
|
|
ep_params->DataOpaquePtr,
|
|
ep_params->DataOpaqueLen);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* USBD_PHDC_EP_DescSizeGet()
|
|
*
|
|
* Description : Return size of extra endpoint descriptor.
|
|
*
|
|
* Argument(s) : dev_nbr Device number.
|
|
*
|
|
* cfg_nbr Configuration number.
|
|
*
|
|
* if_nbr Interface number.
|
|
*
|
|
* if_alt_nbr Interface alternate setting number.
|
|
*
|
|
* ep_addr Endpoint address.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* p_if_alt_class_arg Pointer to class argument specific to alternate interface.
|
|
*
|
|
* Return(s) : Size of extra endpoint descriptor in octets.
|
|
*
|
|
* Note(s) : none.
|
|
**********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_INT16U USBD_PHDC_EP_DescSizeGet (CPU_INT08U dev_nbr,
|
|
CPU_INT08U cfg_nbr,
|
|
CPU_INT08U if_nbr,
|
|
CPU_INT08U if_alt_nbr,
|
|
CPU_INT08U ep_addr,
|
|
void *p_if_class_arg,
|
|
void *p_if_alt_class_arg)
|
|
|
|
{
|
|
CPU_INT16U desc_len;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
USBD_PHDC_EP_PARAMS *ep_params;
|
|
|
|
|
|
(void)dev_nbr;
|
|
(void)cfg_nbr;
|
|
(void)if_nbr;
|
|
(void)if_alt_nbr;
|
|
(void)p_if_alt_class_arg;
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
|
|
if (ep_addr == p_comm->DataBulkIn) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_BULK_IN];
|
|
} else if (ep_addr == p_comm->DataBulkOut) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_BULK_OUT];
|
|
} else if (ep_addr == p_comm->DataIntrIn) {
|
|
ep_params = &p_ctrl->EP_Params[USBD_PHDC_EP_INTR_IN];
|
|
} else {
|
|
return (0);
|
|
}
|
|
|
|
desc_len = USBD_PHDC_QOS_DESC_LEN;
|
|
if (ep_params->DataOpaqueLen > 0) {
|
|
desc_len += USBD_PHDC_METADATA_DESC_LEN +
|
|
ep_params->DataOpaqueLen;
|
|
}
|
|
|
|
return (desc_len);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBD_PHDC_ClassReq()
|
|
*
|
|
* Description : Class request handler.
|
|
*
|
|
* Argument(s) : p_setup_req Pointer to setup request structure.
|
|
*
|
|
* p_if_class_arg Pointer to class argument specific to interface.
|
|
*
|
|
* Return(s) : DEF_OK, if NO error(s) occurred and request should be sent.
|
|
*
|
|
* DEF_FAIL, otherwise.
|
|
*
|
|
* Note(s) : none.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static CPU_BOOLEAN USBD_PHDC_ClassReq ( CPU_INT08U dev_nbr,
|
|
const USBD_SETUP_REQ *p_setup_req,
|
|
void *p_if_class_arg)
|
|
{
|
|
CPU_BOOLEAN rtn_val;
|
|
USBD_ERR err;
|
|
USBD_PHDC_CTRL *p_ctrl;
|
|
USBD_PHDC_COMM *p_comm;
|
|
|
|
|
|
p_comm = (USBD_PHDC_COMM *)p_if_class_arg;
|
|
p_ctrl = p_comm->CtrlPtr;
|
|
rtn_val = DEF_FAIL;
|
|
|
|
switch (p_setup_req->bRequest) {
|
|
case USBD_REQ_GET_STATUS: /* -------------------- GET STATUS ------------------- */
|
|
switch (p_ctrl->State) {
|
|
case USBD_PHDC_STATE_CFG:
|
|
if (p_setup_req->wValue != 0) {
|
|
break;
|
|
}
|
|
p_ctrl->CtrlStatusBufPtr[0] = (CPU_INT08U)( p_ctrl->EP_DataStatus & DEF_INT_08_MASK);
|
|
p_ctrl->CtrlStatusBufPtr[1] = (CPU_INT08U)((p_ctrl->EP_DataStatus >> 8u) & DEF_INT_08_MASK);
|
|
USBD_CtrlTx( dev_nbr,
|
|
(void *)&p_ctrl->CtrlStatusBufPtr[0],
|
|
2u,
|
|
USBD_PHDC_CTRL_REQ_TIMEOUT_mS,
|
|
DEF_FALSE,
|
|
&err);
|
|
if (err == USBD_ERR_NONE) {
|
|
rtn_val = DEF_OK;
|
|
}
|
|
break;
|
|
|
|
case USBD_PHDC_STATE_NONE:
|
|
case USBD_PHDC_STATE_INIT:
|
|
default :
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case USBD_REQ_CLEAR_FEATURE: /* ------------------ CLEAR FEATURE ------------------- */
|
|
switch (p_ctrl->State) {
|
|
case USBD_PHDC_STATE_CFG:
|
|
if (((CPU_INT08U) p_setup_req->wValue == USBD_PHDC_CLASS_SPEC_FEATURE_PHDC_QOS) &&
|
|
((CPU_INT08U)((p_setup_req->wValue & 0xFF00) >> 8) == 0x00)) {
|
|
|
|
/* Make sure metadata msg preambles are supported */
|
|
if (p_ctrl->IF_Params.PreambleCapable == DEF_YES) {
|
|
if (p_ctrl->PreambleEn != DEF_DISABLED) {
|
|
p_ctrl->PreambleEn = DEF_DISABLED;
|
|
if (p_ctrl->PreambleEnNotify != (USBD_PHDC_PREAMBLE_EN_NOTIFY)0) {
|
|
p_ctrl->PreambleEnNotify(p_ctrl->Nbr, DEF_DISABLED);
|
|
}
|
|
|
|
USBD_EP_Abort(dev_nbr,
|
|
p_ctrl->CommPtr->DataBulkOut,
|
|
&err);
|
|
}
|
|
rtn_val = DEF_OK;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case USBD_PHDC_STATE_NONE:
|
|
case USBD_PHDC_STATE_INIT:
|
|
default :
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case USBD_REQ_SET_FEATURE: /* ------------------- SET FEATURE -------------------- */
|
|
switch (p_ctrl->State) {
|
|
case USBD_PHDC_STATE_CFG:
|
|
if (((CPU_INT08U) p_setup_req->wValue == USBD_PHDC_CLASS_SPEC_FEATURE_PHDC_QOS) &&
|
|
((CPU_INT08U)((p_setup_req->wValue & 0xFF00) >> 8) == USBD_PHDC_QOS_ENCOD_VER)) {
|
|
|
|
/* Make sure metadata msg preambles are supported */
|
|
if (p_ctrl->IF_Params.PreambleCapable == DEF_YES) {
|
|
if (p_ctrl->PreambleEn != DEF_ENABLED) {
|
|
p_ctrl->PreambleEn = DEF_ENABLED;
|
|
if (p_ctrl->PreambleEnNotify != (USBD_PHDC_PREAMBLE_EN_NOTIFY)0) {
|
|
p_ctrl->PreambleEnNotify(p_ctrl->Nbr, DEF_ENABLED);
|
|
}
|
|
|
|
USBD_EP_Abort(dev_nbr,
|
|
p_ctrl->CommPtr->DataBulkOut,
|
|
&err);
|
|
}
|
|
rtn_val = DEF_OK;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case USBD_PHDC_STATE_NONE:
|
|
case USBD_PHDC_STATE_INIT:
|
|
default :
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default: /* Request not supported */
|
|
break;
|
|
}
|
|
|
|
return (rtn_val);
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************************************************
|
|
* MODULE END
|
|
**********************************************************************************************************
|
|
*/
|
|
|