forked from PAWPAW-Mirror/lib_xua
Initial implementation, compiles w/o error, not tested
This commit is contained in:
334
lib_xua/src/hid/hid_report_descriptor.c
Normal file
334
lib_xua/src/hid/hid_report_descriptor.c
Normal file
@@ -0,0 +1,334 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <xs1.h>
|
||||
#include "xua_hid_report_descriptor.h"
|
||||
|
||||
#define HID_REPORT_ITEM_HDR_SIZE_MASK ( 0x03 )
|
||||
#define HID_REPORT_ITEM_HDR_SIZE_SHIFT ( 0 )
|
||||
|
||||
#define HID_REPORT_ITEM_HDR_TAG_MASK ( 0xF0 )
|
||||
#define HID_REPORT_ITEM_HDR_TAG_SHIFT ( 4 )
|
||||
|
||||
#define HID_REPORT_ITEM_HDR_TYPE_MASK ( 0x0C )
|
||||
#define HID_REPORT_ITEM_HDR_TYPE_SHIFT ( 2 )
|
||||
|
||||
#define HID_REPORT_ITEM_LOC_BIT_MASK ( 0x70 )
|
||||
#define HID_REPORT_ITEM_LOC_BIT_SHIFT ( 4 )
|
||||
|
||||
#define HID_REPORT_ITEM_LOC_BYTE_MASK ( 0x0F )
|
||||
#define HID_REPORT_ITEM_LOC_BYTE_SHIFT ( 0 )
|
||||
|
||||
#define HID_REPORT_ITEM_USAGE_TAG ( 0 )
|
||||
#define HID_REPORT_ITEM_USAGE_TYPE ( 2 )
|
||||
|
||||
#if 0
|
||||
/* Existing static report descriptor kept for reference */
|
||||
unsigned char hidReportDescriptor[] =
|
||||
{
|
||||
0x05, 0x01, /* Usage Page (Generic Desktop) */
|
||||
0x09, 0x06, /* Usage (Keyboard) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
0x75, 0x01, /* Report Size (1) */
|
||||
0x95, 0x04, /* Report Count (4) */
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x00, /* Logical Maximum (0) */
|
||||
0x81, 0x01, /* Input (Cnst, Ary, Abs, No Wrap, Lin, Pref, No Nul) */
|
||||
0x95, 0x01, /* Report Count (1) */
|
||||
0x25, 0x01, /* Logical Maximum (1) */
|
||||
0x05, 0x07, /* Usage Page (Key Codes) */
|
||||
0x19, 0x17, /* Usage Minimum (Keyboard t or T) */
|
||||
0x29, 0x17, /* Usage Maximum (Keyboard t or T) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
||||
0x05, 0x0C, /* Usage Page (Consumer) */
|
||||
0x0a, 0x26, 0x02, /* Usage (AC Stop) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
||||
0x95, 0x02, /* Report Count (2) */
|
||||
0x05, 0x07, /* Usage Page (Key Codes) */
|
||||
0x19, 0x72, /* Usage Minimum (Keyboard F23) */
|
||||
0x29, 0x73, /* Usage Maximum (Keyboard F24) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs, No Wrap, Lin, Pref, No Nul) */
|
||||
0xc0 /* End collection (Application) */
|
||||
};
|
||||
#endif
|
||||
|
||||
static const USB_HID_Short_Item_t hidCollectionApplication = { .header = 0xA1, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidCollectionEnd = { .header = 0xC0, .data = { 0x00, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidCollectionLogical = { .header = 0xA1, .data = { 0x02, 0x00 }, .location = 0x00 };
|
||||
|
||||
static const USB_HID_Short_Item_t hidInputConstArray = { .header = 0x81, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidInputDataVar = { .header = 0x81, .data = { 0x02, 0x00 }, .location = 0x00 };
|
||||
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum0 = { .header = 0x25, .data = { 0x00, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum1 = { .header = 0x25, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidLogicalMinimum0 = { .header = 0x15, .data = { 0x00, 0x00 }, .location = 0x00 };
|
||||
|
||||
static const USB_HID_Short_Item_t hidReportCount1 = { .header = 0x95, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidReportCount4 = { .header = 0x95, .data = { 0x04, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidReportCount6 = { .header = 0x95, .data = { 0x06, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidReportSize1 = { .header = 0x75, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerControl = { .header = 0x09, .data = { 0x01, 0x00 }, .location = 0x00 };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidUsagePageKeyboard = { .header = 0x05, .data = { 0x07, 0x00 }, .location = 0x00 };
|
||||
static const USB_HID_Short_Item_t hidUsagePageTelephony = { .header = 0x05, .data = { 0x0B, 0x00 }, .location = 0x00 };
|
||||
|
||||
static USB_HID_Short_Item_t hidUsageByte0Bit3 = { .header = 0x09, .data = { 0x73, 0x00 }, .location = 0x30 }; // F24
|
||||
static USB_HID_Short_Item_t hidUsageByte0Bit2 = { .header = 0x09, .data = { 0x72, 0x00 }, .location = 0x20 }; // F23
|
||||
static USB_HID_Short_Item_t hidUsageByte0Bit0 = { .header = 0x09, .data = { 0x17, 0x00 }, .location = 0x00 }; // 't'
|
||||
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit7 = { .header = 0x09, .data = { 0xEA, 0x00 }, .location = 0x71 }; // Vol-
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit6 = { .header = 0x09, .data = { 0xE9, 0x00 }, .location = 0x61 }; // Vol+
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit4 = { .header = 0x09, .data = { 0x00, 0x00 }, .location = 0x41 }; // Voice Command
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit2 = { .header = 0x09, .data = { 0xE2, 0x00 }, .location = 0x21 }; // Mute
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit1 = { .header = 0x09, .data = { 0x00, 0x00 }, .location = 0x11 }; // AC Search
|
||||
static USB_HID_Short_Item_t hidUsageByte1Bit0 = { .header = 0x09, .data = { 0x00, 0x00 }, .location = 0x01 }; // AC Stop
|
||||
|
||||
static USB_HID_Short_Item_t hidUsageByte2Bit1 = { .header = 0x09, .data = { 0x2F, 0x00 }, .location = 0x12 }; // Phone Mute
|
||||
static USB_HID_Short_Item_t hidUsageByte2Bit0 = { .header = 0x09, .data = { 0x20, 0x00 }, .location = 0x02 }; // Hook Switch
|
||||
|
||||
static USB_HID_Short_Item_t* const hidConfigurableItems[] = {
|
||||
&hidUsageByte0Bit0,
|
||||
&hidUsageByte0Bit2,
|
||||
&hidUsageByte0Bit3,
|
||||
&hidUsageByte1Bit0,
|
||||
&hidUsageByte1Bit1,
|
||||
&hidUsageByte1Bit2,
|
||||
&hidUsageByte1Bit4,
|
||||
&hidUsageByte1Bit6,
|
||||
&hidUsageByte1Bit7,
|
||||
&hidUsageByte2Bit0,
|
||||
&hidUsageByte2Bit1
|
||||
};
|
||||
|
||||
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||
&hidUsagePageConsumer,
|
||||
&hidUsageConsumerControl,
|
||||
&hidCollectionApplication,
|
||||
&hidReportSize1,
|
||||
&hidLogicalMinimum0,
|
||||
&hidCollectionLogical, // Byte 0
|
||||
&hidUsagePageKeyboard,
|
||||
&hidLogicalMaximum1,
|
||||
&hidReportCount1,
|
||||
&hidUsageByte0Bit0,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidInputConstArray,
|
||||
&hidLogicalMaximum1,
|
||||
&hidUsageByte0Bit2,
|
||||
&hidInputDataVar,
|
||||
&hidUsageByte0Bit3,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidReportCount4,
|
||||
&hidInputConstArray,
|
||||
&hidCollectionEnd,
|
||||
&hidCollectionLogical, // Byte 1
|
||||
&hidUsagePageConsumer,
|
||||
&hidLogicalMaximum1,
|
||||
&hidReportCount1,
|
||||
&hidUsageByte1Bit0,
|
||||
&hidInputDataVar,
|
||||
&hidUsageByte1Bit1,
|
||||
&hidInputDataVar,
|
||||
&hidUsageByte1Bit2,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidInputConstArray,
|
||||
&hidLogicalMaximum1,
|
||||
&hidUsageByte1Bit4,
|
||||
&hidInputDataVar,
|
||||
&hidLogicalMaximum0,
|
||||
&hidInputConstArray,
|
||||
&hidLogicalMaximum1,
|
||||
&hidUsageByte1Bit6,
|
||||
&hidInputDataVar,
|
||||
&hidUsageByte1Bit7,
|
||||
&hidInputDataVar,
|
||||
&hidCollectionEnd,
|
||||
&hidCollectionLogical, // Byte 2
|
||||
&hidUsagePageTelephony,
|
||||
&hidUsageByte2Bit0,
|
||||
&hidInputDataVar,
|
||||
&hidUsageByte2Bit1,
|
||||
&hidLogicalMaximum0,
|
||||
&hidReportCount6,
|
||||
&hidInputConstArray,
|
||||
&hidCollectionEnd,
|
||||
&hidCollectionEnd
|
||||
};
|
||||
|
||||
#define HID_REPORT_ITEM_LOCATION_SIZE ( 1 )
|
||||
#define HID_REPORT_DESCRIPTOR_MAX_LENGTH ( sizeof hidReportDescriptorItems / sizeof ( USB_HID_Short_Item_t ) * \
|
||||
( sizeof ( USB_HID_Short_Item_t ) - HID_REPORT_ITEM_LOCATION_SIZE ))
|
||||
|
||||
static unsigned char hidReportDescriptor[ HID_REPORT_DESCRIPTOR_MAX_LENGTH ];
|
||||
static unsigned hidReportDescriptorInitialised = 0;
|
||||
|
||||
/**
|
||||
* @brief Get the bit position from the location of an Item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] location The \c location field from a \c USB_HID_Short_Item
|
||||
*
|
||||
* @return The bit position of the Item
|
||||
*/
|
||||
static unsigned hidGetItemBitLocation( const unsigned char header );
|
||||
|
||||
/**
|
||||
* @brief Get the byte position from the location of an Item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] location The \c location field from a \c USB_HID_Short_Item
|
||||
*
|
||||
* @return The byte position of the Item within the HID Report
|
||||
*/
|
||||
static unsigned hidGetItemByteLocation( const unsigned char header );
|
||||
|
||||
/**
|
||||
* @brief Get the number of data bytes from the header of an Item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] header The \c header field from a \c USB_HID_Short_Item
|
||||
*
|
||||
* @return The amount of data for the Item
|
||||
*/
|
||||
static unsigned hidGetItemSize( const unsigned char header );
|
||||
|
||||
/**
|
||||
* @brief Get the Tag from the header of an Item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] header The \c header field from a \c USB_HID_Short_Item
|
||||
*
|
||||
* @return The Tag of the Item
|
||||
*/
|
||||
static unsigned hidGetItemTag( const unsigned char header );
|
||||
|
||||
/**
|
||||
* @brief Get the Type from the header of an Item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] header The \c header field from a \c USB_HID_Short_Item
|
||||
*
|
||||
* @return The Type of the Item
|
||||
*/
|
||||
static unsigned hidGetItemType( const unsigned char header );
|
||||
|
||||
/**
|
||||
* @brief Translate an Item from the \c USB_HID_Short_Item format to raw bytes
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] inPtr A pointer to a \c USB_HID_Short_Item
|
||||
* @param[in,out] outPtr A pointer to the next available space in the raw byte buffer
|
||||
*
|
||||
* @return The updated \a outPtr
|
||||
*/
|
||||
static unsigned char* hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char* outPtr );
|
||||
|
||||
static unsigned hidGetItemBitLocation( const unsigned char location )
|
||||
{
|
||||
unsigned bBit = ( location & HID_REPORT_ITEM_LOC_BIT_MASK ) >> HID_REPORT_ITEM_LOC_BIT_SHIFT;
|
||||
return bBit;
|
||||
}
|
||||
|
||||
static unsigned hidGetItemByteLocation( const unsigned char location )
|
||||
{
|
||||
unsigned bByte = ( location & HID_REPORT_ITEM_LOC_BYTE_MASK ) >> HID_REPORT_ITEM_LOC_BYTE_SHIFT;
|
||||
return bByte;
|
||||
}
|
||||
|
||||
static unsigned hidGetItemSize( const unsigned char header )
|
||||
{
|
||||
unsigned bSize = ( header & HID_REPORT_ITEM_HDR_SIZE_MASK ) >> HID_REPORT_ITEM_HDR_SIZE_SHIFT;
|
||||
assert( bSize <= HID_REPORT_ITEM_MAX_SIZE );
|
||||
return bSize;
|
||||
}
|
||||
|
||||
static unsigned hidGetItemTag( const unsigned char header )
|
||||
{
|
||||
unsigned bTag = ( header & HID_REPORT_ITEM_HDR_TAG_MASK ) >> HID_REPORT_ITEM_HDR_TAG_SHIFT;
|
||||
return bTag;
|
||||
}
|
||||
|
||||
static unsigned hidGetItemType( const unsigned char header )
|
||||
{
|
||||
unsigned bType = ( header & HID_REPORT_ITEM_HDR_TYPE_MASK ) >> HID_REPORT_ITEM_HDR_TYPE_SHIFT;
|
||||
return bType;
|
||||
}
|
||||
|
||||
unsigned char* hidGetReportDescriptor( void )
|
||||
{
|
||||
unsigned char* retVal = NULL;
|
||||
|
||||
if( hidReportDescriptorInitialised ) {
|
||||
retVal = hidReportDescriptor;
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void hidInitReportDescriptor( void )
|
||||
{
|
||||
unsigned char* ptr = hidReportDescriptor;
|
||||
for( unsigned idx = 0; idx < sizeof hidReportDescriptorItems / sizeof( USB_HID_Short_Item_t ); ++idx ) {
|
||||
ptr = hidTranslateItem( hidReportDescriptorItems[ idx ], ptr );
|
||||
}
|
||||
|
||||
hidReportDescriptorInitialised = 1;
|
||||
}
|
||||
|
||||
unsigned hidSetReportItem( const unsigned byte, const unsigned bit, const unsigned char header, const unsigned char data[] )
|
||||
{
|
||||
unsigned retVal = 2;
|
||||
unsigned bSize = hidGetItemSize( header );
|
||||
unsigned bTag = hidGetItemTag ( header );
|
||||
unsigned bType = hidGetItemType( header );
|
||||
|
||||
if(( HID_REPORT_ITEM_MAX_SIZE < bSize ) &&
|
||||
( HID_REPORT_ITEM_USAGE_TAG == bTag ) &&
|
||||
( HID_REPORT_ITEM_USAGE_TAG == bType )) {
|
||||
retVal = 1;
|
||||
} else {
|
||||
for( unsigned itemIdx = 0; itemIdx < sizeof hidConfigurableItems / sizeof( USB_HID_Short_Item_t ); ++itemIdx ) {
|
||||
USB_HID_Short_Item_t item = *hidConfigurableItems[ itemIdx ];
|
||||
unsigned bBit = hidGetItemBitLocation( item.location );
|
||||
unsigned bByte = hidGetItemByteLocation( item.location );
|
||||
|
||||
if(( bit == bBit ) && ( byte == bByte )) {
|
||||
item.header = header;
|
||||
|
||||
for( unsigned dataIdx = 0; dataIdx < bSize; ++dataIdx ) {
|
||||
item.data[ dataIdx ] = data[ dataIdx ];
|
||||
}
|
||||
|
||||
*hidConfigurableItems[ itemIdx ] = item;
|
||||
hidReportDescriptorInitialised = 0;
|
||||
retVal = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
static unsigned char* hidTranslateItem( const USB_HID_Short_Item_t* inPtr, unsigned char* outPtr )
|
||||
{
|
||||
*outPtr++ = inPtr->header;
|
||||
|
||||
unsigned dataLength = hidGetItemSize( inPtr->header );
|
||||
for( unsigned idx = 0; idx < dataLength; ++idx ) {
|
||||
*outPtr++ = inPtr->data[ idx ];
|
||||
}
|
||||
|
||||
return outPtr;
|
||||
}
|
||||
83
lib_xua/src/hid/xua_hid_report_descriptor.h
Normal file
83
lib_xua/src/hid/xua_hid_report_descriptor.h
Normal file
@@ -0,0 +1,83 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
/**
|
||||
* @brief Human Interface Device (HID) Report descriptor
|
||||
*
|
||||
* This file defines the structure and default content of the HID Report descriptor.
|
||||
* Document section numbers refer to the HID Device Class Definition, version 1.11.
|
||||
*/
|
||||
|
||||
#ifndef _HID_REPORT_DESCRIPTOR_
|
||||
#define _HID_REPORT_DESCRIPTOR_
|
||||
|
||||
#define HID_REPORT_ITEM_MAX_SIZE ( 2 )
|
||||
|
||||
#define HID_STATUS_GOOD ( 0 )
|
||||
#define HID_STATUS_BAD_HEADER ( 1 )
|
||||
#define HID_STATUS_BAD_LOCATION ( 2 )
|
||||
|
||||
/**
|
||||
* @brief USB HID Report Descriptor. Short Item
|
||||
*
|
||||
* @note
|
||||
* To reduce memory use, this type does not support Short Items with 4 data bytes.
|
||||
* See section 6.2.2.2
|
||||
*
|
||||
* Elements:
|
||||
*
|
||||
* header - the item prefix containing the size, type and tag fields (see 6.2.2.2)
|
||||
* Format (bit range): bSize (0:1), bType (2:3), bTag (4:7)
|
||||
* data - a two byte array for holding the item's data
|
||||
* The bSize field indicates which data bytes are in use
|
||||
* location - a non-standard extension locating the item within the HID Report
|
||||
* Format (bit range): iByte (0:3), iBit (4:6), Reserved (7)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned char header;
|
||||
unsigned char data[ HID_REPORT_ITEM_MAX_SIZE ];
|
||||
unsigned char location;
|
||||
} USB_HID_Short_Item_t;
|
||||
|
||||
/**
|
||||
* @brief Get the HID Report descriptor
|
||||
*
|
||||
* This function returns a pointer to the USB HID Report descriptor.
|
||||
* It returns NULL if the Report descriptor has not been initialised,
|
||||
* i.e., no one has called \c hidInitReportDescriptor().
|
||||
*
|
||||
* @return A pointer to a list of unsigned char containing the Report descriptor
|
||||
*/
|
||||
unsigned char* hidGetReportDescriptor( void );
|
||||
|
||||
/**
|
||||
* @brief Modify a HID Report descriptor item
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* @param[in] byte The byte position of the control within the HID Report
|
||||
* @param[in] bit The bit position of the control within the \a byte
|
||||
* @param[in] header The LSB of the Item containing the bSize, bType and bTag fields (see 6.2.2.2)
|
||||
* @param[in] data An array containing data bytes or NULL for an Item with no data
|
||||
*
|
||||
* @return A status value
|
||||
* @retval \c HID_STATUS_GOOD Item successfully updated
|
||||
* @retval \c HID_STATUS_BAD_HEADER The Item header specified a data size greater than 2 or
|
||||
* a Tag or Type inconsistent with a Usage Item
|
||||
* @retval \c HID_STATUS_BAD_LOCATION The \a bit or \a byte arguments specify a location outside
|
||||
* of the HID Report
|
||||
*/
|
||||
unsigned hidSetReportItem( const unsigned byte, const unsigned bit, const unsigned char header, const unsigned char data[] );
|
||||
|
||||
/**
|
||||
* @brief Initialise the USB HID Report descriptor
|
||||
*
|
||||
* After initialisation, \c hidGetReportDescriptor() returns a list suitable
|
||||
* for transmission over USB.
|
||||
*
|
||||
* Call this function after altering one or more Report Items using \c hidSetReportItem().
|
||||
*/
|
||||
void hidInitReportDescriptor( void );
|
||||
|
||||
#endif // _HID_REPORT_DESCRIPTOR_
|
||||
Reference in New Issue
Block a user