Skip to content

Commit

Permalink
Merge pull request #1035 from hathach/improve-host-stack
Browse files Browse the repository at this point in the history
Improve host stack
  • Loading branch information
hathach authored Aug 20, 2021
2 parents aab133a + beb1a5c commit 58477b7
Show file tree
Hide file tree
Showing 15 changed files with 427 additions and 334 deletions.
2 changes: 2 additions & 0 deletions examples/host/cdc_msc_hid/src/hid_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ void hid_app_task(void)
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_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);
Expand Down
12 changes: 6 additions & 6 deletions src/class/cdc/cdc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ void cdch_init(void)
tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
}

uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
{
(void) max_len;

// Only support ACM subclass
// Protocol 0xFF can be RNDIS device for windows XP
TU_VERIFY( TUSB_CLASS_CDC == itf_desc->bInterfaceClass &&
CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL == itf_desc->bInterfaceSubClass &&
0xFF != itf_desc->bInterfaceProtocol, 0);
0xFF != itf_desc->bInterfaceProtocol);

cdch_data_t * p_cdc = get_itf(dev_addr);

Expand Down Expand Up @@ -186,7 +186,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const
// notification endpoint
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;

TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 );
TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
p_cdc->ep_notif = desc_ep->bEndpointAddress;

drv_len += tu_desc_len(p_desc);
Expand All @@ -205,9 +205,9 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const
for(uint32_t i=0; i<2; i++)
{
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer, 0);
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_BULK == desc_ep->bmAttributes.xfer);

TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0);
TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));

if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
{
Expand All @@ -222,7 +222,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const
}
}

return drv_len;
return true;
}

bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num)
Expand Down
10 changes: 5 additions & 5 deletions src/class/cdc/cdc_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void cdch_init (void);
uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void cdch_close (uint8_t dev_addr);
void cdch_init (void);
bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void cdch_close (uint8_t dev_addr);

#ifdef __cplusplus
}
Expand Down
78 changes: 47 additions & 31 deletions src/class/hid/hid_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,33 +247,37 @@ static bool config_set_protocol (uint8_t dev_addr, tusb_control_requ
static bool config_get_report_desc (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);

uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);

bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
(void) max_len;

TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);

// len = interface + hid + n*endpoints
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
TU_ASSERT(max_len >= drv_len);

uint16_t drv_len = sizeof(tusb_desc_interface_t);
uint8_t const *p_desc = (uint8_t const *) desc_itf;

//------------- HID descriptor -------------//
p_desc = tu_desc_next(p_desc);
tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0);
TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType);

// not enough interface, try to increase CFG_TUH_HID
// TODO multiple devices
hidh_device_t* hid_dev = get_dev(dev_addr);
TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0);

//------------- Endpoint Descriptor -------------//
drv_len += tu_desc_len(p_desc);
p_desc = tu_desc_next(p_desc);
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0);
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);

// TODO also open endpoint OUT
TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 );
TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );

hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count);
hid_dev->inst_count++;
Expand All @@ -290,9 +294,7 @@ uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const
hid_itf->protocol_mode = HID_PROTOCOL_BOOT;
if ( HID_SUBCLASS_BOOT == desc_itf->bInterfaceSubClass ) hid_itf->itf_protocol = desc_itf->bInterfaceProtocol;

drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);

return drv_len;
return true;
}

bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num)
Expand Down Expand Up @@ -367,50 +369,64 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);

