Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Host edpt xfer #1403

Merged
merged 22 commits into from
Mar 19, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
move code around
  • Loading branch information
hathach committed Mar 19, 2022
commit a270d8d6236124244f5a1447d57b35f4cfa4909c
202 changes: 108 additions & 94 deletions examples/host/bare_api/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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);
}

//--------------------------------------------------------------------+
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
//--------------------------------------------------------------------+
Expand All @@ -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) {
Expand Down