1232 lines
50 KiB
C
1232 lines
50 KiB
C
/*
|
|
*********************************************************************************************************
|
|
* uC/USB-Host
|
|
* The Embedded USB Host Stack
|
|
*
|
|
* Copyright 2004-2021 Silicon Laboratories Inc. www.silabs.com
|
|
*
|
|
* SPDX-License-Identifier: APACHE-2.0
|
|
*
|
|
* This software is subject to an open source license and is distributed by
|
|
* Silicon Laboratories Inc. pursuant to the terms of the Apache License,
|
|
* Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
|
|
*
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*
|
|
* HUMAN INTERFACE DEVICE CLASS PARSER
|
|
*
|
|
* Filename : usbh_hidparser.c
|
|
* Version : V3.42.01
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* INCLUDE FILES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_HIDPARSER_MODULE
|
|
#define MICRIUM_SOURCE
|
|
#include "usbh_hid.h"
|
|
#include "usbh_hidparser.h"
|
|
#include "../../Source/usbh_core.h"
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DEFINES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
#define USBH_HID_ITEM_SIZE(x) (((x) & 0x03u) == 3u ? 4u : ((x) & 0x03u))
|
|
|
|
#define USBH_HID_ITEM_TYPE(x) ((((x) & 0x0Cu) >> 2u) & 0x03u)
|
|
|
|
#define USBH_HID_ITEM_TAG(x) ((((x) & 0xF0u) >> 4u) & 0x0Fu)
|
|
|
|
|
|
#define USBH_HID_SIGNED_DATA(p_parser) (((p_parser)->Size == 1u) ? p_parser->Data.S08 : \
|
|
((p_parser)->Size == 2u) ? p_parser->Data.S16 : \
|
|
((p_parser)->Size == 4u) ? p_parser->Data.S32 : 0u)
|
|
|
|
#define USBH_HID_UNSIGNED_DATA(p_parser) (((p_parser)->Size == 1u) ? p_parser->Data.U08 : \
|
|
((p_parser)->Size == 2u) ? p_parser->Data.U16 : \
|
|
((p_parser)->Size == 4u) ? p_parser->Data.U32 : 0u)
|
|
|
|
/* ----------------- UNDEFINED VALUES ----------------- */
|
|
#define USBH_HID_USAGEPAGE_UNDEFINED 0x00000000u
|
|
#define USBH_HID_LOG_MIN_UNDEFINED 0x7FFFFFFFu
|
|
#define USBH_HID_LOG_MAX_UNDEFINED 0x80000000u
|
|
#define USBH_HID_PHY_MIN_UNDEFINED 0x7FFFFFFFu
|
|
#define USBH_HID_PHY_MAX_UNDEFINED 0x80000000u
|
|
#define USBH_HID_UNIT_EXP_UNDEFINED 0x7FFFFFFFu
|
|
#define USBH_HID_USAGE_MIN_UNDEFINED 0xFFFFFFFFu
|
|
#define USBH_HID_USAGE_MAX_UNDEFINED 0xFFFFFFFFu
|
|
#define USBH_HID_UNIT_UNDEFINED 0xFFFFFFFFu
|
|
#define USBH_HID_REPORT_SIZE_UNDEFINED 0u
|
|
#define USBH_HID_REPORT_CNT_UNDEFINED 0u
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONSTANTS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL DATA TYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/* -------------- GLOBAL ITEM DATA TYPE --------------- */
|
|
typedef struct usbh_hid_global USBH_HID_GLOBAL;
|
|
|
|
struct usbh_hid_global {
|
|
CPU_INT16U UsagePage; /* Usage Page. */
|
|
CPU_INT08U ReportID; /* Report ID. */
|
|
CPU_INT32S LogMin; /* Logical Minimun. */
|
|
CPU_INT32S LogMax; /* Logical Maximum. */
|
|
CPU_INT32S PhyMin; /* Physical Minimum. */
|
|
CPU_INT32S PhyMax; /* Physical Maximum. */
|
|
CPU_INT32S UnitExp; /* Unit exponent. */
|
|
CPU_INT32S Unit; /* Unit. */
|
|
CPU_INT32U ReportSize; /* Report Size (bits). */
|
|
CPU_INT32U ReportCnt; /* Report Count. */
|
|
USBH_HID_GLOBAL *NextPtr; /* Pointer to next global this for global stack. */
|
|
};
|
|
|
|
/* --------------- LOCAL ITEM DATA TYPE --------------- */
|
|
typedef struct usbh_hid_local {
|
|
CPU_INT32U Usage[USBH_HID_CFG_MAX_NBR_USAGE]; /* Usage array. */
|
|
CPU_INT32U NbrUsage; /* Number of usages. */
|
|
CPU_INT32U UsageMin; /* Usage Minimum. */
|
|
CPU_INT32U UsageMax; /* Usage Maximum. */
|
|
} USBH_HID_LOCAL;
|
|
|
|
/* ---------------------- PARSER ---------------------- */
|
|
typedef struct usbh_hid_parser {
|
|
USBH_HID_LOCAL Local; /* Local items. */
|
|
USBH_HID_GLOBAL Global; /* Global items. */
|
|
USBH_HID_GLOBAL *GlobalStkPtr; /* Global items stack for push and pop. */
|
|
USBH_HID_COLL *CollStkPtr; /* Collection stack. */
|
|
CPU_INT08U AppCollNbr; /* Present Apllication Collection number. */
|
|
CPU_INT08U Type; /* Item Type. */
|
|
CPU_INT08U Tag; /* Item Tag. */
|
|
CPU_INT08U Size; /* Item Size. */
|
|
union {
|
|
CPU_INT08U U08;
|
|
CPU_INT08S S08;
|
|
CPU_INT16U U16;
|
|
CPU_INT16S S16;
|
|
CPU_INT32U U32;
|
|
CPU_INT32S S32;
|
|
} Data; /* Item Data. */
|
|
} USBH_HID_PARSER;
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL TABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL GLOBAL VARIABLES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static MEM_POOL USBH_HID_CollPool;
|
|
static USBH_HID_COLL USBH_HID_CollList[USBH_HID_CFG_MAX_COLL];
|
|
|
|
static MEM_POOL USBH_HID_GlobalItemPool;
|
|
static USBH_HID_GLOBAL USBH_HID_GlobalItemList[USBH_HID_CFG_MAX_GLOBAL];
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTION PROTOTYPES
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_InitGlobalItem(USBH_HID_GLOBAL *p_global);
|
|
|
|
static void USBH_HID_InitLocalItem (USBH_HID_LOCAL *p_local);
|
|
|
|
static void USBH_HID_InitItemParser(USBH_HID_PARSER *p_parser);
|
|
|
|
static void USBH_HID_FreeItemParser(USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_ParseMain (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_ParseGlobal (USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_ParseLocal (USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_OpenColl (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_CloseColl (USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_AddReport (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser);
|
|
|
|
static USBH_ERR USBH_HID_ValidateReport(USBH_HID_REPORT_FMT *p_report_fmt);
|
|
|
|
static void USBH_HID_InitReport (USBH_HID_PARSER *p_parser,
|
|
USBH_HID_REPORT_FMT *p_report_fmt);
|
|
|
|
static void USBH_HID_SetData (USBH_HID_PARSER *p_parser,
|
|
void *p_buf);
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* LOCAL CONFIGURATION ERRORS
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* GLOBAL FUNCTION
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ParserGlobalInit()
|
|
*
|
|
* Description : Initialize global data.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if initialization is succesful.
|
|
* USBH_ERR_ALLOC, if global item or collection list allocation failed.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_HID_ParserGlobalInit (void)
|
|
{
|
|
LIB_ERR err_lib;
|
|
CPU_SIZE_T octets_reqd;
|
|
|
|
|
|
Mem_PoolCreate ( &USBH_HID_CollPool, /* POOL for managing collection structures. */
|
|
(void *)USBH_HID_CollList,
|
|
(sizeof(USBH_HID_COLL) * USBH_HID_CFG_MAX_COLL),
|
|
USBH_HID_CFG_MAX_COLL,
|
|
sizeof(USBH_HID_COLL),
|
|
sizeof(CPU_ALIGN),
|
|
&octets_reqd,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("%d octets required\r\n", octets_reqd);
|
|
#endif
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
|
|
Mem_PoolCreate ( &USBH_HID_GlobalItemPool, /* POOL for managing global item structures. */
|
|
(void *)USBH_HID_GlobalItemList,
|
|
(sizeof(USBH_HID_GLOBAL) * USBH_HID_CFG_MAX_GLOBAL),
|
|
USBH_HID_CFG_MAX_GLOBAL,
|
|
sizeof(USBH_HID_GLOBAL),
|
|
sizeof(CPU_ALIGN),
|
|
&octets_reqd,
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("%d octets required\r\n", octets_reqd);
|
|
#endif
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ItemParser()
|
|
*
|
|
* Description : Parse report descriptor.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* p_report_desc Pointer to report descriptor buffer.
|
|
*
|
|
* desc_len Length of report descriptor buffer in octets.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if report successfully parsed.
|
|
* USBH_ERR_UNKNOWN, if unknown error occurred.
|
|
* USBH_ERR_HID_ITEM_LONG, if long item present (not supported).
|
|
* USBH_ERR_HID_ITEM_UNKNOWN, if unknown item present.
|
|
* USBH_ERR_HID_MISMATCH_COLL, if there is a collection mismatch.
|
|
* USBH_ERR_HID_MISMATCH_PUSH_POP, if global stack error occured.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_HID_ItemParser (USBH_HID_DEV *p_hid_dev,
|
|
CPU_INT08U *p_report_desc,
|
|
CPU_INT32U desc_len)
|
|
{
|
|
USBH_HID_PARSER parser;
|
|
CPU_INT32U pos;
|
|
CPU_INT08U item;
|
|
USBH_ERR err;
|
|
|
|
|
|
/* ----------------- INITIALIZE DATA ------------------ */
|
|
USBH_HID_InitItemParser(&parser);
|
|
pos = 0u;
|
|
err = USBH_ERR_UNKNOWN;
|
|
|
|
/* ------------- PARSE REPORT DESCRIPTOR -------------- */
|
|
while (pos < desc_len) {
|
|
item = p_report_desc[pos++];
|
|
parser.Size = USBH_HID_ITEM_SIZE(item);
|
|
parser.Type = USBH_HID_ITEM_TYPE(item);
|
|
parser.Tag = USBH_HID_ITEM_TAG(item);
|
|
USBH_HID_SetData(&parser, (void *)&p_report_desc[pos]);
|
|
pos += parser.Size;
|
|
|
|
if (item == USBH_HID_ITEM_LONG) { /* If item is a long item ... */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("Long Item found\r\n");
|
|
#endif
|
|
err = USBH_ERR_HID_ITEM_LONG; /* ... rtn err. */
|
|
break;
|
|
}
|
|
|
|
switch (parser.Type) {
|
|
case USBH_HID_ITEM_TYPE_MAIN: /* Parse main item. */
|
|
err = USBH_HID_ParseMain(p_hid_dev, &parser);
|
|
break;
|
|
|
|
case USBH_HID_ITEM_TYPE_GLOBAL: /* Parse global item. */
|
|
err = USBH_HID_ParseGlobal(&parser);
|
|
break;
|
|
|
|
case USBH_HID_ITEM_TYPE_LOCAL: /* Parse local item. */
|
|
err = USBH_HID_ParseLocal(&parser);
|
|
|
|
if (pos <= 6u) { /* Store device usage. */
|
|
p_hid_dev->Usage = parser.Local.Usage[0u];
|
|
}
|
|
break;
|
|
|
|
default:
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("Unknown item type\r\n");
|
|
#endif
|
|
err = USBH_ERR_HID_ITEM_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
if (err != USBH_ERR_NONE) {
|
|
USBH_PRINT_ERR(err);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* --------------- HANDLE PARSER ERRORS --------------- */
|
|
if (err != USBH_ERR_NONE) { /* Parsing err. */
|
|
USBH_HID_FreeItemParser(&parser);
|
|
|
|
} else if (parser.CollStkPtr != (USBH_HID_COLL *)0) { /* Collection stack err. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("Missmatch in collections desc_len = %d\r\n",desc_len);
|
|
#endif
|
|
USBH_HID_FreeItemParser(&parser);
|
|
err = USBH_ERR_HID_MISMATCH_COLL;
|
|
|
|
} else if (parser.GlobalStkPtr != (USBH_HID_GLOBAL *)0) { /* Global stack err. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("Missmatch in push and pop items\r\n");
|
|
#endif
|
|
USBH_HID_FreeItemParser(&parser);
|
|
err = USBH_ERR_HID_MISMATCH_PUSH_POP;
|
|
}
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_CreateReportID()
|
|
*
|
|
* Description : Creates report id list from pre-parsed data.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if report ID list successfully created.
|
|
* USBH_ERR_ALLOC, if report ID cannot be allocated.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_ERR USBH_HID_CreateReportID (USBH_HID_DEV *p_hid_dev)
|
|
{
|
|
CPU_BOOLEAN found;
|
|
CPU_INT08U coll_ix;
|
|
CPU_INT08U report_fmt_ix;
|
|
CPU_INT08U report_id_ix;
|
|
USBH_HID_REPORT_FMT *p_report_fmt;
|
|
USBH_HID_REPORT_ID *p_report_id;
|
|
|
|
|
|
p_hid_dev->NbrReportID = 0u;
|
|
/* For each app collection. */
|
|
for (coll_ix = 0u; coll_ix < p_hid_dev->NbrAppColl; coll_ix++) {
|
|
|
|
for (report_fmt_ix = 0u; report_fmt_ix < p_hid_dev->AppColl[coll_ix].NbrReportFmt; report_fmt_ix++) {
|
|
|
|
p_report_fmt = &p_hid_dev->AppColl[coll_ix].ReportFmt[report_fmt_ix];
|
|
found = DEF_FALSE;
|
|
|
|
for (report_id_ix = 0u; report_id_ix < p_hid_dev->NbrReportID; report_id_ix++) {
|
|
p_report_id = &p_hid_dev->ReportID[report_id_ix];
|
|
/* If report ID/type match, increment size. */
|
|
if ((p_report_id->ReportID == p_report_fmt->ReportID ) &&
|
|
(p_report_id->Type == p_report_fmt->ReportType)) {
|
|
|
|
p_report_id->Size += (p_report_fmt->ReportCnt * p_report_fmt->ReportSize);
|
|
found = DEF_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found == DEF_FALSE) { /* No match found, create new report ID. */
|
|
|
|
if (p_hid_dev->NbrReportID >= USBH_HID_CFG_MAX_NBR_REPORT_ID) {
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
|
|
p_report_id = &p_hid_dev->ReportID[p_hid_dev->NbrReportID];
|
|
p_report_id->ReportID = p_report_fmt->ReportID;
|
|
p_report_id->Type = p_report_fmt->ReportType;
|
|
p_report_id->Size = (p_report_fmt->ReportCnt * p_report_fmt->ReportSize);
|
|
p_hid_dev->NbrReportID++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_MaxReport()
|
|
*
|
|
* Description : Find report of given type that has the greater size.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* type Report Type.
|
|
*
|
|
* Return(s) : Max report id structure pointer.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
USBH_HID_REPORT_ID *USBH_HID_MaxReport (USBH_HID_DEV *p_hid_dev,
|
|
CPU_INT08U type)
|
|
{
|
|
USBH_HID_REPORT_ID *p_report_id;
|
|
CPU_INT32U size;
|
|
CPU_INT08U report_id_ix;
|
|
|
|
|
|
size = 0u;
|
|
p_report_id = (USBH_HID_REPORT_ID *)0;
|
|
|
|
for (report_id_ix = 0u; report_id_ix < p_hid_dev->NbrReportID; report_id_ix++) {
|
|
|
|
if (p_hid_dev->ReportID[report_id_ix].Type == type) {
|
|
|
|
if (p_hid_dev->ReportID[report_id_ix].Size > size) {
|
|
size = p_hid_dev->ReportID[report_id_ix].Size;
|
|
p_report_id = &p_hid_dev->ReportID[report_id_ix];
|
|
}
|
|
}
|
|
}
|
|
|
|
return (p_report_id);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
* LOCAL FUNCTIONS
|
|
*********************************************************************************************************
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_InitItemParser()
|
|
*
|
|
* Description : Initialize HID parser.
|
|
*
|
|
* Argument(s) : p_parser Pointer to the parser.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_InitItemParser (USBH_HID_PARSER *p_parser)
|
|
{
|
|
|
|
Mem_Clr((void *)p_parser,
|
|
sizeof(USBH_HID_PARSER));
|
|
|
|
USBH_HID_InitGlobalItem(&p_parser->Global);
|
|
USBH_HID_InitLocalItem(&p_parser->Local);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_FreeItemParser()
|
|
*
|
|
* Description : Free memory allocated for parser structure.
|
|
*
|
|
* Argument(s) : p_parser Pointer to parser.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_FreeItemParser (USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_HID_GLOBAL *p_global;
|
|
USBH_HID_GLOBAL *p_global_free;
|
|
USBH_HID_COLL *p_coll;
|
|
USBH_HID_COLL *p_coll_free;
|
|
LIB_ERR err_lib;
|
|
|
|
/* --------------- FREE THE GLOBAL STACK -------------- */
|
|
p_global = p_parser->GlobalStkPtr;
|
|
while (p_global != (USBH_HID_GLOBAL *)0) {
|
|
p_global_free = p_global;
|
|
p_global = p_global->NextPtr;
|
|
|
|
Mem_PoolBlkFree( &USBH_HID_GlobalItemPool,
|
|
(void *)p_global_free,
|
|
&err_lib);
|
|
}
|
|
/* ------------- FREE THE COLLECTION STACK ------------ */
|
|
p_coll = p_parser->CollStkPtr;
|
|
while (p_coll != (USBH_HID_COLL *)0) {
|
|
p_coll_free = p_coll;
|
|
p_coll = p_coll->NextPtr;
|
|
|
|
Mem_PoolBlkFree( &USBH_HID_CollPool,
|
|
(void *)p_coll_free,
|
|
&err_lib);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_InitGlobalItem()
|
|
*
|
|
* Description : Initialize global item.
|
|
*
|
|
* Argument(s) : p_global Pointer to global item.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_InitGlobalItem (USBH_HID_GLOBAL *p_global)
|
|
{
|
|
|
|
Mem_Clr((void *)p_global,
|
|
sizeof(USBH_HID_GLOBAL));
|
|
|
|
p_global->LogMin = (CPU_INT32S)USBH_HID_LOG_MIN_UNDEFINED;
|
|
p_global->LogMax = (CPU_INT32S)USBH_HID_LOG_MAX_UNDEFINED;
|
|
p_global->PhyMin = (CPU_INT32S)USBH_HID_PHY_MIN_UNDEFINED;
|
|
p_global->PhyMax = (CPU_INT32S)USBH_HID_PHY_MAX_UNDEFINED;
|
|
p_global->UnitExp = (CPU_INT32S)USBH_HID_UNIT_EXP_UNDEFINED;
|
|
p_global->Unit = (CPU_INT32S)USBH_HID_UNIT_UNDEFINED;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_InitLocalItem()
|
|
*
|
|
* Description : Initialize the local item.
|
|
*
|
|
* Argument(s) : p_local Pointer to the local item.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_InitLocalItem (USBH_HID_LOCAL *p_local)
|
|
{
|
|
Mem_Clr((void *)p_local,
|
|
sizeof(USBH_HID_LOCAL));
|
|
|
|
p_local->UsageMin = USBH_HID_USAGE_MIN_UNDEFINED;
|
|
p_local->UsageMax = USBH_HID_USAGE_MAX_UNDEFINED;
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ParseMain()
|
|
*
|
|
* Description : Parse a main item.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to the HID device.
|
|
*
|
|
* p_parser Pointer to the parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if item is successfully parsed.
|
|
* USBH_ERR_HID_ITEM_UNKNOWN, if unknown item.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_ParseMain (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_ERR err;
|
|
|
|
|
|
/* -------------------- PARSE ITEM -------------------- */
|
|
switch (p_parser->Tag) {
|
|
case USBH_HID_MAIN_ITEM_TAG_FEATURE:
|
|
case USBH_HID_MAIN_ITEM_TAG_IN:
|
|
case USBH_HID_MAIN_ITEM_TAG_OUT:
|
|
err = USBH_HID_AddReport(p_hid_dev, p_parser); /* Add report to report list. */
|
|
break;
|
|
|
|
case USBH_HID_MAIN_ITEM_TAG_COLL:
|
|
err = USBH_HID_OpenColl(p_hid_dev, p_parser); /* Open new collection. */
|
|
break;
|
|
|
|
case USBH_HID_MAIN_ITEM_TAG_ENDCOLL:
|
|
err = USBH_HID_CloseColl(p_parser); /* Close collection. */
|
|
break;
|
|
|
|
default:
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("Unknown main tag\r\n");
|
|
#endif
|
|
err = USBH_ERR_HID_ITEM_UNKNOWN;
|
|
}
|
|
/* ---------------- RE-INIT LOCAL ITEM ---------------- */
|
|
USBH_HID_InitLocalItem(&p_parser->Local);
|
|
|
|
return (err);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ParseGlobal()
|
|
*
|
|
* Description : Parse a global item.
|
|
*
|
|
* Argument(s) : p_parser Pointer to parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if global item successfully parsed.
|
|
* USBH_ERR_HID_USAGE_PAGE_INVALID, if usage page is out of range.
|
|
* USBH_ERR_HID_REPORT_ID, if report ID is invalid.
|
|
* USBH_ERR_HID_REPORTID_OUTRANGE, if report ID is out of range.
|
|
* USBH_ERR_HID_REPORT_CNT, if report count is zero.
|
|
* USBH_ERR_HID_PUSH_SIZE, if push item with zero size.
|
|
* USBH_ERR_HID_POP_SIZE, if pop item with zero size.
|
|
* USBH_ERR_HID_MISMATCH_PUSH_POP, if mismatch in push and pop items.
|
|
* USBH_ERR_HID_ITEM_UNKNOWN, if unknown global item.
|
|
* USBH_ERR_ALLOC, if global item cannot be allocated.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_ParseGlobal (USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_HID_GLOBAL *p_global_new;
|
|
USBH_HID_GLOBAL *p_global_free;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
switch (p_parser->Tag) {
|
|
case USBH_HID_GLOBAL_ITEM_TAG_USAGE_PAGE:
|
|
p_parser->Global.UsagePage = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
|
|
if (p_parser->Size > 2u) { /* Rtn err if parser size is too large. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM USAGE PAGE: OUT OF RANGE\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_USAGE_PAGE_INVALID);
|
|
}
|
|
|
|
if ((p_parser->Global.UsagePage >= 0x0092u) && /* Warn if usage page is a reserved value. */
|
|
(p_parser->Global.UsagePage < 0xFEFFu)) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM USAGE PAGE: RESERVED VALUE\r\n");
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_LOG_MIN:
|
|
p_parser->Global.LogMin = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_LOG_MAX:
|
|
p_parser->Global.LogMax = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_PHY_MIN:
|
|
p_parser->Global.PhyMin = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_PHY_MAX:
|
|
p_parser->Global.PhyMax = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT:
|
|
p_parser->Global.UnitExp = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_UNIT:
|
|
p_parser->Global.Unit = USBH_HID_SIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_REPORT_SIZE:
|
|
p_parser->Global.ReportSize = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_REPORT_ID:
|
|
p_parser->Global.ReportID = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
|
|
if (p_parser->Global.ReportID == 0u) { /* Report ID should not be zero. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM REPORT ID: REPORT ID == 0\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_ID);
|
|
}
|
|
|
|
if (p_parser->Size > 1u) { /* Report ID should be 1-byte value. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM REPORT ID: REPORT ID > 255\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_ID);
|
|
}
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_REPORT_COUNT:
|
|
p_parser->Global.ReportCnt = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
|
|
if (p_parser->Global.ReportCnt == 0u) { /* Report cnt should not be zero. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM REPORT COUNT: REPORT COUNT ZERO\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_CNT);
|
|
}
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_PUSH: /* Push item to stack. */
|
|
if (p_parser->Size != 0u) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM PUSH: SIZE ZERO\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_PUSH_SIZE);
|
|
}
|
|
/* Allocate memory for new entry. */
|
|
p_global_new = (USBH_HID_GLOBAL *)Mem_PoolBlkGet ((MEM_POOL *)&USBH_HID_GlobalItemPool,
|
|
sizeof(USBH_HID_GLOBAL),
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM PUSH: OUT OF MEMORY\r\n");
|
|
#endif
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
|
|
*p_global_new = p_parser->Global; /* Copy global to new entry. */
|
|
p_global_new->NextPtr = p_parser->GlobalStkPtr;
|
|
p_parser->GlobalStkPtr = p_global_new;
|
|
break;
|
|
|
|
case USBH_HID_GLOBAL_ITEM_TAG_POP: /* Pop item from stack. */
|
|
if (p_parser->Size != 0u) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM POP: SIZE ZERO\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_POP_SIZE);
|
|
}
|
|
/* Global stack should be not empty. */
|
|
if (p_parser->GlobalStkPtr == (USBH_HID_GLOBAL *)0) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM POP: MISMATCHED PUSH/POP\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_MISMATCH_PUSH_POP);
|
|
}
|
|
p_parser->Global = *(p_parser->GlobalStkPtr);/* Copy top element to global. */
|
|
p_global_free = p_parser->GlobalStkPtr;
|
|
p_parser->GlobalStkPtr = p_global_free->NextPtr;
|
|
|
|
Mem_PoolBlkFree( &USBH_HID_GlobalItemPool, /* Free top item. */
|
|
(void *)p_global_free,
|
|
&err_lib);
|
|
break;
|
|
|
|
default:
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("GLOBAL ITEM: UNKNOWN\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_ITEM_UNKNOWN);
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ParseLocal()
|
|
*
|
|
* Description : Parse a local item.
|
|
*
|
|
* Argument(s) : p_parser Pointer to the parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if local item is successfully parsed.
|
|
* USBH_ERR_ALLOC, if usage array would have overflowed.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_ParseLocal (USBH_HID_PARSER *p_parser)
|
|
{
|
|
switch (p_parser->Tag) {
|
|
case USBH_HID_LOCAL_ITEM_TAG_USAGE:
|
|
p_parser->Local.NbrUsage++;
|
|
|
|
if (p_parser->Local.NbrUsage > USBH_HID_CFG_MAX_NBR_USAGE) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("LOCAL ITEM USAGE: ARRAY OVERFLOW\r\n");
|
|
#endif
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
p_parser->Local.Usage[p_parser->Local.NbrUsage - 1u] = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_LOCAL_ITEM_TAG_USAGE_MIN:
|
|
p_parser->Local.UsageMin = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
case USBH_HID_LOCAL_ITEM_TAG_USAGE_MAX:
|
|
p_parser->Local.UsageMax = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_OpenColl()
|
|
*
|
|
* Description : Add new collection item to collection stack.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* p_parser Pointer to parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if collection opened successfully.
|
|
* USBH_ERR_HID_NOT_APP_COLL, if top level collection not an application collection.
|
|
* USBH_ERR_ALLOC, if collection cannot be freed/allocated.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_OpenColl (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_HID_COLL *p_coll_new;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
/* --------------- INIT NEW COLLECTION ---------------- */
|
|
p_coll_new = (USBH_HID_COLL *)Mem_PoolBlkGet(&USBH_HID_CollPool,
|
|
sizeof(USBH_HID_COLL),
|
|
&err_lib);
|
|
if (err_lib != LIB_MEM_ERR_NONE) {
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
/* Initialize collection parameters. */
|
|
p_coll_new->Usage = (((CPU_INT32U)p_parser->Global.UsagePage << 16u) & 0xFFFF0000u) | (CPU_INT32U)p_parser->Local.Usage[0];
|
|
p_coll_new->Type = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
|
|
if ((p_parser->CollStkPtr == (USBH_HID_COLL *)0) && /* Check if first collection is app. */
|
|
(p_coll_new->Type != USBH_HID_COLL_APP)) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("OPEN COLLECTION: FIRST COLLECTION NOT APP COLLECTION\r\n");
|
|
#endif
|
|
Mem_PoolBlkFree( &USBH_HID_CollPool,
|
|
(void *)p_coll_new,
|
|
&err_lib);
|
|
|
|
return (USBH_ERR_HID_NOT_APP_COLL);
|
|
}
|
|
|
|
/* --------- PUT COLLECTION IN APP USAGE ARAY --------- */
|
|
if (p_coll_new->Type == USBH_HID_COLL_APP) {
|
|
if (p_parser->CollStkPtr != (USBH_HID_COLL *)0) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("OPEN COLLECTION: NESTED\r\n");
|
|
#endif
|
|
Mem_PoolBlkFree( &USBH_HID_CollPool,
|
|
(void *)p_coll_new,
|
|
&err_lib);
|
|
|
|
return (USBH_ERR_HID_NOT_APP_COLL);
|
|
}
|
|
/* Max app collections exceeded. */
|
|
if (p_hid_dev->NbrAppColl == USBH_HID_CFG_MAX_NBR_APP_COLL) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("OPEN COLLECTION: MAX APP COLLECTION EXCEEDED\r\n");
|
|
#endif
|
|
Mem_PoolBlkFree( &USBH_HID_CollPool,
|
|
(void *)p_coll_new,
|
|
&err_lib);
|
|
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
p_hid_dev->AppColl[p_hid_dev->NbrAppColl].Usage = p_coll_new->Usage;
|
|
p_hid_dev->AppColl[p_hid_dev->NbrAppColl].Type = p_coll_new->Type;
|
|
p_hid_dev->NbrAppColl++;
|
|
}
|
|
|
|
/* ------------- PUT COLLECTION IN STACK -------------- */
|
|
p_coll_new->NextPtr = p_parser->CollStkPtr;
|
|
p_parser->CollStkPtr = p_coll_new;
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_CloseColl()
|
|
*
|
|
* Description : Remove top collection from collection stack.
|
|
*
|
|
* Argument(s) : p_parser Pointer to the parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if collection is successfully closed.
|
|
* USBH_ERR_HID_MISMATCH_COLL, if collection stack is empty.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_CloseColl (USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_HID_COLL *p_coll_free;
|
|
LIB_ERR err_lib;
|
|
|
|
|
|
if (p_parser->CollStkPtr == (USBH_HID_COLL *)0) { /* Collection stack should not be empty. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("CLOSE COLLECTION: MISMATCH\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_MISMATCH_COLL);
|
|
}
|
|
|
|
p_coll_free = p_parser->CollStkPtr; /* Remove top element from collection stack. */
|
|
p_parser->CollStkPtr = p_coll_free->NextPtr;
|
|
|
|
Mem_PoolBlkFree( &USBH_HID_CollPool,
|
|
(void *)p_coll_free,
|
|
&err_lib);
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_AddReport()
|
|
*
|
|
* Description : Add new report to report list in application collection.
|
|
*
|
|
* Argument(s) : p_hid_dev Pointer to HID device.
|
|
*
|
|
* p_parser Pointer to parser.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if report is successfully added.
|
|
* USBH_ERR_ALLOC, if memory could not be allocated for report format.
|
|
* USBH_ERR_HID_REPORT_OUTSIDE_COLL, if no application collection.
|
|
*
|
|
* ----- RETURNED BY USBH_HID_ValidateReport -----
|
|
* USBH_ERR_HID_REPORT_INVALID_VAL, if any of report's value is invalid.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_AddReport (USBH_HID_DEV *p_hid_dev,
|
|
USBH_HID_PARSER *p_parser)
|
|
{
|
|
USBH_HID_REPORT_FMT *p_report_new;
|
|
USBH_HID_APP_COLL *p_app_coll;
|
|
USBH_ERR err;
|
|
|
|
|
|
if (p_hid_dev->NbrAppColl == 0u) { /* Rtn error if no app collections exist. */
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("ADD REPORT: NO APP COLLECTION's\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_OUTSIDE_COLL);
|
|
}
|
|
/* Current Application Collection */
|
|
p_app_coll = &p_hid_dev->AppColl[p_hid_dev->NbrAppColl - 1u];
|
|
|
|
if (p_app_coll->NbrReportFmt == USBH_HID_CFG_MAX_NBR_REPORT_FMT) {
|
|
return (USBH_ERR_ALLOC);
|
|
}
|
|
/* Get new Report Format */
|
|
p_report_new = &p_app_coll->ReportFmt[p_app_coll->NbrReportFmt];
|
|
p_app_coll->NbrReportFmt++;
|
|
|
|
/* ----------------- INITIALIZE REPORT ---------------- */
|
|
USBH_HID_InitReport(p_parser, p_report_new);
|
|
if (p_report_new->ReportID != 0u) {
|
|
p_hid_dev->IsReportID_Present = DEF_TRUE;
|
|
}
|
|
|
|
/* ------------------ VALIDATE REPORT ----------------- */
|
|
err = USBH_HID_ValidateReport(p_report_new);
|
|
if (err != USBH_ERR_NONE) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("HID DEVICE REPORT VALIDATION FAILED, ERR = %d\r\n", err);
|
|
#endif
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_ValidateReport()
|
|
*
|
|
* Description : Validate report by checking report values.
|
|
*
|
|
* Argument(s) : p_report_fmt Pointer to report.
|
|
*
|
|
* Return(s) : USBH_ERR_NONE, if report is valid.
|
|
* USBH_ERR_HID_REPORT_INVALID_VAL, if any of report's value is invalid.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static USBH_ERR USBH_HID_ValidateReport (USBH_HID_REPORT_FMT *p_report_fmt)
|
|
{
|
|
CPU_BOOLEAN x_def;
|
|
CPU_BOOLEAN y_def;
|
|
|
|
/* --------------- CHK MANDATORY FIELDS --------------- */
|
|
if ((p_report_fmt->UsagePage == USBH_HID_USAGE_PAGE_UNDEFINED ) ||
|
|
(p_report_fmt->LogMax == USBH_HID_LOG_MIN_UNDEFINED ) ||
|
|
(p_report_fmt->LogMin == USBH_HID_LOG_MAX_UNDEFINED ) ||
|
|
(p_report_fmt->ReportCnt == USBH_HID_REPORT_CNT_UNDEFINED ) ||
|
|
(p_report_fmt->ReportSize == USBH_HID_REPORT_SIZE_UNDEFINED)) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("VALIDATE REPORT: MANDATORY FIELD NOT DEFINED\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_INVALID_VAL);
|
|
}
|
|
|
|
/* -------------- CHK LOGICAL MIN & MAX --------------- */
|
|
if (p_report_fmt->LogMin >= p_report_fmt->LogMax) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("VALIDATE REPORT: LOG MIN > LOG MAX\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_INVALID_VAL);
|
|
}
|
|
/* Chk presence/value of physical min & max. */
|
|
x_def = p_report_fmt->PhyMax == USBH_HID_PHY_MAX_UNDEFINED ? DEF_FALSE : DEF_TRUE;
|
|
y_def = p_report_fmt->PhyMin == USBH_HID_PHY_MIN_UNDEFINED ? DEF_FALSE : DEF_TRUE;
|
|
|
|
if (((x_def == DEF_TRUE) && (y_def == DEF_FALSE)) ||
|
|
((y_def == DEF_TRUE) && (x_def == DEF_FALSE))) {
|
|
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("VALIDATE REPORT: ONLY ONE OF PHY MIN & MAX DEF'd\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_INVALID_VAL);
|
|
|
|
} else if ((x_def == DEF_FALSE) && (y_def == DEF_FALSE)) {
|
|
|
|
p_report_fmt->PhyMin = p_report_fmt->LogMin;
|
|
p_report_fmt->PhyMax = p_report_fmt->LogMax;
|
|
|
|
} else if (p_report_fmt->PhyMax < p_report_fmt->PhyMin) {
|
|
#if (USBH_CFG_PRINT_LOG == DEF_ENABLED)
|
|
USBH_PRINT_LOG("VALIDATE REPORT: PHY MIN > PHY MAX\r\n");
|
|
#endif
|
|
return (USBH_ERR_HID_REPORT_INVALID_VAL);
|
|
}
|
|
|
|
return (USBH_ERR_NONE);
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_InitReport()
|
|
*
|
|
* Description : Initialize report.
|
|
*
|
|
* Argument(s) : p_parser Pointer to parser.
|
|
*
|
|
* p_report_fmt Pointer to report.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
static void USBH_HID_InitReport (USBH_HID_PARSER *p_parser,
|
|
USBH_HID_REPORT_FMT *p_report_fmt)
|
|
{
|
|
USBH_HID_COLL *p_coll_tmp;
|
|
CPU_INT08U usage_ix;
|
|
|
|
/* Copy usages. */
|
|
for (usage_ix = 0u; usage_ix < p_parser->Local.NbrUsage; usage_ix++) {
|
|
p_report_fmt->Usage[usage_ix] = ((CPU_INT32U)p_parser->Global.UsagePage << 16u) |
|
|
(CPU_INT32U)p_parser->Local.Usage[usage_ix];
|
|
}
|
|
|
|
p_report_fmt->UsagePage = p_parser->Global.UsagePage;
|
|
p_report_fmt->NbrUsage = p_parser->Local.NbrUsage;
|
|
p_report_fmt->ReportType = p_parser->Tag;
|
|
p_report_fmt->Flag = USBH_HID_UNSIGNED_DATA(p_parser);
|
|
p_report_fmt->LogMin = p_parser->Global.LogMin;
|
|
p_report_fmt->LogMax = p_parser->Global.LogMax;
|
|
p_report_fmt->PhyMin = p_parser->Global.PhyMin;
|
|
p_report_fmt->PhyMax = p_parser->Global.PhyMax;
|
|
p_report_fmt->ReportSize = p_parser->Global.ReportSize;
|
|
p_report_fmt->ReportCnt = p_parser->Global.ReportCnt;
|
|
p_report_fmt->UnitExp = p_parser->Global.UnitExp;
|
|
p_report_fmt->Unit = p_parser->Global.Unit;
|
|
p_report_fmt->ReportID = p_parser->Global.ReportID;
|
|
p_report_fmt->UsageMin = p_parser->Local.UsageMin;
|
|
p_report_fmt->UsageMax = p_parser->Local.UsageMax;
|
|
p_report_fmt->PhyUsage = USBH_HID_USAGE_PAGE_UNDEFINED; /* Init collection usage to undefined values. */
|
|
p_report_fmt->AppUsage = USBH_HID_USAGE_PAGE_UNDEFINED;
|
|
p_report_fmt->LogUsage = USBH_HID_USAGE_PAGE_UNDEFINED;
|
|
|
|
p_coll_tmp = p_parser->CollStkPtr; /* Find values for collection usage. */
|
|
while (p_coll_tmp != (USBH_HID_COLL *)0) {
|
|
switch (p_coll_tmp->Type) {
|
|
case USBH_HID_COLL_PHYSICAL:
|
|
p_report_fmt->PhyUsage = p_coll_tmp->Usage;
|
|
break;
|
|
|
|
case USBH_HID_COLL_APP:
|
|
p_report_fmt->AppUsage = p_coll_tmp->Usage;
|
|
break;
|
|
|
|
case USBH_HID_COLL_LOGICAL:
|
|
p_report_fmt->LogUsage = p_coll_tmp->Usage;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
p_coll_tmp = p_coll_tmp->NextPtr;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
*********************************************************************************************************
|
|
* USBH_HID_SetData()
|
|
*
|
|
* Description : Set data in parser.
|
|
*
|
|
* Argument(s) : p_parser Pointer to parser.
|
|
*
|
|
* p_buf Pointer to data buffer.
|
|
*
|
|
* Return(s) : None.
|
|
*
|
|
* Note(s) : None.
|
|
*********************************************************************************************************
|
|
*/
|
|
|
|
static void USBH_HID_SetData (USBH_HID_PARSER *p_parser,
|
|
void *p_buf)
|
|
{
|
|
switch (p_parser->Size) {
|
|
case 1:
|
|
p_parser->Data.U08 = MEM_VAL_GET_INT08U_LITTLE(p_buf);
|
|
p_parser->Data.S08 = (CPU_INT08S)MEM_VAL_GET_INT08U_LITTLE(p_buf);
|
|
break;
|
|
|
|
case 2:
|
|
p_parser->Data.U16 = MEM_VAL_GET_INT16U_LITTLE(p_buf);
|
|
p_parser->Data.S16 = (CPU_INT16S)MEM_VAL_GET_INT16U_LITTLE(p_buf);
|
|
break;
|
|
|
|
case 4:
|
|
p_parser->Data.U32 = MEM_VAL_GET_INT32U_LITTLE(p_buf);
|
|
p_parser->Data.S32 = (CPU_INT32S)MEM_VAL_GET_INT32U_LITTLE(p_buf);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|