mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
improve hid parser
This commit is contained in:
parent
350dfb2ea3
commit
ad845db6a5
@ -37,14 +37,16 @@
|
||||
|
||||
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
// Each HID instance can has multiple reports
|
||||
static uint8_t _report_count[CFG_TUH_HID];
|
||||
static tuh_hid_report_info_t _report_info[CFG_TUH_HID][MAX_REPORT];
|
||||
static tuh_hid_report_info_t _report_info_arr[CFG_TUH_HID][MAX_REPORT];
|
||||
|
||||
static void process_kbd_report(hid_keyboard_report_t const *report);
|
||||
static void process_mouse_report(hid_mouse_report_t const * report);
|
||||
|
||||
void hid_app_task(void)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -55,21 +57,13 @@ void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_
|
||||
{
|
||||
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
|
||||
|
||||
// Parse report descriptor with built-in parser
|
||||
_report_count[instance] = tuh_hid_parse_report_descriptor(_report_info[instance], MAX_REPORT, desc_report, desc_len);
|
||||
|
||||
if (_report_count[instance])
|
||||
{
|
||||
printf("Composite with %u reports", _report_count[instance]);
|
||||
}else
|
||||
{
|
||||
printf("Single report");
|
||||
}
|
||||
|
||||
// Interface protocol
|
||||
const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; // hid_protocol_type_t
|
||||
uint8_t const interface_protocol = tuh_hid_interface_protocol(dev_addr, instance);
|
||||
printf(", Interface protocol = %s, ", protocol_str[interface_protocol]);
|
||||
|
||||
// Parse report descriptor with built-in parser
|
||||
_report_count[instance] = tuh_hid_parse_report_descriptor(_report_info_arr[instance], MAX_REPORT, desc_report, desc_len);
|
||||
printf("HID has %u reports and interface protocol = %s\r\n", _report_count[instance], protocol_str[interface_protocol]);
|
||||
}
|
||||
|
||||
void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance)
|
||||
@ -82,20 +76,36 @@ void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* re
|
||||
(void) dev_addr;
|
||||
|
||||
uint8_t const rpt_count = _report_count[instance];
|
||||
tuh_hid_report_info_t* rpt_info;
|
||||
tuh_hid_report_info_t* rpt_info_arr = _report_info_arr[instance];
|
||||
tuh_hid_report_info_t* rpt_info = NULL;
|
||||
|
||||
if (rpt_count)
|
||||
if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0)
|
||||
{
|
||||
// Simple report without report ID as 1st byte
|
||||
rpt_info = &rpt_info_arr[0];
|
||||
}else
|
||||
{
|
||||
// Composite report, 1st byte is report ID, data starts from 2nd byte
|
||||
// Note: report index = report ID - 1
|
||||
uint8_t idx = report[0] - 1;
|
||||
rpt_info = &_report_info[instance][idx];
|
||||
uint8_t const rpt_id = report[0];
|
||||
|
||||
// Find report id in the arrray
|
||||
for(uint8_t i=0; i<rpt_count; i++)
|
||||
{
|
||||
if (rpt_id == rpt_info_arr[i].report_id )
|
||||
{
|
||||
rpt_info = &rpt_info_arr[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
report++;
|
||||
len--;
|
||||
}else
|
||||
}
|
||||
|
||||
if (!rpt_info)
|
||||
{
|
||||
rpt_info = &_report_info[instance][0];
|
||||
printf("Couldn't find the report info for this report !\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP )
|
||||
|
@ -337,7 +337,7 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co
|
||||
// Report Descriptor Parser
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len)
|
||||
uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
// Report Item 6.2.2.2 USB HID 1.11
|
||||
union TU_ATTR_PACKED
|
||||
@ -351,18 +351,16 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
};
|
||||
} header;
|
||||
|
||||
uint8_t report_num = 0;
|
||||
tuh_hid_report_info_t* info = report_info;
|
||||
tu_memclr(report_info_arr, arr_count*sizeof(tuh_hid_report_info_t));
|
||||
|
||||
tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t));
|
||||
uint8_t report_num = 0;
|
||||
tuh_hid_report_info_t* info = report_info_arr;
|
||||
|
||||
// current parsed report count & size from descriptor
|
||||
// uint8_t ri_report_count = 0;
|
||||
// uint8_t ri_report_size = 0;
|
||||
|
||||
uint8_t ri_collection_depth = 0;
|
||||
uint16_t ri_usage_page = 0;
|
||||
uint8_t ri_usage = 0;
|
||||
|
||||
while(desc_len && report_num < arr_count)
|
||||
{
|
||||
@ -394,6 +392,11 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
|
||||
case RI_MAIN_COLLECTION_END:
|
||||
ri_collection_depth--;
|
||||
if (ri_collection_depth == 0)
|
||||
{
|
||||
info++;
|
||||
report_num++;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
@ -404,11 +407,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
switch(tag)
|
||||
{
|
||||
case RI_GLOBAL_USAGE_PAGE:
|
||||
// only take in account the "usage page" before starting COLLECTION
|
||||
if ( ri_collection_depth == 0)
|
||||
{
|
||||
memcpy(&ri_usage_page, desc_report, size);
|
||||
}
|
||||
// only take in account the "usage page" before REPORT ID
|
||||
if ( ri_collection_depth == 0 ) memcpy(&info->usage_page, desc_report, size);
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_LOGICAL_MIN : break;
|
||||
@ -417,23 +417,7 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
case RI_GLOBAL_PHYSICAL_MAX : break;
|
||||
|
||||
case RI_GLOBAL_REPORT_ID:
|
||||
report_num++;
|
||||
if (data8 <= arr_count)
|
||||
{
|
||||
uint8_t const idx = data8 - 1;
|
||||
if ( info != &report_info[idx] )
|
||||
{
|
||||
// copy info so far to its correct report ID, and update info pointer
|
||||
report_info[idx] = *info;
|
||||
info = &report_info[idx];
|
||||
}
|
||||
|
||||
info->usage_page = ri_usage_page;
|
||||
info->usage = ri_usage;
|
||||
}else
|
||||
{
|
||||
TU_LOG2("HID Skip a report with ID (%u) larger than array count (%u)\r\n", data8, arr_count);
|
||||
}
|
||||
info->report_id = data8;
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_REPORT_SIZE:
|
||||
@ -457,8 +441,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
switch(tag)
|
||||
{
|
||||
case RI_LOCAL_USAGE:
|
||||
// only take in account the "usage" before starting COLLECTION
|
||||
if ( ri_collection_depth == 0) ri_usage = data8;
|
||||
// only take in account the "usage" before starting REPORT ID
|
||||
if ( ri_collection_depth == 0 ) info->usage = data8;
|
||||
break;
|
||||
|
||||
case RI_LOCAL_USAGE_MIN : break;
|
||||
@ -482,16 +466,10 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint
|
||||
desc_len -= size;
|
||||
}
|
||||
|
||||
if ( report_num == 0 )
|
||||
for ( uint8_t i = 0; i < report_num; i++ )
|
||||
{
|
||||
report_info[0].usage_page = ri_usage_page;
|
||||
report_info[0].usage = ri_usage;
|
||||
}
|
||||
|
||||
for ( uint8_t i = 0; (i < report_num) || (!i && !report_num); i++ )
|
||||
{
|
||||
info = report_info+i;
|
||||
TU_LOG2("%u: usage_page = %u, usage = %u\r\n", i, info->usage_page, info->usage);
|
||||
info = report_info_arr+i;
|
||||
TU_LOG2("%u: id = %u, usage_page = %u, usage = %u\r\n", i, info->report_id, info->usage_page, info->usage);
|
||||
}
|
||||
|
||||
return report_num;
|
||||
|
@ -53,8 +53,9 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t report_id;
|
||||
uint8_t usage;
|
||||
uint16_t usage_page;
|
||||
uint8_t usage;
|
||||
|
||||
// TODO still use the endpoint size for now
|
||||
// uint8_t in_len; // length of IN report
|
||||
@ -83,9 +84,8 @@ bool tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance);
|
||||
bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol);
|
||||
|
||||
// Parse report descriptor into array of report_info struct and return number of reports.
|
||||
// If return 0, this is a ingle report, otherwise it is composite report with 1st byte as ID.
|
||||
// For complicated report, application should write its own parser.
|
||||
uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* report_info, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
|
||||
uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr, uint8_t arr_count, uint8_t const* desc_report, uint16_t desc_len) TU_ATTR_UNUSED;
|
||||
|
||||
// Check if the interface is ready to use
|
||||
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
|
||||
|
Loading…
x
Reference in New Issue
Block a user