Files
test/middleware/usb/uC-USBD/Class/Vendor/usbd_vendor.c
2025-11-07 20:19:23 +08:00

1936 lines
83 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 VENDOR CLASS
*
* Filename : usbd_vendor.c
* Version : V4.06.01
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define MICRIUM_SOURCE
#define USBD_VENDOR_MODULE
#include <lib_mem.h>
#include <lib_math.h>
#include "usbd_vendor.h"
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/* Max nbr of comm struct. */
#define USBD_VENDOR_COMM_NBR_MAX (USBD_VENDOR_CFG_MAX_NBR_DEV * \
USBD_VENDOR_CFG_MAX_NBR_CFG)
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* FORWARD DECLARATIONS
*********************************************************************************************************
*/
typedef struct usbd_vendor_ctrl USBD_VENDOR_CTRL; /* Forward declaration. */
/*
*********************************************************************************************************
* VENDOR CLASS STATES
*********************************************************************************************************
*/
typedef enum usbd_vendor_state { /* Vendor class states. */
USBD_VENDOR_STATE_NONE = 0,
USBD_VENDOR_STATE_INIT,
USBD_VENDOR_STATE_CFG
} USBD_VENDOR_STATE;
/*
*********************************************************************************************************
* VENDOR CLASS EP REQUIREMENTS DATA TYPE
*********************************************************************************************************
*/
/* -------------- VENDOR CLASS COMM INFO -------------- */
typedef struct usbd_vendor_comm {
USBD_VENDOR_CTRL *CtrlPtr; /* Ptr to ctrl info. */
/* Avail EP for comm: Bulk (and Intr) */
CPU_INT08U DataBulkInEpAddr;
CPU_INT08U DataBulkOutEpAddr;
CPU_INT08U IntrInEpAddr;
CPU_INT08U IntrOutEpAddr;
CPU_BOOLEAN DataBulkInActiveXfer;
CPU_BOOLEAN DataBulkOutActiveXfer;
CPU_BOOLEAN IntrInActiveXfer;
CPU_BOOLEAN IntrOutActiveXfer;
} USBD_VENDOR_COMM;
struct usbd_vendor_ctrl { /* -------------- VENDOR CLASS CTRL INFO -------------- */
CPU_INT08U DevNbr; /* Vendor class dev nbr. */
USBD_VENDOR_STATE State; /* Vendor class state. */
CPU_INT08U ClassNbr; /* Vendor class instance nbr. */
USBD_VENDOR_COMM *CommPtr; /* Vendor class comm info ptr. */
CPU_BOOLEAN IntrEn; /* Intr IN & OUT EPs en/dis flag. */
CPU_INT16U IntrInterval; /* Polling interval for intr IN & OUT EPs. */
USBD_VENDOR_REQ_FNCT VendorReqCallbackPtr; /* Ptr to app callback for vendor-specific req. */
/* Ptrs to callback and extra arg used for async comm. */
USBD_VENDOR_ASYNC_FNCT BulkRdAsyncFnct;
void *BulkRdAsyncArgPtr;
USBD_VENDOR_ASYNC_FNCT BulkWrAsyncFnct;
void *BulkWrAsyncArgPtr;
USBD_VENDOR_ASYNC_FNCT IntrRdAsyncFnct;
void *IntrRdAsyncArgPtr;
USBD_VENDOR_ASYNC_FNCT IntrWrAsyncFnct;
void *IntrWrAsyncArgPtr;
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED) /* Microsoft ext properties. */
USBD_MS_OS_EXT_PROPERTY MS_ExtPropertyTbl[USBD_VENDOR_CFG_MAX_NBR_MS_EXT_PROPERTY];
CPU_INT08U MS_ExtPropertyNext;
#endif
};
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/* Vendor class instances array. */
static USBD_VENDOR_CTRL USBD_Vendor_CtrlTbl[USBD_VENDOR_CFG_MAX_NBR_DEV];
static CPU_INT08U USBD_Vendor_CtrlNbrNext;
/* Vendor class comm array. */
static USBD_VENDOR_COMM USBD_Vendor_CommTbl[USBD_VENDOR_COMM_NBR_MAX];
static CPU_INT08U USBD_Vendor_CommNbrNext;
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
static void USBD_Vendor_Conn ( CPU_INT08U dev_nbr,
CPU_INT08U cfg_nbr,
void *p_if_class_arg);
static void USBD_Vendor_Disconn ( CPU_INT08U dev_nbr,
CPU_INT08U cfg_nbr,
void *p_if_class_arg);
static CPU_BOOLEAN USBD_Vendor_VendorReq ( CPU_INT08U dev_nbr,
const USBD_SETUP_REQ *p_setup_req,
void *p_if_class_arg);
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
static CPU_INT08U USBD_Vendor_MS_GetCompatID ( CPU_INT08U dev_nbr,
CPU_INT08U *p_sub_compat_id_ix);
static CPU_INT08U USBD_Vendor_MS_GetExtPropertyTbl( CPU_INT08U dev_nbr,
USBD_MS_OS_EXT_PROPERTY **pp_ext_property_tbl);
#endif
static void USBD_Vendor_RdAsyncCmpl ( CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err);
static void USBD_Vendor_WrAsyncCmpl ( CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err);
static void USBD_Vendor_IntrRdAsyncCmpl ( CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err);
static void USBD_Vendor_IntrWrAsyncCmpl ( CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err);
/*
*********************************************************************************************************
* VENDOR CLASS DRIVER
*********************************************************************************************************
*/
static USBD_CLASS_DRV USBD_Vendor_Drv = {
USBD_Vendor_Conn,
USBD_Vendor_Disconn,
DEF_NULL, /* Vendor does NOT use alternate interface(s). */
DEF_NULL,
DEF_NULL, /* Vendor does NOT use functional EP desc. */
DEF_NULL,
DEF_NULL, /* Vendor does NOT use functional IF desc. */
DEF_NULL,
DEF_NULL, /* Vendor does NOT handle std req with IF recipient. */
DEF_NULL, /* Vendor does NOT define class-specific req. */
USBD_Vendor_VendorReq,
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
USBD_Vendor_MS_GetCompatID,
USBD_Vendor_MS_GetExtPropertyTbl,
#endif
};
/*
*********************************************************************************************************
* LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
*********************************************************************************************************
* GLOBAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBD_Vendor_Init()
*
* Description : Initialize internal structures and variables used by the Vendor class.
*
* Argument(s) : p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Vendor class successfully initialized.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_Vendor_Init (USBD_ERR *p_err)
{
CPU_INT08U ix;
USBD_VENDOR_CTRL *p_ctrl;
USBD_VENDOR_COMM *p_comm;
#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_VENDOR_CFG_MAX_NBR_DEV; ix++) { /* Init vendor class struct. */
p_ctrl = &USBD_Vendor_CtrlTbl[ix];
p_ctrl->DevNbr = USBD_DEV_NBR_NONE;
p_ctrl->State = USBD_VENDOR_STATE_NONE;
p_ctrl->ClassNbr = USBD_CLASS_NBR_NONE;
p_ctrl->CommPtr = (USBD_VENDOR_COMM *)0;
p_ctrl->IntrEn = DEF_FALSE;
p_ctrl->IntrInterval = 0u;
p_ctrl->VendorReqCallbackPtr = (USBD_VENDOR_REQ_FNCT)0;
p_ctrl->BulkRdAsyncFnct = (USBD_VENDOR_ASYNC_FNCT)0;
p_ctrl->BulkRdAsyncArgPtr = (void *)0;
p_ctrl->BulkWrAsyncFnct = (USBD_VENDOR_ASYNC_FNCT)0;
p_ctrl->BulkWrAsyncArgPtr = (void *)0;
p_ctrl->IntrRdAsyncFnct = (USBD_VENDOR_ASYNC_FNCT)0;
p_ctrl->IntrRdAsyncArgPtr = (void *)0;
p_ctrl->IntrWrAsyncFnct = (USBD_VENDOR_ASYNC_FNCT)0;
p_ctrl->IntrWrAsyncArgPtr = (void *)0;
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
Mem_Clr(p_ctrl->MS_ExtPropertyTbl,
sizeof(p_ctrl->MS_ExtPropertyTbl));
p_ctrl->MS_ExtPropertyNext = 0u;
#endif
}
for (ix = 0u; ix < USBD_VENDOR_COMM_NBR_MAX; ix++) { /* Init vendor EP tbl. */
p_comm = &USBD_Vendor_CommTbl[ix];
p_comm->CtrlPtr = (USBD_VENDOR_CTRL *)0;
p_comm->DataBulkInEpAddr = USBD_EP_ADDR_NONE;
p_comm->DataBulkOutEpAddr = USBD_EP_ADDR_NONE;
p_comm->IntrInEpAddr = USBD_EP_ADDR_NONE;
p_comm->IntrOutEpAddr = USBD_EP_ADDR_NONE;
p_comm->DataBulkInActiveXfer = DEF_NO;
p_comm->DataBulkOutActiveXfer = DEF_NO;
p_comm->IntrInActiveXfer = DEF_NO;
p_comm->IntrOutActiveXfer = DEF_NO;
}
USBD_Vendor_CtrlNbrNext = 0u;
USBD_Vendor_CommNbrNext = 0u;
*p_err = USBD_ERR_NONE;
}
/*
*********************************************************************************************************
* USBD_Vendor_Add()
*
* Description : Add a new instance of the Vendor class.
*
* Argument(s) : intr_en Interrupt endpoints IN and OUT flag:
*
* DEF_TRUE Pair of interrupt endpoints added to interface.
* DEF_FALSE Pair of interrupt endpoints not added to interface.
*
* interval Endpoint interval in milliseconds. It must be a power of 2.
*
* req_callback Vendor-specific request callback.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Vendor class instance successfully added.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'intr_en'/'interval'.
* USBD_ERR_ALLOC No more class instance structure available.
*
*
* Return(s) : Class instance number, if NO error(s).
*
* USBD_CLASS_NBR_NONE, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT08U USBD_Vendor_Add (CPU_BOOLEAN intr_en,
CPU_INT16U interval,
USBD_VENDOR_REQ_FNCT req_callback,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_INT08U vendor_class_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(0);
}
if (intr_en == DEF_TRUE) {
if (MATH_IS_PWR2(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();
vendor_class_nbr = USBD_Vendor_CtrlNbrNext; /* Alloc new vendor class instance nbr. */
if (vendor_class_nbr >= USBD_VENDOR_CFG_MAX_NBR_DEV) { /* Chk if max nbr of instances reached. */
CPU_CRITICAL_EXIT();
*p_err = USBD_ERR_VENDOR_INSTANCE_ALLOC;
return (USBD_CLASS_NBR_NONE);
}
USBD_Vendor_CtrlNbrNext++; /* Next avail vendor class instance nbr. */
CPU_CRITICAL_EXIT();
p_ctrl = &USBD_Vendor_CtrlTbl[vendor_class_nbr]; /* Get vendor class instance. */
/* Store vendor class instance info. */
p_ctrl->IntrEn = intr_en; /* Intr EPs en/dis. */
p_ctrl->IntrInterval = interval; /* Polling interval for intr EPs. */
p_ctrl->VendorReqCallbackPtr = req_callback; /* App callback for vendor-specific req. */
*p_err = USBD_ERR_NONE;
return (vendor_class_nbr);
}
/*
*********************************************************************************************************
* USBD_Vendor_CfgAdd()
*
* Description : Add Vendor class instance into the specified configuration (see Note #1).
*
* Argument(s) : class_nbr Class instance number.
*
* dev_nbr Device number.
*
* cfg_nbr Configuration index to add Vendor class instance to.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Vendor class instance successfully added.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'/
* 'dev_nbr'.
* USBD_ERR_ALLOC No more class communication structure available.
*
* ---------- RETURNED BY USBD_IF_Add() : ----------
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_desc'/
* 'class_desc_size'.
* USBD_ERR_NULL_PTR Argument 'p_class_drv'/'p_class_drv->Conn'/
* 'p_class_drv->Disconn' passed a NULL
* pointer.
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
* USBD_ERR_DEV_INVALID_STATE Invalid device state.
* USBD_ERR_CFG_INVALID_NBR Invalid configuration number.
* USBD_ERR_IF_ALLOC Interfaces NOT available.
* USBD_ERR_IF_ALT_ALLOC Interface alternate settings NOT available.
*
* ---------- RETURNED BY USBD_BulkAdd() : ----------
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'max_pkt_len'.
*
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
* USBD_ERR_CFG_INVALID_NBR Invalid configuration number.
* USBD_ERR_IF_INVALID_NBR Invalid interface number.
* USBD_ERR_EP_NONE_AVAIL Physical endpoint NOT available.
* USBD_ERR_EP_ALLOC Endpoints NOT available.
*
* ---------- RETURNED BY USBD_IntrAdd() : ----------
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'interval'/
* 'max_pkt_len'.
*
* USBD_ERR_DEV_INVALID_NBR Invalid device number.
* USBD_ERR_CFG_INVALID_NBR Invalid configuration number.
* USBD_ERR_IF_INVALID_NBR Invalid interface number.
* USBD_ERR_EP_NONE_AVAIL Physical endpoint NOT available.
* USBD_ERR_EP_ALLOC Endpoints NOT available.
*
* Return(s) : none.
*
* Note(s) : (1) Called several times, it allows to create multiple instances and multiple configurations.
* For instance, the following architecture could be created :
*
* HS
* |-- Configuration 0
* |-- Interface 0 (Vendor 0)
* |-- Configuration 1
* |-- Interface 0 (Vendor 0)
* |-- Interface 1 (Vendor 1)
*
* In that example, there are 2 instances of Vendor class: 'Vendor 0' and '1', and 2
* possible configurations: 'Configuration 0' and '1'. 'Configuration 1' is composed
* of 2 interfaces. Each class instance has an association with one of the interfaces.
* If 'Configuration 1' is activated by the host, it allows the host to access 2
* different functionalities offered by the device.
*
* (2) Configuration Descriptor corresponding to a Vendor-specific device has the following
* format :
*
* Configuration Descriptor
* |-- Interface Descriptor (Vendor class)
* |-- Endpoint Descriptor (Bulk OUT)
* |-- Endpoint Descriptor (Bulk IN)
* |-- Endpoint Descriptor (Interrupt OUT) - optional
* |-- Endpoint Descriptor (Interrupt IN) - optional
*********************************************************************************************************
*/
void USBD_Vendor_CfgAdd (CPU_INT08U class_nbr,
CPU_INT08U dev_nbr,
CPU_INT08U cfg_nbr,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
USBD_VENDOR_COMM *p_comm;
CPU_INT08U if_nbr;
CPU_INT08U ep_addr;
CPU_INT16U comm_nbr;
CPU_INT16U intr_interval;
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(;);
}
#endif
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return;
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get vendor class instance. */
CPU_CRITICAL_ENTER();
if ((p_ctrl->DevNbr != USBD_DEV_NBR_NONE) && /* Chk if class is associated with a different dev. */
(p_ctrl->DevNbr != dev_nbr)) {
CPU_CRITICAL_EXIT();
*p_err = USBD_ERR_INVALID_ARG;
return;
}
p_ctrl->DevNbr = dev_nbr;
comm_nbr = USBD_Vendor_CommNbrNext; /* Alloc new vendor class comm info nbr. */
if (comm_nbr >= USBD_VENDOR_COMM_NBR_MAX) { /* Chk if max nbr of comm instances reached. */
USBD_Vendor_CtrlNbrNext--;
CPU_CRITICAL_EXIT();
*p_err = USBD_ERR_VENDOR_INSTANCE_ALLOC;
return;
}
USBD_Vendor_CommNbrNext++; /* Next avail vendor class comm info nbr. */
CPU_CRITICAL_EXIT();
p_comm = &USBD_Vendor_CommTbl[comm_nbr]; /* Get vendor class comm info. */
/* -------------- CFG DESC CONSTRUCTION --------------- */
/* See Note #2. */
/* Add vendor IF desc to cfg desc. */
if_nbr = USBD_IF_Add( dev_nbr,
cfg_nbr,
&USBD_Vendor_Drv,
(void *)p_comm, /* EP comm struct associated to Vendor IF. */
(void *)0,
USBD_CLASS_CODE_VENDOR_SPECIFIC,
USBD_SUBCLASS_CODE_VENDOR_SPECIFIC,
USBD_PROTOCOL_CODE_VENDOR_SPECIFIC,
"Vendor-specific class",
p_err);
if (*p_err != USBD_ERR_NONE) {
return;
}
/* Add bulk IN EP desc. */
ep_addr = USBD_BulkAdd(dev_nbr,
cfg_nbr,
if_nbr,
0u,
DEF_YES,
0u,
p_err);
if (*p_err != USBD_ERR_NONE) {
return;
}
p_comm->DataBulkInEpAddr = ep_addr; /* Store bulk IN EP addr. */
/* Add bulk OUT EP desc. */
ep_addr = USBD_BulkAdd(dev_nbr,
cfg_nbr,
if_nbr,
0u,
DEF_NO,
0u,
p_err);
if (*p_err != USBD_ERR_NONE) {
return;
}
p_comm->DataBulkOutEpAddr = ep_addr; /* Store bulk OUT EP addr. */
if (p_ctrl->IntrEn == DEF_TRUE) {
if (DEF_BIT_IS_CLR(cfg_nbr, USBD_CFG_NBR_SPD_BIT) == DEF_YES) {
intr_interval = p_ctrl->IntrInterval; /* In FS, bInterval in frames. */
} else {
intr_interval = p_ctrl->IntrInterval * 8u; /* In HS, bInterval in microframes. */
}
/* Add intr IN EP desc. */
ep_addr = USBD_IntrAdd(dev_nbr,
cfg_nbr,
if_nbr,
0u,
DEF_YES,
0u,
intr_interval,
p_err);
if (*p_err != USBD_ERR_NONE) {
return;
}
p_comm->IntrInEpAddr = ep_addr; /* Store intr IN EP addr. */
/* Add intr OUT EP desc. */
ep_addr = USBD_IntrAdd(dev_nbr,
cfg_nbr,
if_nbr,
0u,
DEF_NO,
0u,
intr_interval,
p_err);
if (*p_err != USBD_ERR_NONE) {
return;
}
p_comm->IntrOutEpAddr = ep_addr; /* Store intr OUT EP addr. */
}
/* Store vendor class instance info. */
CPU_CRITICAL_ENTER();
p_ctrl->State = USBD_VENDOR_STATE_INIT; /* Set class instance to init state. */
p_ctrl->ClassNbr = class_nbr;
p_ctrl->CommPtr = (USBD_VENDOR_COMM *)0;
CPU_CRITICAL_EXIT();
p_comm->CtrlPtr = p_ctrl; /* Save ref to vendor class instance ctrl struct. */
*p_err = USBD_ERR_NONE;
}
/*
*********************************************************************************************************
* USBD_Vendor_IsConn()
*
* Description : Get the vendor class connection state.
*
* Argument(s) : class_nbr Class instance number.
*
* Return(s) : DEF_YES, if Vendor class is connected.
*
* DEF_NO, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_BOOLEAN USBD_Vendor_IsConn (CPU_INT08U class_nbr)
{
USBD_VENDOR_CTRL *p_ctrl;
USBD_DEV_STATE state;
USBD_ERR err;
/* ------------------- VALIDATE ARG ------------------- */
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED)
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
return (DEF_NO);
}
#endif
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
state = USBD_DevStateGet(p_ctrl->DevNbr, &err); /* Get dev state. */
if ((err == USBD_ERR_NONE ) &&
(state == USBD_DEV_STATE_CONFIGURED) &&
(p_ctrl->State == USBD_VENDOR_STATE_CFG )) {
return (DEF_YES);
} else {
return (DEF_NO);
}
}
/*
*********************************************************************************************************
* USBD_Vendor_MS_ExtPropertyAdd()
*
* Description : Add a Microsoft OS extended property to this vendor class instance.
*
* Argument(s) : class_nbr Class instance number.
*
* property_type Property type. See Note (2).
*
* USBD_MS_OS_PROPERTY_TYPE_REG_SZ
* USBD_MS_OS_PROPERTY_TYPE_REG_EXPAND_SZ
* USBD_MS_OS_PROPERTY_TYPE_REG_BINARY
* USBD_MS_OS_PROPERTY_TYPE_REG_DWORD_LITTLE_ENDIAN
* USBD_MS_OS_PROPERTY_TYPE_REG_DWORD_BIG_ENDIAN
* USBD_MS_OS_PROPERTY_TYPE_REG_LINK
* USBD_MS_OS_PROPERTY_TYPE_REG_MULTI_SZ
*
* p_property_name Pointer to buffer that contains property name.
*
* property_name_len Length of property name in octets.
*
* p_property Pointer to buffer that contains property.
*
* property_len Length of property in octets.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE MS extended property successfully set.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr',
* 'property_type'.
* USBD_ERR_NULL_PTR Argument 'p_property_name', 'p_property'
* passed a NULL.
*
* Return(s) : None.
*
* Note(s) : (1) For more information on Microsoft OS descriptors, see
* 'http://msdn.microsoft.com/en-us/library/windows/hardware/gg463179.aspx'.
*
* (2) For more information on property types, refer to "Table 3. Property Data Types" of
* "Extended Properties OS Feature Descriptor Specification" document provided by
* Microsoft available at
* 'http://msdn.microsoft.com/en-us/library/windows/hardware/gg463179.aspx'.
*********************************************************************************************************
*/
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
void USBD_Vendor_MS_ExtPropertyAdd ( CPU_INT08U class_nbr,
CPU_INT08U property_type,
const CPU_INT08U *p_property_name,
CPU_INT16U property_name_len,
const CPU_INT08U *p_property,
CPU_INT32U property_len,
USBD_ERR *p_err)
{
CPU_INT08U ext_property_nbr;
USBD_VENDOR_CTRL *p_ctrl;
USBD_MS_OS_EXT_PROPERTY *p_ext_property;
CPU_SR_ALLOC();
/* ------------------- VALIDATE ARG ------------------- */
#if (USBD_CFG_ERR_ARG_CHK_EXT_EN == DEF_ENABLED)
if (p_err == (USBD_ERR *)0) { /* Validate error ptr. */
CPU_SW_EXCEPTION(;);
}
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_INVALID_ARG;
return;
}
if ((property_type != USBD_MS_OS_PROPERTY_TYPE_REG_SZ ) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_EXPAND_SZ ) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_BINARY ) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_DWORD_LITTLE_ENDIAN) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_DWORD_BIG_ENDIAN ) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_LINK ) &&
(property_type != USBD_MS_OS_PROPERTY_TYPE_REG_MULTI_SZ)) {
*p_err = USBD_ERR_INVALID_ARG;
return;
}
if ((p_property_name == (const CPU_INT08U *)0) &&
(property_name_len != 0u)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
if ((p_property == (const CPU_INT08U *)0) &&
(property_len != 0u)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
#endif
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
CPU_CRITICAL_ENTER();
ext_property_nbr = p_ctrl->MS_ExtPropertyNext;
if (ext_property_nbr >= USBD_VENDOR_CFG_MAX_NBR_MS_EXT_PROPERTY) {
CPU_CRITICAL_EXIT();
*p_err = USBD_ERR_ALLOC;
return;
}
p_ctrl->MS_ExtPropertyNext++;
p_ext_property = &p_ctrl->MS_ExtPropertyTbl[ext_property_nbr];
p_ext_property->PropertyType = property_type;
p_ext_property->PropertyNamePtr = p_property_name;
p_ext_property->PropertyNameLen = property_name_len;
p_ext_property->PropertyPtr = p_property;
p_ext_property->PropertyLen = property_len;
CPU_CRITICAL_EXIT();
*p_err = USBD_ERR_NONE;
}
#endif
/*
*********************************************************************************************************
* USBD_Vendor_Rd()
*
* Description : Receive data from host through Bulk OUT endpoint. This function is blocking.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to receive buffer.
*
* buf_len Receive buffer length in octets.
*
* timeout Timeout in milliseconds.
*
* 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_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* ------ 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.
*
* Return(s) : Number of octets received, if NO error(s).
*
* 0, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U USBD_Vendor_Rd (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT16U timeout,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_INT32U xfer_len;
CPU_BOOLEAN conn;
#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_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return (0u);
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return (0u);
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
xfer_len = USBD_BulkRx(p_ctrl->DevNbr,
p_ctrl->CommPtr->DataBulkOutEpAddr,
p_buf,
buf_len,
timeout,
p_err);
if (*p_err != USBD_ERR_NONE) {
return (0u);
}
return (xfer_len);
}
/*
*********************************************************************************************************
* USBD_Vendor_Wr()
*
* Description : Send data to host through Bulk IN endpoint. This function is blocking.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to transmit buffer.
*
* buf_len Transmit buffer length in octets.
*
* timeout Timeout in milliseconds.
*
* end End-of-transfer flag (see Note #1).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Data successfully sent to host.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* ------ RETURNED BY USBD_BulkTx() : ------
* 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.
*
* Return(s) : Number of octets sent, if NO error(s).
*
* 0, otherwise.
*
* Note(s) : (1) If end-of-transfer is set and transfer length is multiple of maximum packet size,
* a zero-length packet is transferred to indicate the end of transfer to the host.
*********************************************************************************************************
*/
CPU_INT32U USBD_Vendor_Wr (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT16U timeout,
CPU_BOOLEAN end,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_INT32U xfer_len;
CPU_BOOLEAN conn;
#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_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return (0u);
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return (0u);
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
xfer_len = USBD_BulkTx(p_ctrl->DevNbr,
p_ctrl->CommPtr->DataBulkInEpAddr,
p_buf,
buf_len,
timeout,
end,
p_err);
if (*p_err != USBD_ERR_NONE) {
return (0u);
}
return (xfer_len);
}
/*
*********************************************************************************************************
* USBD_Vendor_RdAsync()
*
* Description : Receive data from host through Bulk OUT endpoint. This function is non-blocking.
* It returns immediately after transfer preparation. Upon transfer completion, a
* callback provided by the application will be called to finalize the transfer.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to receive buffer.
*
* buf_len Receive buffer length in octets.
*
* async_fnct Receive callback.
*
* p_async_arg Additional argument provided by application for receive callback.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Transfer successfully prepared.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* --- RETURNED BY USBD_BulkRxAsync() : ---
* 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.
* USBD_ERR_EP_INVALID_STATE Endpoint not opened.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_Vendor_RdAsync (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
USBD_VENDOR_ASYNC_FNCT async_fnct,
void *p_async_arg,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_BOOLEAN conn;
#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) &&
(buf_len != 0)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
#endif
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return;
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return;
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
p_ctrl->BulkRdAsyncFnct = async_fnct;
p_ctrl->BulkRdAsyncArgPtr = p_async_arg;
if (p_ctrl->CommPtr->DataBulkOutActiveXfer == DEF_NO) { /* Check if another xfer is already in progress. */
p_ctrl->CommPtr->DataBulkOutActiveXfer = DEF_YES; /* Indicate that a xfer is in progres. */
USBD_BulkRxAsync( p_ctrl->DevNbr,
p_ctrl->CommPtr->DataBulkOutEpAddr,
p_buf,
buf_len,
USBD_Vendor_RdAsyncCmpl,
(void *)p_ctrl,
p_err);
if (*p_err != USBD_ERR_NONE) {
p_ctrl->CommPtr->DataBulkOutActiveXfer = DEF_NO;
}
} else {
*p_err = USBD_ERR_CLASS_XFER_IN_PROGRESS;
}
}
/*
*********************************************************************************************************
* USBD_Vendor_WrAsync()
*
* Description : Send data to host through Bulk IN endpoint. This function is non-blocking.
* It returns immediately after transfer preparation. Upon transfer completion, a
* callback provided by the application will be called to finalize the transfer.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to transmit buffer.
*
* buf_len Transmit buffer length in octets.
*
* async_fnct Transmit callback.
*
* p_async_arg Additional argument provided by application for transmit callback.
*
* end End-of-transfer flag (see Note #1).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Transfer successfully prepared.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* --- RETURNED BY USBD_BulkTxAsync() : ---
* 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.
* USBD_ERR_EP_INVALID_STATE Endpoint not opened.
*
* Return(s) : none.
*
* Note(s) : (1) If end-of-transfer is set and transfer length is multiple of maximum packet size,
* a zero-length packet is transferred to indicate the end of transfer to the host.
*********************************************************************************************************
*/
void USBD_Vendor_WrAsync (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
USBD_VENDOR_ASYNC_FNCT async_fnct,
void *p_async_arg,
CPU_BOOLEAN end,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_BOOLEAN conn;
#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) &&
(buf_len != 0)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
#endif
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return;
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return;
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
p_ctrl->BulkWrAsyncFnct = async_fnct;
p_ctrl->BulkWrAsyncArgPtr = p_async_arg;
if (p_ctrl->CommPtr->DataBulkInActiveXfer == DEF_NO) { /* Check if another xfer is already in progress. */
p_ctrl->CommPtr->DataBulkInActiveXfer = DEF_YES; /* Indicate that a xfer is in progres. */
USBD_BulkTxAsync( p_ctrl->DevNbr,
p_ctrl->CommPtr->DataBulkInEpAddr,
p_buf,
buf_len,
USBD_Vendor_WrAsyncCmpl,
(void *)p_ctrl,
end,
p_err);
if (*p_err != USBD_ERR_NONE) {
p_ctrl->CommPtr->DataBulkInActiveXfer = DEF_NO;
}
} else {
*p_err = USBD_ERR_CLASS_XFER_IN_PROGRESS;
}
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrRd()
*
* Description : Receive data from host through Interrupt OUT endpoint. This function is blocking.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to receive buffer.
*
* buf_len Receive buffer length in octets.
*
* timeout Timeout in milliseconds.
*
* 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_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* ------ RETURNED BY USBD_IntrRx() : ------
* 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.
*
* Return(s) : Number of octets received, if NO error(s).
*
* 0, otherwise.
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_INT32U USBD_Vendor_IntrRd (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT16U timeout,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_INT32U xfer_len;
CPU_BOOLEAN conn;
#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_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return (0u);
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return (0u);
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
xfer_len = USBD_IntrRx(p_ctrl->DevNbr,
p_ctrl->CommPtr->IntrOutEpAddr,
p_buf,
buf_len,
timeout,
p_err);
if (*p_err != USBD_ERR_NONE) {
return (0u);
}
return (xfer_len);
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrWr()
*
* Description : Send data to host through Interrupt IN endpoint. This function is blocking.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to transmit buffer.
*
* buf_len Transmit buffer length in octets.
*
* timeout Timeout in milliseconds.
*
* end End-of-transfer flag (see Note #1).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Data successfully sent to host.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* ------ RETURNED BY USBD_IntrTx() : ------
* 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.
*
* Return(s) : Number of octets sent, if NO error(s).
*
* 0, otherwise.
*
* Note(s) : (1) If end-of-transfer is set and transfer length is multiple of maximum packet size,
* a zero-length packet is transferred to indicate the end of transfer to the host.
*********************************************************************************************************
*/
CPU_INT32U USBD_Vendor_IntrWr (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT16U timeout,
CPU_BOOLEAN end,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_INT32U xfer_len;
CPU_BOOLEAN conn;
#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_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return (0u);
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return (0u);
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
xfer_len = USBD_IntrTx(p_ctrl->DevNbr,
p_ctrl->CommPtr->IntrInEpAddr,
p_buf,
buf_len,
timeout,
end,
p_err);
if (*p_err != USBD_ERR_NONE) {
return (0u);
}
return (xfer_len);
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrRdAsync()
*
* Description : Receive data from host through Interrupt OUT endpoint. This function is non-blocking.
* It returns immediately after transfer preparation. Upon transfer completion, a
* callback provided by the application will be called to finalize the transfer.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to receive buffer.
*
* buf_len Receive buffer length in octets.
*
* async_fnct Receive callback.
*
* p_async_arg Additional argument provided by application for receive callback.
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Transfer successfully prepared.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* --- RETURNED BY USBD_IntrRxAsync() : ---
* 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.
* USBD_ERR_EP_INVALID_STATE Endpoint not opened.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
void USBD_Vendor_IntrRdAsync (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
USBD_VENDOR_ASYNC_FNCT async_fnct,
void *p_async_arg,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_BOOLEAN conn;
#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) &&
(buf_len != 0)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
#endif
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return;
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return;
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
p_ctrl->IntrRdAsyncFnct = async_fnct;
p_ctrl->IntrRdAsyncArgPtr = p_async_arg;
if (p_ctrl->CommPtr->IntrOutActiveXfer == DEF_NO) { /* Check if another xfer is already in progress. */
p_ctrl->CommPtr->IntrOutActiveXfer = DEF_YES; /* Indicate that a xfer is in progres. */
USBD_IntrRxAsync( p_ctrl->DevNbr,
p_ctrl->CommPtr->IntrOutEpAddr,
p_buf,
buf_len,
USBD_Vendor_IntrRdAsyncCmpl,
(void *)p_ctrl,
p_err);
if (*p_err != USBD_ERR_NONE) {
p_ctrl->CommPtr->IntrOutActiveXfer = DEF_NO;
}
} else {
*p_err = USBD_ERR_CLASS_XFER_IN_PROGRESS;
}
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrWrAsync()
*
* Description : Send data to host through Interrupt IN endpoint. This function is non-blocking.
* It returns immediately after transfer preparation. Upon transfer completion, a
* callback provided by the application will be called to finalize the transfer.
*
* Argument(s) : class_nbr Class instance number.
*
* p_buf Pointer to transmit buffer.
*
* buf_len Transmit buffer length in octets.
*
* async_fnct Transmit callback.
*
* p_async_arg Additional argument provided by application for transmit callback.
*
* end End-of-transfer flag (see Note #1).
*
* p_err Pointer to variable that will receive the return error code from this function :
*
* USBD_ERR_NONE Transfer successfully prepared.
* USBD_ERR_NULL_PTR Argument 'p_buf' passed a NULL pointer.
* USBD_ERR_INVALID_ARG Invalid argument(s) passed to 'class_nbr'.
* USBD_ERR_INVALID_CLASS_STATE Invalid class state.
*
* --- RETURNED BY USBD_IntrTxAsync() : ---
* 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.
* USBD_ERR_EP_INVALID_STATE Endpoint not opened.
*
* Return(s) : none.
*
* Note(s) : (1) If end-of-transfer is set and transfer length is multiple of maximum packet size,
* a zero-length packet is transferred to indicate the end of transfer to the host.
*********************************************************************************************************
*/
void USBD_Vendor_IntrWrAsync (CPU_INT08U class_nbr,
void *p_buf,
CPU_INT32U buf_len,
USBD_VENDOR_ASYNC_FNCT async_fnct,
void *p_async_arg,
CPU_BOOLEAN end,
USBD_ERR *p_err)
{
USBD_VENDOR_CTRL *p_ctrl;
CPU_BOOLEAN conn;
#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) &&
(buf_len != 0)) {
*p_err = USBD_ERR_NULL_PTR;
return;
}
#endif
if (class_nbr >= USBD_Vendor_CtrlNbrNext) {
*p_err = USBD_ERR_CLASS_INVALID_NBR;
return;
}
conn = USBD_Vendor_IsConn(class_nbr);
if (conn != DEF_YES) { /* Chk class state. */
*p_err = USBD_ERR_INVALID_CLASS_STATE;
return;
}
p_ctrl = &USBD_Vendor_CtrlTbl[class_nbr]; /* Get Vendor class instance ctrl struct. */
p_ctrl->IntrWrAsyncFnct = async_fnct;
p_ctrl->IntrWrAsyncArgPtr = p_async_arg;
if (p_ctrl->CommPtr->IntrInActiveXfer == DEF_NO) { /* Check if another xfer is already in progress. */
p_ctrl->CommPtr->IntrInActiveXfer = DEF_YES; /* Indicate that a xfer is in progres. */
USBD_IntrTxAsync( p_ctrl->DevNbr,
p_ctrl->CommPtr->IntrInEpAddr,
p_buf,
buf_len,
USBD_Vendor_IntrWrAsyncCmpl,
(void *)p_ctrl,
end,
p_err);
if (*p_err != USBD_ERR_NONE) {
p_ctrl->CommPtr->IntrInActiveXfer = DEF_NO;
}
} else {
*p_err = USBD_ERR_CLASS_XFER_IN_PROGRESS;
}
}
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* USBD_Vendor_Conn()
*
* Description : Notify class that configuration is active.
*
* Argument(s) : dev_nbr Device number.
*
* cfg_nbr Configuration index to add the interface to.
*
* p_if_class_arg Pointer to class argument.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_Conn (CPU_INT08U dev_nbr,
CPU_INT08U cfg_nbr,
void *p_if_class_arg)
{
USBD_VENDOR_COMM *p_comm;
CPU_SR_ALLOC();
(void)dev_nbr;
(void)cfg_nbr;
p_comm = (USBD_VENDOR_COMM *)p_if_class_arg;
CPU_CRITICAL_ENTER();
p_comm->CtrlPtr->CommPtr = p_comm;
p_comm->CtrlPtr->State = USBD_VENDOR_STATE_CFG;
CPU_CRITICAL_EXIT();
}
/*
*********************************************************************************************************
* USBD_Vendor_Disconn()
*
* Description : Notify class that configuration is not active.
*
* Argument(s) : dev_nbr Device number.
*
* cfg_nbr Configuration index to add the interface.
*
* p_if_class_arg Pointer to class argument.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_Disconn (CPU_INT08U dev_nbr,
CPU_INT08U cfg_nbr,
void *p_if_class_arg)
{
USBD_VENDOR_COMM *p_comm;
CPU_SR_ALLOC();
(void)dev_nbr;
(void)cfg_nbr;
p_comm = (USBD_VENDOR_COMM *)p_if_class_arg;
CPU_CRITICAL_ENTER();
p_comm->CtrlPtr->CommPtr = (USBD_VENDOR_COMM *)0;
p_comm->CtrlPtr->State = USBD_VENDOR_STATE_INIT;
CPU_CRITICAL_EXIT();
}
/*
*********************************************************************************************************
* USBD_Vendor_VendorReq()
*
* Description : Process vendor-specific request.
*
* Argument(s) : dev_nbr Device number.
*
* p_setup_req Pointer to setup request structure.
*
* p_if_class_arg Pointer to class argument passed to USBD_IF_Add().
*
* Return(s) : DEF_OK, if vendor-specific request successfully processed.
*
* DEF_FAIL, otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
static CPU_BOOLEAN USBD_Vendor_VendorReq ( CPU_INT08U dev_nbr,
const USBD_SETUP_REQ *p_setup_req,
void *p_if_class_arg)
{
USBD_VENDOR_COMM *p_comm;
CPU_BOOLEAN valid;
(void)dev_nbr;
p_comm = (USBD_VENDOR_COMM *)p_if_class_arg;
/* Process req if callback avail. */
if (p_comm->CtrlPtr->VendorReqCallbackPtr != (USBD_VENDOR_REQ_FNCT)0) {
valid = p_comm->CtrlPtr->VendorReqCallbackPtr(p_comm->CtrlPtr->ClassNbr,
p_comm->CtrlPtr->DevNbr,
p_setup_req);
} else {
valid = DEF_FAIL;
}
return (valid);
}
/*
*********************************************************************************************************
* USBD_Vendor_MS_GetCompatID()
*
* Description : Returns Microsoft descriptor compatible ID.
*
* Argument(s) : dev_nbr Device number.
*
* p_sub_compat_id_ix Pointer to variable that will receive subcompatible ID.
*
* Return(s) : Compatible ID.
*
* DEF_FAIL, otherwise.
*
* Note(s) : None.
*********************************************************************************************************
*/
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
static CPU_INT08U USBD_Vendor_MS_GetCompatID (CPU_INT08U dev_nbr,
CPU_INT08U *p_sub_compat_id_ix)
{
(void)dev_nbr;
*p_sub_compat_id_ix = USBD_MS_OS_SUBCOMPAT_ID_NULL;
return (USBD_MS_OS_COMPAT_ID_WINUSB);
}
#endif
/*
*********************************************************************************************************
* USBD_Vendor_MS_GetExtPropertyTbl()
*
* Description : Returns Microsoft descriptor extended properties table.
*
* Argument(s) : dev_nbr Device number.
*
* pp_ext_property_tbl Pointer to variable that will receive the Microsoft extended
* properties table.
*
* Return(s) : Number of Microsoft extended properties in table.
*
* Note(s) : None.
*********************************************************************************************************
*/
#if (USBD_CFG_MS_OS_DESC_EN == DEF_ENABLED)
static CPU_INT08U USBD_Vendor_MS_GetExtPropertyTbl (CPU_INT08U dev_nbr,
USBD_MS_OS_EXT_PROPERTY **pp_ext_property_tbl)
{
USBD_VENDOR_CTRL *p_ctrl;
p_ctrl = &USBD_Vendor_CtrlTbl[dev_nbr]; /* Get Vendor class instance ctrl struct. */
*pp_ext_property_tbl = p_ctrl->MS_ExtPropertyTbl;
return (p_ctrl->MS_ExtPropertyNext); /* Only one extended property (GUID) supported. */
}
#endif
/*
*********************************************************************************************************
* USBD_Vendor_RdAsyncCmpl()
*
* Description : Inform the application about the Bulk OUT transfer completion.
*
* Argument(s) : dev_nbr Device number
*
* ep_addr Endpoint address.
*
* p_buf Pointer to the receive buffer.
*
* buf_len Receive buffer length.
*
* xfer_len Number of octets received.
*
* p_arg Additional argument provided by application.
*
* err Transfer status: success or error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_RdAsyncCmpl (CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err)
{
USBD_VENDOR_CTRL *p_ctrl;
void *p_callback_arg;
(void)dev_nbr;
(void)ep_addr;
p_ctrl = (USBD_VENDOR_CTRL *)p_arg; /* Get Vendor class instance ctrl struct. */
p_callback_arg = p_ctrl->BulkRdAsyncArgPtr;
p_ctrl->CommPtr->DataBulkOutActiveXfer = DEF_NO; /* Xfer finished, no more active xfer. */
p_ctrl->BulkRdAsyncFnct(p_ctrl->ClassNbr, /* Call app callback to inform about xfer completion. */
p_buf,
buf_len,
xfer_len,
p_callback_arg,
err);
}
/*
*********************************************************************************************************
* USBD_Vendor_WrAsyncCmpl()
*
* Description : Inform the application about the Bulk IN transfer completion.
*
* Argument(s) : dev_nbr Device number
*
* ep_addr Endpoint address.
*
* p_buf Pointer to the transmit buffer.
*
* buf_len Transmit buffer length.
*
* xfer_len Number of octets sent.
*
* p_arg Additional argument provided by application.
*
* err Transfer status: success or error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_WrAsyncCmpl (CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err)
{
USBD_VENDOR_CTRL *p_ctrl;
void *p_callback_arg;
(void)dev_nbr;
(void)ep_addr;
p_ctrl = (USBD_VENDOR_CTRL *)p_arg; /* Get Vendor class instance ctrl struct. */
p_callback_arg = p_ctrl->BulkWrAsyncArgPtr;
p_ctrl->CommPtr->DataBulkInActiveXfer = DEF_NO; /* Xfer finished, no more active xfer. */
p_ctrl->BulkWrAsyncFnct(p_ctrl->ClassNbr, /* Call app callback to inform about xfer completion. */
p_buf,
buf_len,
xfer_len,
p_callback_arg,
err);
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrRdAsyncCmpl()
*
* Description : Inform the application about the Interrupt OUT transfer completion.
*
* Argument(s) : dev_nbr Device number.
*
* ep_addr Endpoint address.
*
* p_buf Pointer to the receive buffer.
*
* buf_len Receive buffer length.
*
* xfer_len Number of octets received.
*
* p_arg Additional argument provided by application.
*
* err Transfer status: success or error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_IntrRdAsyncCmpl (CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err)
{
USBD_VENDOR_CTRL *p_ctrl;
void *p_callback_arg;
(void)dev_nbr;
(void)ep_addr;
p_ctrl = (USBD_VENDOR_CTRL *)p_arg; /* Get Vendor class instance ctrl struct. */
p_callback_arg = p_ctrl->IntrRdAsyncArgPtr;
p_ctrl->CommPtr->IntrOutActiveXfer = DEF_NO; /* Xfer finished, no more active xfer. */
p_ctrl->IntrRdAsyncFnct(p_ctrl->ClassNbr, /* Call app callback to inform about xfer completion. */
p_buf,
buf_len,
xfer_len,
p_callback_arg,
err);
}
/*
*********************************************************************************************************
* USBD_Vendor_IntrWrAsyncCmpl()
*
* Description : Inform the application about the Interrupt IN transfer completion.
*
* Argument(s) : dev_nbr Device number.
*
* ep_addr Endpoint address.
*
* p_buf Pointer to the transmit buffer.
*
* buf_len Transmit buffer length.
*
* xfer_len Number of octets sent.
*
* p_arg Additional argument provided by application.
*
* err Transfer status: success or error.
*
* Return(s) : none.
*
* Note(s) : none.
*********************************************************************************************************
*/
static void USBD_Vendor_IntrWrAsyncCmpl (CPU_INT08U dev_nbr,
CPU_INT08U ep_addr,
void *p_buf,
CPU_INT32U buf_len,
CPU_INT32U xfer_len,
void *p_arg,
USBD_ERR err)
{
USBD_VENDOR_CTRL *p_ctrl;
void *p_callback_arg;
(void)dev_nbr;
(void)ep_addr;
p_ctrl = (USBD_VENDOR_CTRL *)p_arg; /* Get Vendor class instance ctrl struct. */
p_callback_arg = p_ctrl->IntrWrAsyncArgPtr;
p_ctrl->CommPtr->IntrInActiveXfer = DEF_NO; /* Xfer finished, no more active xfer. */
p_ctrl->IntrWrAsyncFnct(p_ctrl->ClassNbr, /* Call app callback to inform about xfer completion. */
p_buf,
buf_len,
xfer_len,
p_callback_arg,
err);
}