|
|
@@ -37,6 +37,13 @@
|
|
|
|
|
|
// English
|
|
|
#define LANGUAGE_ID 0x0409
|
|
|
+#define BUF_COUNT 4
|
|
|
+
|
|
|
+
|
|
|
+tusb_desc_device_t desc_device;
|
|
|
+
|
|
|
+uint8_t buf_pool[BUF_COUNT][64];
|
|
|
+uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
// MACRO CONSTANT TYPEDEF PROTYPES
|
|
|
@@ -47,12 +54,8 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len);
|
|
|
void print_device_descriptor(tuh_xfer_t* xfer);
|
|
|
void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
|
|
|
|
|
|
-tusb_desc_device_t desc_device;
|
|
|
-
|
|
|
-#define BUF_COUNT 4
|
|
|
-
|
|
|
-uint8_t buf_pool[BUF_COUNT][64];
|
|
|
-uint8_t buf_owner[BUF_COUNT] = { 0 }; // device address that owns buffer
|
|
|
+uint8_t* get_hid_buf(uint8_t daddr);
|
|
|
+void free_hid_buf(uint8_t daddr);
|
|
|
|
|
|
/*------------- MAIN -------------*/
|
|
|
int main(void)
|
|
|
@@ -88,6 +91,7 @@ void tuh_mount_cb (uint8_t daddr)
|
|
|
void tuh_umount_cb(uint8_t daddr)
|
|
|
{
|
|
|
printf("Device removed, address = %d\r\n", daddr);
|
|
|
+ free_hid_buf(daddr);
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
@@ -150,63 +154,90 @@ void print_device_descriptor(tuh_xfer_t* xfer)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//--------------------------------------------------------------------+
|
|
|
// Configuration Descriptor
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
|
-// get an buffer from pool
|
|
|
-uint8_t* get_hid_buf(uint8_t daddr)
|
|
|
+// count total length of an interface
|
|
|
+uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
|
|
|
+
|
|
|
+void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
|
|
|
+
|
|
|
+// simple configuration parser to open and listen to HID Endpoint IN
|
|
|
+void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
|
|
|
{
|
|
|
- for(size_t i=0; i<BUF_COUNT; i++)
|
|
|
+ uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
|
|
|
+ uint8_t const* p_desc = tu_desc_next(desc_cfg);
|
|
|
+
|
|
|
+ // parse each interfaces
|
|
|
+ while( p_desc < desc_end )
|
|
|
{
|
|
|
- if (buf_owner[i] == 0)
|
|
|
+ uint8_t assoc_itf_count = 1;
|
|
|
+
|
|
|
+ // Class will always starts with Interface Association (if any) and then Interface descriptor
|
|
|
+ if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
|
|
|
{
|
|
|
- buf_owner[i] = daddr;
|
|
|
- return buf_pool[i];
|
|
|
+ tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
|
|
|
+ assoc_itf_count = desc_iad->bInterfaceCount;
|
|
|
+
|
|
|
+ p_desc = tu_desc_next(p_desc); // next to Interface
|
|
|
}
|
|
|
- }
|
|
|
|
|
|
- // out of memory, increase BUF_COUNT
|
|
|
- return NULL;
|
|
|
-}
|
|
|
+ // must be interface from now
|
|
|
+ if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return;
|
|
|
+ tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
|
|
|
|
|
|
-// free all buffer owned by device
|
|
|
-void free_hid_buf(uint8_t daddr)
|
|
|
-{
|
|
|
- for(size_t i=0; i<BUF_COUNT; i++)
|
|
|
- {
|
|
|
- if (buf_owner[i] == daddr) buf_owner[i] = 0;
|
|
|
+ uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc);
|
|
|
+
|
|
|
+ // probably corrupted descriptor
|
|
|
+ if(drv_len < sizeof(tusb_desc_interface_t)) return;
|
|
|
+
|
|
|
+ // only open and listen to HID endpoint IN
|
|
|
+ if (desc_itf->bInterfaceClass == TUSB_CLASS_HID)
|
|
|
+ {
|
|
|
+ open_hid_interface(dev_addr, desc_itf, drv_len);
|
|
|
+ }
|
|
|
+
|
|
|
+ // next Interface or IAD descriptor
|
|
|
+ p_desc += drv_len;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void hid_report_received(tuh_xfer_t* xfer)
|
|
|
+uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
|
|
|
{
|
|
|
- // Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram
|
|
|
- // For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback
|
|
|
- uint8_t* buf = (uint8_t*) xfer->user_data;
|
|
|
+ uint8_t const* p_desc = (uint8_t const*) desc_itf;
|
|
|
+ uint16_t len = 0;
|
|
|
|
|
|
- if (xfer->result == XFER_RESULT_SUCCESS)
|
|
|
+ while (itf_count--)
|
|
|
{
|
|
|
- printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr);
|
|
|
- for(uint32_t i=0; i<xfer->actual_len; i++)
|
|
|
+ // Next on interface desc
|
|
|
+ len += tu_desc_len(desc_itf);
|
|
|
+ p_desc = tu_desc_next(p_desc);
|
|
|
+
|
|
|
+ while (len < max_len)
|
|
|
{
|
|
|
- if (i%16 == 0) printf("\r\n ");
|
|
|
- printf("%02X ", buf[i]);
|
|
|
+ // return on IAD regardless of itf count
|
|
|
+ if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
|
|
|
+
|
|
|
+ if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
|
|
|
+ ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 )
|
|
|
+ {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ len += tu_desc_len(p_desc);
|
|
|
+ p_desc = tu_desc_next(p_desc);
|
|
|
}
|
|
|
- printf("\r\n");
|
|
|
}
|
|
|
|
|
|
- // continue to submit transfer, with updated buffer
|
|
|
- // other field remain the same
|
|
|
- xfer->buflen = 64;
|
|
|
- xfer->buffer = buf;
|
|
|
-
|
|
|
- tuh_edpt_xfer(xfer);
|
|
|
+ return len;
|
|
|
}
|
|
|
|
|
|
-// count total length of an interface
|
|
|
-uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
|
|
|
+//--------------------------------------------------------------------+
|
|
|
+// HID Interface
|
|
|
+//--------------------------------------------------------------------+
|
|
|
+
|
|
|
+void hid_report_received(tuh_xfer_t* xfer);
|
|
|
|
|
|
void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
|
|
|
{
|
|
|
@@ -260,77 +291,60 @@ void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, ui
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// simple configuration parser to open and listen to HID Endpoint IN
|
|
|
-void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
|
|
|
+void hid_report_received(tuh_xfer_t* xfer)
|
|
|
{
|
|
|
- uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
|
|
|
- uint8_t const* p_desc = tu_desc_next(desc_cfg);
|
|
|
+ // Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram
|
|
|
+ // For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback
|
|
|
+ uint8_t* buf = (uint8_t*) xfer->user_data;
|
|
|
|
|
|
- // parse each interfaces
|
|
|
- while( p_desc < desc_end )
|
|
|
+ if (xfer->result == XFER_RESULT_SUCCESS)
|
|
|
{
|
|
|
- uint8_t assoc_itf_count = 1;
|
|
|
-
|
|
|
- // Class will always starts with Interface Association (if any) and then Interface descriptor
|
|
|
- if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
|
|
|
+ printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr);
|
|
|
+ for(uint32_t i=0; i<xfer->actual_len; i++)
|
|
|
{
|
|
|
- tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
|
|
|
- assoc_itf_count = desc_iad->bInterfaceCount;
|
|
|
-
|
|
|
- p_desc = tu_desc_next(p_desc); // next to Interface
|
|
|
+ if (i%16 == 0) printf("\r\n ");
|
|
|
+ printf("%02X ", buf[i]);
|
|
|
}
|
|
|
+ printf("\r\n");
|
|
|
+ }
|
|
|
|
|
|
- // must be interface from now
|
|
|
- if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return;
|
|
|
- tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
|
|
|
+ // continue to submit transfer, with updated buffer
|
|
|
+ // other field remain the same
|
|
|
+ xfer->buflen = 64;
|
|
|
+ xfer->buffer = buf;
|
|
|
|
|
|
- uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, desc_end-p_desc);
|
|
|
+ tuh_edpt_xfer(xfer);
|
|
|
+}
|
|
|
|
|
|
- // probably corrupted descriptor
|
|
|
- if(drv_len < sizeof(tusb_desc_interface_t)) return;
|
|
|
+//--------------------------------------------------------------------+
|
|
|
+// Buffer helper
|
|
|
+//--------------------------------------------------------------------+
|
|
|
|
|
|
- // only open and listen to HID endpoint IN
|
|
|
- if (desc_itf->bInterfaceClass == TUSB_CLASS_HID)
|
|
|
+// get an buffer from pool
|
|
|
+uint8_t* get_hid_buf(uint8_t daddr)
|
|
|
+{
|
|
|
+ for(size_t i=0; i<BUF_COUNT; i++)
|
|
|
+ {
|
|
|
+ if (buf_owner[i] == 0)
|
|
|
{
|
|
|
- open_hid_interface(dev_addr, desc_itf, drv_len);
|
|
|
+ buf_owner[i] = daddr;
|
|
|
+ return buf_pool[i];
|
|
|
}
|
|
|
-
|
|
|
- // next Interface or IAD descriptor
|
|
|
- p_desc += drv_len;
|
|
|
}
|
|
|
+
|
|
|
+ // out of memory, increase BUF_COUNT
|
|
|
+ return NULL;
|
|
|
}
|
|
|
|
|
|
-uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
|
|
|
+// free all buffer owned by device
|
|
|
+void free_hid_buf(uint8_t daddr)
|
|
|
{
|
|
|
- uint8_t const* p_desc = (uint8_t const*) desc_itf;
|
|
|
- uint16_t len = 0;
|
|
|
-
|
|
|
- while (itf_count--)
|
|
|
+ for(size_t i=0; i<BUF_COUNT; i++)
|
|
|
{
|
|
|
- // Next on interface desc
|
|
|
- len += tu_desc_len(desc_itf);
|
|
|
- p_desc = tu_desc_next(p_desc);
|
|
|
-
|
|
|
- while (len < max_len)
|
|
|
- {
|
|
|
- // return on IAD regardless of itf count
|
|
|
- if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
|
|
|
-
|
|
|
- if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
|
|
|
- ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 )
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- len += tu_desc_len(p_desc);
|
|
|
- p_desc = tu_desc_next(p_desc);
|
|
|
- }
|
|
|
+ if (buf_owner[i] == daddr) buf_owner[i] = 0;
|
|
|
}
|
|
|
-
|
|
|
- return len;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
//--------------------------------------------------------------------+
|
|
|
// Blinking Task
|
|
|
//--------------------------------------------------------------------+
|
|
|
@@ -350,7 +364,7 @@ void led_blinking_task(void)
|
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------+
|
|
|
-// Helper
|
|
|
+// String Descriptor Helper
|
|
|
//--------------------------------------------------------------------+
|
|
|
|
|
|
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
|