355 lines
8.1 KiB
C
355 lines
8.1 KiB
C
//
|
|
// This file contains a 'Sample Driver' and is licensed as such
|
|
// under the terms of your license agreement with Intel or your
|
|
// vendor. This file may be modified by the user, subject to
|
|
// the additional terms of the license agreement
|
|
//
|
|
/** @file
|
|
Bluetooth HID Parser which is used to implement the report mode
|
|
for hid device support.
|
|
|
|
Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
|
|
This software and associated documentation (if any) is furnished
|
|
under a license and may only be used or copied in accordance
|
|
with the terms of the license. Except as permitted by such
|
|
license, no part of this software or documentation may be
|
|
reproduced, stored in a retrieval system, or transmitted in any
|
|
form or by any means without the express written consent of
|
|
Intel Corporation.
|
|
|
|
**/
|
|
#include "BluetoothHidParser.h"
|
|
|
|
// Types of items
|
|
#define GET_ITEM_TYPE(x) ((x >> 2) & 0x3) // Type of item is conveyed in bit 3:2
|
|
#define ITEM_MAIN 0x0
|
|
#define ITEM_GLOBAL 0x1
|
|
#define ITEM_LOCAL 0x2
|
|
#define ITEM_RESERVED 0x3
|
|
|
|
#define GET_TAG(x) (x >> 4) // Type of tag is conveyed in bits 7:4
|
|
#define GET_LEN(x) (x & 0x3) // Figure the number of bytes to leave out
|
|
#define DATA_OR_CONSTANT(x) (x & 0x01)
|
|
#define ARRAY_OR_VARIABLE(x) ((x >> 1 ) & 0x01)
|
|
#define ABS_OR_REL(x) ((x >> 2 ) & 0x01)
|
|
#define NOWRAP_OR_WRAP(x) ((x >> 3 ) & 0x01)
|
|
#define LIN_OR_NONLIN(x) ((x >> 4 ) & 0x01)
|
|
#define PREFSTATE_OR_NOT(x) ((x >> 5 ) & 0x01)
|
|
#define NULL_STATE(x) ((x >> 6 ) & 0x01)
|
|
#define NON_VOL_OR_VOL(x) ((x >> 7 ) & 0x01)
|
|
#define BIT_FILED_BUFFBYTE(x) ((x >> 1 ) & 0x01)
|
|
|
|
#define IS_LONG_ITEM(x) (((x & 0xf0) == 0xf0) ? 1 : 0) // If an Item is Long Item
|
|
|
|
// Types of Main Items
|
|
#define M_INPUT 0x8
|
|
#define M_OUTPUT 0x9
|
|
#define M_FEATURE 0xb
|
|
#define M_COLLECTION 0xa
|
|
#define M_END_COLLECTION 0xc
|
|
|
|
// Types of Global Items
|
|
#define G_USAGE_PAGE 0x0
|
|
#define G_LOGICAL_MIN 0x1
|
|
#define G_LOGICAL_MAX 0x2
|
|
#define G_PHYSICAL_MIN 0x3
|
|
#define G_PHYSICAL_MAX 0x4
|
|
#define G_UNIT_EXPONENT 0x5
|
|
#define G_UNIT 0x6
|
|
#define G_REPORT_SIZE 0x7
|
|
#define G_REPORT_ID 0x8
|
|
#define G_REPORT_COUNT 0x9
|
|
#define G_PUSH 0xa
|
|
#define G_POP 0xb
|
|
|
|
// Type of Local items
|
|
#define L_USAGE 0x0
|
|
#define L_USAGE_MIN 0x1
|
|
#define L_USAGE_MAX 0x2
|
|
#define L_DESIGNATOR_INDEX 0x3
|
|
#define L_DESIGNATOR_MIN 0x4
|
|
#define L_DESIGNATOR_MAX 0x5
|
|
#define L_STRING_INDEX 0x7
|
|
#define L_STRING_MIN 0x8
|
|
#define L_STRING_MAX 0x9
|
|
#define L_DELIMETER 0xa
|
|
|
|
// Other defines
|
|
#define USAGE_PAGE_DESKTOP 0x01
|
|
#define USAGE_KEYBOARD 0x07
|
|
|
|
STATIC HID_REPORT_FMT CurrentValues;
|
|
|
|
/**
|
|
Add an item.
|
|
|
|
@param[in] BtHidDev Pointer to Bluetooth HID Device Structure.
|
|
@param[in] Map The buffer save the report map.
|
|
@param[in] Cur The cursor position.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
AddItem(
|
|
IN BT_HID_DEV *BtHidDev,
|
|
IN UINT8 *Map,
|
|
IN UINT16 Cur
|
|
)
|
|
{
|
|
HID_REPORT_FMT *Format;
|
|
Format = AllocateZeroPool(sizeof(HID_REPORT_FMT));
|
|
if (Format == NULL) {
|
|
ASSERT (Format != NULL);
|
|
return;
|
|
}
|
|
|
|
// Save value
|
|
Format->Signature = ITEM_SIGNATURE;
|
|
Format->DatConst = DATA_OR_CONSTANT( Map[Cur + 1] );
|
|
Format->ArrVar = ARRAY_OR_VARIABLE( Map[Cur + 1] );
|
|
Format->AbsRel = ABS_OR_REL( Map[Cur + 1] );
|
|
Format->Wrap = NOWRAP_OR_WRAP( Map[Cur + 1] );
|
|
Format->Linear = LIN_OR_NONLIN( Map[Cur + 1] );
|
|
Format->Preferred = PREFSTATE_OR_NOT( Map[Cur + 1] );
|
|
Format->NullPosState = NULL_STATE( Map[Cur + 1] );
|
|
|
|
Format->UsageMin = CurrentValues.UsageMin;
|
|
Format->Usage = CurrentValues.Usage;
|
|
Format->UsagePage = CurrentValues.UsagePage;
|
|
Format->UsageMax = CurrentValues.UsageMax;
|
|
Format->LogicalMin = CurrentValues.LogicalMin;
|
|
Format->LogicalMax = CurrentValues.LogicalMax;
|
|
Format->ReportCount = CurrentValues.ReportCount;
|
|
Format->ReportSize = CurrentValues.ReportSize;
|
|
Format->ReportId = CurrentValues.ReportId;
|
|
Format->Type = CurrentValues.Type;
|
|
|
|
// Reset Local Items
|
|
CurrentValues.UsageMin = 0;
|
|
CurrentValues.UsageMax = 0;
|
|
|
|
InsertTailList ( &BtHidDev->ReportFormatList, &Format->Link );
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Handle the main item.
|
|
|
|
@param[in] BtHidDev Pointer to Bluetooth HID Device Structure.
|
|
@param[in] Map The buffer save the report map.
|
|
@param[in] Cur The cursor position.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
MainItemHandler(
|
|
IN BT_HID_DEV *BtHidDev,
|
|
IN UINT8 *Map,
|
|
IN UINT16 *Cur
|
|
)
|
|
{
|
|
switch ( GET_TAG(Map[*Cur]) )
|
|
{
|
|
case M_INPUT:
|
|
CurrentValues.Type = M_INPUT;
|
|
AddItem(BtHidDev, Map, *Cur);
|
|
break;
|
|
|
|
case M_OUTPUT:
|
|
CurrentValues.Type = M_OUTPUT;
|
|
AddItem(BtHidDev, Map, *Cur);
|
|
break;
|
|
|
|
case M_FEATURE:
|
|
break;
|
|
|
|
case M_COLLECTION:
|
|
break;
|
|
|
|
case M_END_COLLECTION:
|
|
break;
|
|
}
|
|
|
|
*Cur += GET_LEN( Map[*Cur] );
|
|
}
|
|
|
|
/**
|
|
Handle the global item.
|
|
|
|
@param[in] Map The buffer save the report map.
|
|
@param[in] Cur The cursor position.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
GlobalItemHandler(
|
|
IN UINT8 *Map,
|
|
IN UINT16 *Cur
|
|
)
|
|
{
|
|
switch ( GET_TAG(Map[*Cur]) )
|
|
{
|
|
case G_USAGE_PAGE:
|
|
CurrentValues.UsagePage = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_LOGICAL_MIN:
|
|
CurrentValues.LogicalMin = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_LOGICAL_MAX:
|
|
CurrentValues.LogicalMax = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_PHYSICAL_MIN:
|
|
break;
|
|
|
|
case G_PHYSICAL_MAX:
|
|
break;
|
|
|
|
case G_UNIT_EXPONENT:
|
|
break;
|
|
|
|
case G_UNIT:
|
|
break;
|
|
|
|
case G_REPORT_SIZE:
|
|
CurrentValues.ReportSize = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_REPORT_ID:
|
|
CurrentValues.ReportId = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_REPORT_COUNT:
|
|
CurrentValues.ReportCount = Map[*Cur + 1];
|
|
break;
|
|
|
|
case G_PUSH:
|
|
break;
|
|
|
|
case G_POP:
|
|
break;
|
|
}
|
|
|
|
*Cur += GET_LEN( Map[*Cur] );
|
|
}
|
|
|
|
/**
|
|
Handle the local item.
|
|
|
|
@param[in] Map The buffer save the report map.
|
|
@param[in] Cur The cursor position.
|
|
|
|
**/
|
|
STATIC
|
|
VOID
|
|
LocalItemHandler(
|
|
IN UINT8 *Map,
|
|
IN UINT16 *Cur
|
|
)
|
|
{
|
|
switch ( GET_TAG(Map[*Cur]) )
|
|
{
|
|
case L_USAGE:
|
|
CurrentValues.Usage = Map[*Cur + 1];
|
|
break;
|
|
|
|
case L_USAGE_MIN:
|
|
CurrentValues.UsageMin = Map[*Cur + 1];
|
|
break;
|
|
|
|
case L_USAGE_MAX:
|
|
CurrentValues.UsageMax = Map[*Cur + 1];
|
|
break;
|
|
|
|
case L_DESIGNATOR_INDEX:
|
|
break;
|
|
|
|
case L_DESIGNATOR_MIN:
|
|
break;
|
|
|
|
case L_DESIGNATOR_MAX:
|
|
break;
|
|
|
|
case L_STRING_INDEX:
|
|
break;
|
|
|
|
case L_STRING_MIN:
|
|
break;
|
|
|
|
case L_STRING_MAX:
|
|
break;
|
|
}
|
|
|
|
*Cur += GET_LEN( Map[*Cur] );
|
|
}
|
|
|
|
/**
|
|
Report Map Parser Function for the Report Mde Operation of Bluetooth HID devices
|
|
|
|
@param[in] BtHidDev Pointer to Bluetooth HID Device Structure.
|
|
|
|
**/
|
|
VOID
|
|
BtHidParseReportMap (
|
|
IN BT_HID_DEV *BtHidDev
|
|
)
|
|
{
|
|
UINT8 *Map;
|
|
UINT16 Cur;
|
|
// set the cursor to the zeroth position
|
|
Cur = 0;
|
|
Map = BtHidDev->ReportMap;
|
|
|
|
InitializeListHead (&BtHidDev->ReportFormatList);
|
|
|
|
do {
|
|
|
|
// Skip long items
|
|
if (IS_LONG_ITEM(Map[Cur])) {
|
|
Cur += Map[Cur + 1];
|
|
continue;
|
|
}
|
|
|
|
// Process only the short items
|
|
switch( GET_ITEM_TYPE(Map[Cur]) )
|
|
{
|
|
case ITEM_MAIN: MainItemHandler(BtHidDev, Map, &Cur);
|
|
break;
|
|
|
|
case ITEM_GLOBAL: GlobalItemHandler(Map, &Cur);
|
|
break;
|
|
|
|
case ITEM_LOCAL: LocalItemHandler(Map, &Cur);
|
|
break;
|
|
}
|
|
|
|
// Scan till the end of the map, keep the cursor updated
|
|
Cur ++;
|
|
} while ( Cur < BtHidDev->ReportMapLen );
|
|
}
|
|
|
|
/**
|
|
Fetches the Head of the Link List having the report format structures
|
|
@param[in] This A pointer to the BT_HID_DEV_FROM_HID_PROTOCOL
|
|
instance.
|
|
@param[out] Head Pointer to Report format linked list.
|
|
|
|
@retval EFI_SUCCESS The function completes successfully.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
BtHidGetReportFormatList (
|
|
IN EDKII_HID_PROTOCOL *This,
|
|
OUT LIST_ENTRY **Head
|
|
)
|
|
{
|
|
BT_HID_DEV *BtHidDev;
|
|
BtHidDev = BT_HID_DEV_FROM_HID_PROTOCOL (This);
|
|
*Head = &BtHidDev->ReportFormatList;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|