mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
move report_info to application
update API accordingly, update hid parser for usage, and usage_page.
This commit is contained in:
parent
da6a7fb2bb
commit
ffdcf9a0d0
209
examples/host/cdc_msc_hid/src/hid_app.c
Normal file
209
examples/host/cdc_msc_hid/src/hid_app.c
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021, Ha Thach (tinyusb.org)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define MAX_REPORT 4
|
||||
|
||||
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
static uint8_t _report_count[CFG_TUH_HID];
|
||||
static tuh_hid_report_info_t _report_info[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)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
|
||||
{
|
||||
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_n_hid_n_interface_protocol(dev_addr, instance);
|
||||
printf(", Interface protocol = %s, ", protocol_str[interface_protocol]);
|
||||
}
|
||||
|
||||
void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
|
||||
}
|
||||
|
||||
void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
uint8_t const rpt_count = _report_count[instance];
|
||||
tuh_hid_report_info_t* rpt_info;
|
||||
|
||||
if (rpt_count)
|
||||
{
|
||||
// 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];
|
||||
|
||||
report++;
|
||||
}else
|
||||
{
|
||||
rpt_info = &_report_info[instance][0];
|
||||
}
|
||||
|
||||
if ( rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP )
|
||||
{
|
||||
switch (rpt_info->usage)
|
||||
{
|
||||
case HID_USAGE_DESKTOP_KEYBOARD:
|
||||
TU_LOG1("HID receive keyboard report\r\n");
|
||||
// Assume keyboard follow boot report layout
|
||||
process_kbd_report( (hid_keyboard_report_t const*) report );
|
||||
break;
|
||||
|
||||
case HID_USAGE_DESKTOP_MOUSE:
|
||||
TU_LOG1("HID receive mouse report\r\n");
|
||||
// Assume mouse follow boot report layout
|
||||
process_mouse_report( (hid_mouse_report_t const*) report );
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Keyboard
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// look up new key in previous keys
|
||||
static inline bool find_key_in_report(hid_keyboard_report_t const *report, uint8_t keycode)
|
||||
{
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
{
|
||||
if (report->keycode[i] == keycode) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void process_kbd_report(hid_keyboard_report_t const *report)
|
||||
{
|
||||
static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
|
||||
|
||||
//------------- example code ignore control (non-printable) key affects -------------//
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
{
|
||||
if ( report->keycode[i] )
|
||||
{
|
||||
if ( find_key_in_report(&prev_report, report->keycode[i]) )
|
||||
{
|
||||
// exist in previous report means the current key is holding
|
||||
}else
|
||||
{
|
||||
// not existed in previous report means the current key is pressed
|
||||
bool const is_shift = report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
|
||||
uint8_t ch = keycode2ascii[report->keycode[i]][is_shift ? 1 : 0];
|
||||
putchar(ch);
|
||||
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
|
||||
|
||||
fflush(stdout); // flush right away, else nanolib will wait for newline
|
||||
}
|
||||
}
|
||||
// TODO example skips key released
|
||||
}
|
||||
|
||||
prev_report = *report;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Mouse
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void cursor_movement(int8_t x, int8_t y, int8_t wheel)
|
||||
{
|
||||
// Move X using ansi escape
|
||||
if ( x < 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
|
||||
}else if ( x > 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
|
||||
}
|
||||
|
||||
// Move Y using ansi escape
|
||||
if ( y < 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
|
||||
}else if ( y > 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_DOWN(%d), y); // move down
|
||||
}
|
||||
|
||||
// Scroll using ansi escape
|
||||
if (wheel < 0)
|
||||
{
|
||||
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
|
||||
}else if (wheel > 0)
|
||||
{
|
||||
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
|
||||
}
|
||||
}
|
||||
|
||||
static void process_mouse_report(hid_mouse_report_t const * report)
|
||||
{
|
||||
static hid_mouse_report_t prev_report = { 0 };
|
||||
|
||||
//------------- button state -------------//
|
||||
uint8_t button_changed_mask = report->buttons ^ prev_report.buttons;
|
||||
if ( button_changed_mask & report->buttons)
|
||||
{
|
||||
printf(" %c%c%c ",
|
||||
report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
|
||||
report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
|
||||
report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
|
||||
}
|
||||
|
||||
//------------- cursor movement -------------//
|
||||
cursor_movement(report->x, report->y, report->wheel);
|
||||
}
|
@ -37,7 +37,7 @@ void print_greeting(void);
|
||||
void led_blinking_task(void);
|
||||
|
||||
extern void cdc_task(void);
|
||||
extern void hid_task(void);
|
||||
extern void hid_app_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
@ -58,7 +58,7 @@ int main(void)
|
||||
#endif
|
||||
|
||||
#if CFG_TUH_HID
|
||||
hid_task();
|
||||
hid_app_task();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -106,127 +106,11 @@ void cdc_task(void)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USB HID
|
||||
//--------------------------------------------------------------------+
|
||||
uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
|
||||
|
||||
// look up new key in previous keys
|
||||
static inline bool find_key_in_report(hid_keyboard_report_t const *p_report, uint8_t keycode)
|
||||
{
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
{
|
||||
if (p_report->keycode[i] == keycode) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void process_kbd_report(hid_keyboard_report_t const *p_new_report)
|
||||
{
|
||||
static hid_keyboard_report_t prev_report = { 0, 0, {0} }; // previous report to check key released
|
||||
|
||||
//------------- example code ignore control (non-printable) key affects -------------//
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
{
|
||||
if ( p_new_report->keycode[i] )
|
||||
{
|
||||
if ( find_key_in_report(&prev_report, p_new_report->keycode[i]) )
|
||||
{
|
||||
// exist in previous report means the current key is holding
|
||||
}else
|
||||
{
|
||||
// not existed in previous report means the current key is pressed
|
||||
bool const is_shift = p_new_report->modifier & (KEYBOARD_MODIFIER_LEFTSHIFT | KEYBOARD_MODIFIER_RIGHTSHIFT);
|
||||
uint8_t ch = keycode2ascii[p_new_report->keycode[i]][is_shift ? 1 : 0];
|
||||
putchar(ch);
|
||||
if ( ch == '\r' ) putchar('\n'); // added new line for enter key
|
||||
|
||||
fflush(stdout); // flush right away, else nanolib will wait for newline
|
||||
}
|
||||
}
|
||||
// TODO example skips key released
|
||||
}
|
||||
|
||||
prev_report = *p_new_report;
|
||||
}
|
||||
|
||||
void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
|
||||
// printf("A Keyboard device (address %d) is mounted\r\n", dev_addr);
|
||||
// printf("A Mouse device (address %d) is mounted\r\n", dev_addr);
|
||||
}
|
||||
|
||||
void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
|
||||
// printf("A Keyboard device (address %d) is unmounted\r\n", dev_addr);
|
||||
// printf("A Mouse device (address %d) is unmounted\r\n", dev_addr);
|
||||
}
|
||||
|
||||
void cursor_movement(int8_t x, int8_t y, int8_t wheel)
|
||||
{
|
||||
//------------- X -------------//
|
||||
if ( x < 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_BACKWARD(%d), (-x)); // move left
|
||||
}else if ( x > 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_FORWARD(%d), x); // move right
|
||||
}else { }
|
||||
|
||||
//------------- Y -------------//
|
||||
if ( y < 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_UP(%d), (-y)); // move up
|
||||
}else if ( y > 0)
|
||||
{
|
||||
printf(ANSI_CURSOR_DOWN(%d), y); // move down
|
||||
}else { }
|
||||
|
||||
//------------- wheel -------------//
|
||||
if (wheel < 0)
|
||||
{
|
||||
printf(ANSI_SCROLL_UP(%d), (-wheel)); // scroll up
|
||||
}else if (wheel > 0)
|
||||
{
|
||||
printf(ANSI_SCROLL_DOWN(%d), wheel); // scroll down
|
||||
}else { }
|
||||
}
|
||||
|
||||
static inline void process_mouse_report(hid_mouse_report_t const * p_report)
|
||||
{
|
||||
static hid_mouse_report_t prev_report = { 0 };
|
||||
|
||||
//------------- button state -------------//
|
||||
uint8_t button_changed_mask = p_report->buttons ^ prev_report.buttons;
|
||||
if ( button_changed_mask & p_report->buttons)
|
||||
{
|
||||
printf(" %c%c%c ",
|
||||
p_report->buttons & MOUSE_BUTTON_LEFT ? 'L' : '-',
|
||||
p_report->buttons & MOUSE_BUTTON_MIDDLE ? 'M' : '-',
|
||||
p_report->buttons & MOUSE_BUTTON_RIGHT ? 'R' : '-');
|
||||
}
|
||||
|
||||
//------------- cursor movement -------------//
|
||||
cursor_movement(p_report->x, p_report->y, p_report->wheel);
|
||||
}
|
||||
|
||||
void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
|
||||
{
|
||||
process_kbd_report( (hid_keyboard_report_t*) report );
|
||||
}
|
||||
|
||||
void hid_task(void)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// tinyusb callbacks
|
||||
// TinyUSB Callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// BLINKING TASK
|
||||
// Blinking Task
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
|
@ -57,16 +57,8 @@ typedef struct
|
||||
uint16_t epin_size;
|
||||
uint16_t epout_size;
|
||||
|
||||
uint8_t boot_protocol; // None, Keyboard, Mouse
|
||||
bool boot_mode; // Boot or Report protocol
|
||||
|
||||
tuh_hid_report_info_t report_info;
|
||||
|
||||
// Parsed Report ID for convenient API
|
||||
uint8_t rid_keyboard;
|
||||
uint8_t rid_mouse;
|
||||
uint8_t rid_gamepad;
|
||||
uint8_t rid_consumer;
|
||||
uint8_t boot_interface; // None, Keyboard, Mouse
|
||||
bool boot_mode; // Boot or Report protocol
|
||||
|
||||
uint8_t epin_buf[CFG_TUH_HID_EP_BUFSIZE];
|
||||
uint8_t epout_buf[CFG_TUH_HID_EP_BUFSIZE];
|
||||
@ -107,49 +99,30 @@ bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance)
|
||||
return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0);
|
||||
}
|
||||
|
||||
uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance)
|
||||
uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
return hid_itf->boot_protocol;
|
||||
return hid_itf->boot_interface;
|
||||
}
|
||||
|
||||
bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance)
|
||||
bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
return hid_itf->boot_mode;
|
||||
}
|
||||
|
||||
tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
return &get_instance(dev_addr, instance)->report_info;
|
||||
}
|
||||
//bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode)
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
|
||||
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
return !hcd_edpt_busy(dev_addr, hid_itf->ep_in);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// KEYBOARD
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
|
||||
// TODO check rid_keyboard
|
||||
return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0);
|
||||
}
|
||||
|
||||
// TODO remove
|
||||
bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance)
|
||||
{
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
return tuh_device_ready(dev_addr) && (hid_itf->ep_in != 0);
|
||||
}
|
||||
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance)
|
||||
//{
|
||||
// TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
|
||||
//
|
||||
// hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
|
||||
// return !hcd_edpt_busy(dev_addr, hid_itf->ep_in);
|
||||
//}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH API
|
||||
@ -167,10 +140,9 @@ bool hidh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
|
||||
|
||||
if ( dir == TUSB_DIR_IN )
|
||||
{
|
||||
if (tuh_hid_get_report_cb)
|
||||
{
|
||||
tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes);
|
||||
}
|
||||
TU_LOG2(" Get Report callback (%u, %u)\r\n", dev_addr, instance);
|
||||
TU_LOG1_MEM(hid_itf->epin_buf, 8, 2);
|
||||
tuh_hid_get_report_cb(dev_addr, instance, hid_itf->epin_buf, xferred_bytes);
|
||||
|
||||
// queue next report
|
||||
hidh_get_report(dev_addr, hid_itf);
|
||||
@ -197,7 +169,6 @@ void hidh_close(uint8_t dev_addr)
|
||||
// Enumeration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len);
|
||||
static bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||
static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
|
||||
|
||||
@ -228,40 +199,40 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
|
||||
hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count);
|
||||
hid_dev->inst_count++;
|
||||
|
||||
hid_itf->itf_num = desc_itf->bInterfaceNumber;
|
||||
hid_itf->ep_in = desc_ep->bEndpointAddress;
|
||||
hid_itf->itf_num = desc_itf->bInterfaceNumber;
|
||||
hid_itf->ep_in = desc_ep->bEndpointAddress;
|
||||
hid_itf->epin_size = desc_ep->wMaxPacketSize.size;
|
||||
|
||||
// Assume bNumDescriptors = 1
|
||||
hid_itf->report_desc_type = desc_hid->bReportType;
|
||||
hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength);
|
||||
hid_itf->report_desc_len = tu_unaligned_read16(&desc_hid->wReportLength);
|
||||
|
||||
hid_itf->boot_mode = false; // default is report mode
|
||||
if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass )
|
||||
{
|
||||
hid_itf->boot_protocol = desc_itf->bInterfaceProtocol;
|
||||
hid_itf->boot_interface = desc_itf->bInterfaceProtocol;
|
||||
|
||||
if ( HID_PROTOCOL_KEYBOARD == desc_itf->bInterfaceProtocol)
|
||||
{
|
||||
TU_LOG2(" Boot Keyboard\r\n");
|
||||
// TODO boot protocol may still have more report in report mode
|
||||
hid_itf->report_info.count = 1;
|
||||
// hid_itf->report_info.count = 1;
|
||||
|
||||
hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP;
|
||||
hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD;
|
||||
hid_itf->report_info.info[0].in_len = 8;
|
||||
hid_itf->report_info.info[0].out_len = 1;
|
||||
// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP;
|
||||
// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_KEYBOARD;
|
||||
// hid_itf->report_info.info[0].in_len = 8;
|
||||
// hid_itf->report_info.info[0].out_len = 1;
|
||||
}
|
||||
else if ( HID_PROTOCOL_MOUSE == desc_itf->bInterfaceProtocol)
|
||||
{
|
||||
TU_LOG2(" Boot Mouse\r\n");
|
||||
// TODO boot protocol may still have more report in report mode
|
||||
hid_itf->report_info.count = 1;
|
||||
// hid_itf->report_info.count = 1;
|
||||
|
||||
hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP;
|
||||
hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE;
|
||||
hid_itf->report_info.info[0].in_len = 5;
|
||||
hid_itf->report_info.info[0].out_len = 0;
|
||||
// hid_itf->report_info.info[0].usage_page = HID_USAGE_PAGE_DESKTOP;
|
||||
// hid_itf->report_info.info[0].usage = HID_USAGE_DESKTOP_MOUSE;
|
||||
// hid_itf->report_info.info[0].in_len = 5;
|
||||
// hid_itf->report_info.info[0].out_len = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -344,15 +315,8 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co
|
||||
uint8_t const* desc_report = usbh_get_enum_buf();
|
||||
uint16_t const desc_len = request->wLength;
|
||||
|
||||
if (tuh_hid_descriptor_report_cb)
|
||||
{
|
||||
tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len);
|
||||
}
|
||||
|
||||
parse_report_descriptor(hid_itf, desc_report, desc_len);
|
||||
|
||||
// enumeration is complete
|
||||
if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance);
|
||||
tuh_hid_mounted_cb(dev_addr, instance, desc_report, desc_len);
|
||||
|
||||
// queue transfer for IN endpoint
|
||||
hidh_get_report(dev_addr, hid_itf);
|
||||
@ -363,8 +327,11 @@ bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t co
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parse Report Descriptor to tuh_hid_report_info_t
|
||||
static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* desc_report, uint16_t desc_len)
|
||||
//--------------------------------------------------------------------+
|
||||
// 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)
|
||||
{
|
||||
// Report Item 6.2.2.2 USB HID 1.11
|
||||
union TU_ATTR_PACKED
|
||||
@ -378,7 +345,20 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
};
|
||||
} header;
|
||||
|
||||
while(desc_len)
|
||||
uint8_t report_num = 0;
|
||||
tuh_hid_report_info_t* info = report_info;
|
||||
|
||||
tu_memclr(report_info, arr_count*sizeof(tuh_hid_report_info_t));
|
||||
|
||||
// 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)
|
||||
{
|
||||
header.byte = *desc_report++;
|
||||
desc_len--;
|
||||
@ -387,6 +367,8 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
uint8_t const type = header.type;
|
||||
uint8_t const size = header.size;
|
||||
|
||||
uint8_t const data8 = desc_report[0];
|
||||
|
||||
TU_LOG2("tag = %d, type = %d, size = %d, data = ", tag, type, size);
|
||||
for(uint32_t i=0; i<size; i++) TU_LOG2("%02X ", desc_report[i]);
|
||||
TU_LOG2("\r\n");
|
||||
@ -399,8 +381,14 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
case RI_MAIN_INPUT: break;
|
||||
case RI_MAIN_OUTPUT: break;
|
||||
case RI_MAIN_FEATURE: break;
|
||||
case RI_MAIN_COLLECTION: break;
|
||||
case RI_MAIN_COLLECTION_END: break;
|
||||
|
||||
case RI_MAIN_COLLECTION:
|
||||
ri_collection_depth++;
|
||||
break;
|
||||
|
||||
case RI_MAIN_COLLECTION_END:
|
||||
ri_collection_depth--;
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
@ -409,16 +397,49 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
case RI_TYPE_GLOBAL:
|
||||
switch(tag)
|
||||
{
|
||||
case RI_GLOBAL_USAGE_PAGE : break;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_LOGICAL_MIN : break;
|
||||
case RI_GLOBAL_LOGICAL_MAX : break;
|
||||
case RI_GLOBAL_PHYSICAL_MIN : break;
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_REPORT_SIZE:
|
||||
// ri_report_size = data8;
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_REPORT_COUNT:
|
||||
// ri_report_count = data8;
|
||||
break;
|
||||
|
||||
case RI_GLOBAL_UNIT_EXPONENT : break;
|
||||
case RI_GLOBAL_UNIT : break;
|
||||
case RI_GLOBAL_REPORT_SIZE : break;
|
||||
case RI_GLOBAL_REPORT_ID : break;
|
||||
case RI_GLOBAL_REPORT_COUNT : break;
|
||||
case RI_GLOBAL_PUSH : break;
|
||||
case RI_GLOBAL_POP : break;
|
||||
|
||||
@ -429,7 +450,11 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
case RI_TYPE_LOCAL:
|
||||
switch(tag)
|
||||
{
|
||||
case RI_LOCAL_USAGE : break;
|
||||
case RI_LOCAL_USAGE:
|
||||
// only take in account the "usage" before starting COLLECTION
|
||||
if ( ri_collection_depth == 0) ri_usage = data8;
|
||||
break;
|
||||
|
||||
case RI_LOCAL_USAGE_MIN : break;
|
||||
case RI_LOCAL_USAGE_MAX : break;
|
||||
case RI_LOCAL_DESIGNATOR_INDEX : break;
|
||||
@ -448,8 +473,22 @@ static void parse_report_descriptor(hidh_interface_t* hid_itf, uint8_t const* de
|
||||
}
|
||||
|
||||
desc_report += size;
|
||||
desc_len -= size;
|
||||
desc_len -= size;
|
||||
}
|
||||
|
||||
if ( report_num == 0 )
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return report_num;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -53,17 +53,12 @@
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t count; // number of info
|
||||
uint16_t usage_page;
|
||||
uint8_t usage;
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t usage_page;
|
||||
uint8_t usage;
|
||||
|
||||
// TODO still use the endpoint size for now
|
||||
uint8_t in_len; // length of IN report
|
||||
uint8_t out_len; // length of OUT report
|
||||
} info[CFG_TUH_HID_REPORT_MAX];
|
||||
// TODO still use the endpoint size for now
|
||||
// uint8_t in_len; // length of IN report
|
||||
// uint8_t out_len; // length of OUT report
|
||||
} tuh_hid_report_info_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
@ -79,47 +74,44 @@ uint8_t tuh_n_hid_instance_count(uint8_t dev_addr);
|
||||
// Check if HID instance is mounted
|
||||
bool tuh_n_hid_n_mounted(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Get boot protocol check out hid_protocol_type_t for possible value
|
||||
uint8_t tuh_n_hid_n_boot_protocol(uint8_t dev_addr, uint8_t instance);
|
||||
// Get boot interface protocol check out hid_protocol_type_t for possible value
|
||||
uint8_t tuh_n_hid_n_interface_protocol(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Check if current mode is Boot (true) or Report (false)
|
||||
bool tuh_n_hid_n_boot_mode(uint8_t dev_addr, uint8_t instance);
|
||||
// Get current protocol mode: Boot (true) or Report (false)
|
||||
// By HID spec, device will be initialized in Report mode
|
||||
bool tuh_n_hid_n_get_protocol(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Get Report information parsed from report descriptor. Data must not be modified by application
|
||||
// If report information does not match the actual device descriptor, that is because the built-in parser
|
||||
// has its limit. Application could use tuh_hid_descriptor_report_cb() callback to parse descriptor by itself.
|
||||
tuh_hid_report_info_t const* tuh_n_hid_n_get_report_info(uint8_t dev_addr, uint8_t instance);
|
||||
// Set protocol to Boot or Report mode.
|
||||
// This function is only supported by Boot interface tuh_n_hid_n_boot_interface()
|
||||
bool tuh_n_hid_n_set_protocol(uint8_t dev_addr, uint8_t instance, bool boot_mode);
|
||||
|
||||
// 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;
|
||||
|
||||
// Check if the interface is ready to use
|
||||
bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
|
||||
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Set Report using control endpoint
|
||||
//bool tuh_n_hid_n_set_report_control(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len);
|
||||
|
||||
//------------- -------------//
|
||||
|
||||
// Check if HID instance with Keyboard is mounted
|
||||
bool tuh_n_hid_n_keyboard_mounted(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Check if HID instance with Mouse is mounted
|
||||
bool tuh_n_hid_n_mouse_mounted(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Callbacks (Weak is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when report descriptor is received
|
||||
// Note: enumeration is still not complete yet at this time
|
||||
TU_ATTR_WEAK void tuh_hid_descriptor_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len);
|
||||
|
||||
// Invoked when device with hid interface is mounted
|
||||
TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance);
|
||||
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
|
||||
// can be used to parse common/simple enough descriptor.
|
||||
void tuh_hid_mounted_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len);
|
||||
|
||||
// Invoked when device with hid interface is un-mounted
|
||||
TU_ATTR_WEAK void tuh_hid_unmounted_cb(uint8_t dev_addr, uint8_t instance);
|
||||
|
||||
// Invoked when received Report from device via either regular or control endpoint
|
||||
TU_ATTR_WEAK void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||
void tuh_hid_get_report_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
|
||||
|
||||
// Invoked when Sent Report to device via either regular or control endpoint
|
||||
TU_ATTR_WEAK void tuh_hid_set_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes);
|
||||
|
Loading…
x
Reference in New Issue
Block a user