// Get Report Descriptor
// Get Report Descriptor if possible
// using usbh enumeration buffer since report descriptor can be very long
TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE );
if( hid_itf->report_desc_len > CFG_TUH_ENUMERATION_BUFSIZE )
{
TU_LOG2("HID Skip Report Descriptor since it is too large %u bytes\r\n", hid_itf->report_desc_len);

TU_LOG2("HID Get Report Descriptor\r\n");
tusb_control_request_t const new_request =
// Driver is mounted without report descriptor
config_driver_mount_complete(dev_addr, instance, NULL, 0);
}else
{
.bmRequestType_bit =
TU_LOG2("HID Get Report Descriptor\r\n");
tusb_control_request_t const new_request =
{
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_STANDARD,
.direction = TUSB_DIR_IN
},
.bRequest = TUSB_REQ_GET_DESCRIPTOR,
.wValue = tu_u16(hid_itf->report_desc_type, 0),
.wIndex = itf_num,
.wLength = hid_itf->report_desc_len
};
.bmRequestType_bit =
{
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_STANDARD,
.direction = TUSB_DIR_IN
},
.bRequest = TUSB_REQ_GET_DESCRIPTOR,
.wValue = tu_u16(hid_itf->report_desc_type, 0),
.wIndex = itf_num,
.wLength = hid_itf->report_desc_len
};

TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
}

TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
return true;
}

static 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 instance = get_instance_id_by_itfnum(dev_addr, itf_num);
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
uint8_t const itf_num = (uint8_t) request->wIndex;
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);

uint8_t const* desc_report = usbh_get_enum_buf();
uint16_t const desc_len = request->wLength;

config_driver_mount_complete(dev_addr, instance, desc_report, desc_len);

return true;
}

static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
{
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);

// enumeration is complete
tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len);

// queue transfer for IN endpoint
hidh_get_report(dev_addr, hid_itf);

// notify usbh that driver enumeration is complete
usbh_driver_set_config_complete(dev_addr, itf_num);

return true;
usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num);
}

//--------------------------------------------------------------------+
Expand Down
12 changes: 7 additions & 5 deletions src/class/hid/hid_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr,
// Invoked when device with hid interface is mounted
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
void tuh_hid_mount_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
Expand All @@ -119,11 +121,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
void hidh_init (void);
uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void hidh_close (uint8_t dev_addr);
void hidh_init (void);
bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
void hidh_close (uint8_t dev_addr);

#ifdef __cplusplus
}
Expand Down
10 changes: 5 additions & 5 deletions src/class/msc/msc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,22 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);

uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);

// msc driver length is fixed
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
TU_ASSERT(drv_len <= max_len, 0);
TU_ASSERT(drv_len <= max_len);

msch_interface_t* p_msc = get_itf(dev_addr);
tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) tu_desc_next(desc_itf);

for(uint32_t i=0; i<2; i++)
{
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer, 0);
TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc), 0);
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType && TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
TU_ASSERT(usbh_edpt_open(rhport, dev_addr, ep_desc));

if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
{
Expand All @@ -390,7 +390,7 @@ uint16_t msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const

p_msc->itf_num = desc_itf->bInterfaceNumber;

return drv_len;
return true;
}

bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
Expand Down
10 changes: 5 additions & 5 deletions src/class/msc/msc_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr);
// Internal Class Driver API
//--------------------------------------------------------------------+

void msch_init (void);
uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void msch_close (uint8_t dev_addr);
void msch_init (void);
bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
void msch_close (uint8_t dev_addr);
bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);

#ifdef __cplusplus
}
Expand Down
17 changes: 17 additions & 0 deletions src/common/tusb_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@
#include "tusb_error.h" // TODO remove
#include "tusb_timeout.h" // TODO remove

//--------------------------------------------------------------------+
// Internal Helper used by Host and Device Stack
//--------------------------------------------------------------------+

// Check if endpoint descriptor is valid per USB specs
bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);

// Bind all endpoint of a interface descriptor to class driver
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);

// Calculate total length of n interfaces (depending on IAD)
uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);

//--------------------------------------------------------------------+
// Internal Inline Functions
//--------------------------------------------------------------------+

//------------- Mem -------------//
#define tu_memclr(buffer, size) memset((buffer), 0, (size))
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
Expand Down
Loading

0 comments on commit 58477b7

Please sign in to comment.