summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-05-14 01:02:47 +0700
committerhathach <[email protected]>2021-05-18 12:58:24 +0700
commit9ddc3bfd6dc1450d30c16c0a1d07240ea74a13bf (patch)
tree89f9ca74b765b2fb0ee27f707a533d76cdd66f60 /src
parent641f55f1f18234dbcf3f2b5d46d2231a5e9abae3 (diff)
more host hid API
adding hid parser
Diffstat (limited to 'src')
-rw-r--r--src/class/hid/hid.h60
-rw-r--r--src/class/hid/hid_host.c148
-rw-r--r--src/class/hid/hid_host.h35
3 files changed, 195 insertions, 48 deletions
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index 351a4d600..f0ad03603 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -479,6 +479,7 @@ typedef enum
//--------------------------------------------------------------------+
// REPORT DESCRIPTOR
//--------------------------------------------------------------------+
+
//------------- ITEM & TAG -------------//
#define HID_REPORT_DATA_0(data)
#define HID_REPORT_DATA_1(data) , data
@@ -488,18 +489,31 @@ typedef enum
#define HID_REPORT_ITEM(data, tag, type, size) \
(((tag) << 4) | ((type) << 2) | (size)) HID_REPORT_DATA_##size(data)
-#define RI_TYPE_MAIN 0
-#define RI_TYPE_GLOBAL 1
-#define RI_TYPE_LOCAL 2
+// Report Item Types
+enum {
+ RI_TYPE_MAIN = 0,
+ RI_TYPE_GLOBAL = 1,
+ RI_TYPE_LOCAL = 2
+};
+
+//------------- Main Items - HID 1.11 section 6.2.2.4 -------------//
+
+// Report Item Main group
+enum {
+ RI_MAIN_INPUT = 8,
+ RI_MAIN_OUTPUT = 9,
+ RI_MAIN_COLLECTION = 10,
+ RI_MAIN_FEATURE = 11,
+ RI_MAIN_COLLECTION_END = 12
+};
-//------------- MAIN ITEMS 6.2.2.4 -------------//
#define HID_INPUT(x) HID_REPORT_ITEM(x, 8, RI_TYPE_MAIN, 1)
#define HID_OUTPUT(x) HID_REPORT_ITEM(x, 9, RI_TYPE_MAIN, 1)
#define HID_COLLECTION(x) HID_REPORT_ITEM(x, 10, RI_TYPE_MAIN, 1)
#define HID_FEATURE(x) HID_REPORT_ITEM(x, 11, RI_TYPE_MAIN, 1)
#define HID_COLLECTION_END HID_REPORT_ITEM(x, 12, RI_TYPE_MAIN, 0)
-//------------- INPUT, OUTPUT, FEATURE 6.2.2.5 -------------//
+//------------- Input, Output, Feature - HID 1.11 section 6.2.2.5 -------------//
#define HID_DATA (0<<0)
#define HID_CONSTANT (1<<0)
@@ -527,7 +541,7 @@ typedef enum
#define HID_BITFIELD (0<<8)
#define HID_BUFFERED_BYTES (1<<8)
-//------------- COLLECTION ITEM 6.2.2.6 -------------//
+//------------- Collection Item - HID 1.11 section 6.2.2.6 -------------//
enum {
HID_COLLECTION_PHYSICAL = 0,
HID_COLLECTION_APPLICATION,
@@ -538,7 +552,24 @@ enum {
HID_COLLECTION_USAGE_MODIFIER
};
-//------------- GLOBAL ITEMS 6.2.2.7 -------------//
+//------------- Global Items - HID 1.11 section 6.2.2.7 -------------//
+
+// Report Item Global group
+enum {
+ RI_GLOBAL_USAGE_PAGE = 0,
+ RI_GLOBAL_LOGICAL_MIN = 1,
+ RI_GLOBAL_LOGICAL_MAX = 2,
+ RI_GLOBAL_PHYSICAL_MIN = 3,
+ RI_GLOBAL_PHYSICAL_MAX = 4,
+ RI_GLOBAL_UNIT_EXPONENT = 5,
+ RI_GLOBAL_UNIT = 6,
+ RI_GLOBAL_REPORT_SIZE = 7,
+ RI_GLOBAL_REPORT_ID = 8,
+ RI_GLOBAL_REPORT_COUNT = 9,
+ RI_GLOBAL_PUSH = 10,
+ RI_GLOBAL_POP = 11
+};
+
#define HID_USAGE_PAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, 1)
#define HID_USAGE_PAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_GLOBAL, n)
@@ -573,6 +604,21 @@ enum {
#define HID_POP HID_REPORT_ITEM(x, 11, RI_TYPE_GLOBAL, 0)
//------------- LOCAL ITEMS 6.2.2.8 -------------//
+
+enum {
+ RI_LOCAL_USAGE = 0,
+ RI_LOCAL_USAGE_MIN = 1,
+ RI_LOCAL_USAGE_MAX = 2,
+ RI_LOCAL_DESIGNATOR_INDEX = 3,
+ RI_LOCAL_DESIGNATOR_MIN = 4,
+ RI_LOCAL_DESIGNATOR_MAX = 5,
+ // 6 is reserved
+ RI_LOCAL_STRING_INDEX = 7,
+ RI_LOCAL_STRING_MIN = 8,
+ RI_LOCAL_STRING_MAX = 9,
+ RI_LOCAL_DELIMITER = 10,
+};
+
#define HID_USAGE(x) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, 1)
#define HID_USAGE_N(x, n) HID_REPORT_ITEM(x, 0, RI_TYPE_LOCAL, n)
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index 60ee667d0..862026b5b 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -35,14 +35,15 @@
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-/* "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard
- "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse
- "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control
- "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control
- "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
- "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen
- "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
- "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF
+/*
+ "KEYBOARD" : in_len=8 , out_len=1, usage_page=0x01, usage=0x06 # Generic Desktop, Keyboard
+ "MOUSE" : in_len=4 , out_len=0, usage_page=0x01, usage=0x02 # Generic Desktop, Mouse
+ "CONSUMER" : in_len=2 , out_len=0, usage_page=0x0C, usage=0x01 # Consumer, Consumer Control
+ "SYS_CONTROL" : in_len=1 , out_len=0, usage_page=0x01, usage=0x80 # Generic Desktop, Sys Control
+ "GAMEPAD" : in_len=6 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
+ "DIGITIZER" : in_len=5 , out_len=0, usage_page=0x0D, usage=0x02 # Digitizers, Pen
+ "XAC_COMPATIBLE_GAMEPAD" : in_len=3 , out_len=0, usage_page=0x01, usage=0x05 # Generic Desktop, Game Pad
+ "RAW" : in_len=64, out_len=0, usage_page=0xFFAF, usage=0xAF # Vendor 0xFFAF "Adafruit", 0xAF
*/
typedef struct
{
@@ -57,22 +58,14 @@ typedef struct
uint8_t boot_protocol; // None, Keyboard, Mouse
bool boot_mode; // Boot or Report protocol
- uint8_t report_count; // Number of reports
- struct {
- uint8_t usage_page;
- uint8_t usage;
-
- // TODO just use the endpint size for now
- uint8_t in_len; // length of IN report
- uint8_t out_len; // length of OUT report
- }reports[CFG_TUH_HID_REPORT_MAX];
+ 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;
-}hidh_interface_t;
+} hidh_interface_t;
typedef struct
{
@@ -104,6 +97,23 @@ 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)
+{
+ hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+ return hid_itf->boot_protocol;
+}
+
+bool tuh_n_hid_n_boot_mode(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_ready(uint8_t dev_addr, uint8_t instance)
{
TU_VERIFY(tuh_n_hid_n_mounted(dev_addr, instance));
@@ -190,6 +200,7 @@ 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);
@@ -235,23 +246,25 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
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_count = 1;
+ hid_itf->report_info.count = 1;
- hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP;
- hid_itf->reports[0].usage = HID_USAGE_DESKTOP_KEYBOARD;
- hid_itf->reports[0].in_len = 8;
- hid_itf->reports[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_count = 1;
+ hid_itf->report_info.count = 1;
- hid_itf->reports[0].usage_page = HID_USAGE_PAGE_DESKTOP;
- hid_itf->reports[0].usage = HID_USAGE_DESKTOP_MOUSE;
- hid_itf->reports[0].in_len = 8;
- hid_itf->reports[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_MOUSE;
+ hid_itf->report_info.info[0].in_len = 5;
+ hid_itf->report_info.info[0].out_len = 0;
}
else
{
@@ -326,19 +339,23 @@ bool config_set_idle_complete(uint8_t dev_addr, tusb_control_request_t const * r
bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
{
TU_ASSERT(XFER_RESULT_SUCCESS == result);
- uint8_t const itf_num = (uint8_t) request->wIndex;
- uint8_t const inst = get_instance_id_by_itfnum(dev_addr, itf_num);
- //hidh_interface_t* hid_itf = get_instance(dev_addr, inst);
+
+ uint8_t const itf_num = (uint8_t) request->wIndex;
+ uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
+ hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+
+ 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, inst, usbh_get_enum_buf(), request->wLength);
+ tuh_hid_descriptor_report_cb(dev_addr, instance, desc_report, desc_len);
}
- // TODO Report descriptor parser
+ parse_report_descriptor(hid_itf, desc_report, desc_len);
// enumeration is complete
- if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, inst);
+ if (tuh_hid_mounted_cb) tuh_hid_mounted_cb(dev_addr, instance);
// notify usbh that driver enumeration is complete
usbh_driver_set_config_complete(dev_addr, itf_num);
@@ -346,8 +363,69 @@ 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)
+{
+ enum
+ {
+ USAGE_PAGE = 0x05,
+ USAGE = 0x09,
+ USAGE_MIN = 0x19,
+ USAGE_MAX = 0x29,
+ LOGICAL_MIN = 0x15,
+ LOGICAL_MAX = 0x25,
+ REPORT_SIZE = 0x75,
+ REPORT_COUNT = 0x95
+ };
+
+ // Short Item 6.2.2.2 USB HID 1.11
+ union TU_ATTR_PACKED
+ {
+ uint8_t byte;
+ struct TU_ATTR_PACKED
+ {
+ uint8_t size : 2;
+ uint8_t type : 2;
+ uint8_t tag : 4;
+ };
+ } header;
+
+ while(desc_len)
+ {
+ header.byte = *desc_report++;
+
+ uint8_t const tag = header.tag;
+ uint8_t const type = header.type;
+ uint8_t const size = header.size;
+
+ desc_len--;
+
+ 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");
+
+ switch(type)
+ {
+ case RI_TYPE_MAIN:
+ break;
+
+ case RI_TYPE_GLOBAL:
+ break;
+
+ case RI_TYPE_LOCAL:
+ break;
+
+ // error
+ default: break;
+ }
+
+ desc_report += size;
+ desc_len -= size;
+ }
+}
+
//--------------------------------------------------------------------+
-// Instance helper
+// Helper
//--------------------------------------------------------------------+
// Get Device by address
diff --git a/src/class/hid/hid_host.h b/src/class/hid/hid_host.h
index 45f03a192..2460e5cda 100644
--- a/src/class/hid/hid_host.h
+++ b/src/class/hid/hid_host.h
@@ -46,9 +46,20 @@
#define CFG_TUH_HID_REPORT_MAX 4
#endif
-#ifndef CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE
-#define CFG_TUH_HID_REPORT_DESCRIPTOR_BUFSIZE 256
-#endif
+typedef struct
+{
+ uint8_t count; // number of info
+
+ 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];
+} tuh_hid_report_info_t;
//--------------------------------------------------------------------+
// Application API (Multiple devices)
@@ -63,13 +74,25 @@ 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);
+
+// 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 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);
+
// Check if the interface is ready to use
bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance);
// Get Report from device
bool tuh_n_hid_n_get_report(uint8_t dev_addr, uint8_t instance, void* report, uint16_t len);
-
+// 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);
//------------- -------------//
@@ -93,10 +116,10 @@ TU_ATTR_WEAK void tuh_hid_mounted_cb (uint8_t dev_addr, uint8_t instance);
// 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
+// Invoked when received Report from device via either regular or control endpoint
TU_ATTR_WEAK void tuh_hid_get_report_complete_cb(uint8_t dev_addr, uint8_t instance, uint8_t xferred_bytes);
-// Invoked when Sent Report to device
+// 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);
//--------------------------------------------------------------------+