Skip to content

Commit 58477b7

Browse files
authored
Merge pull request #1035 from hathach/improve-host-stack
Improve host stack
2 parents aab133a + beb1a5c commit 58477b7

File tree

15 files changed

+427
-334
lines changed

15 files changed

+427
-334
lines changed

examples/host/cdc_msc_hid/src/hid_app.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ void hid_app_task(void)
6161
// Invoked when device with hid interface is mounted
6262
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
6363
// can be used to parse common/simple enough descriptor.
64+
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
65+
// therefore report_desc = NULL, desc_len = 0
6466
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
6567
{
6668
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);

src/class/cdc/cdc_host.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,15 @@ void cdch_init(void)
149149
tu_memclr(cdch_data, sizeof(cdch_data_t)*CFG_TUSB_HOST_DEVICE_MAX);
150150
}
151151

152-
uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
152+
bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
153153
{
154154
(void) max_len;
155155

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

162162
cdch_data_t * p_cdc = get_itf(dev_addr);
163163

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

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

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

210-
TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep), 0);
210+
TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));
211211

212212
if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
213213
{
@@ -222,7 +222,7 @@ uint16_t cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const
222222
}
223223
}
224224

225-
return drv_len;
225+
return true;
226226
}
227227

228228
bool cdch_set_config(uint8_t dev_addr, uint8_t itf_num)

src/class/cdc/cdc_host.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,11 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i
121121
//--------------------------------------------------------------------+
122122
// Internal Class Driver API
123123
//--------------------------------------------------------------------+
124-
void cdch_init (void);
125-
uint16_t cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
126-
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
127-
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
128-
void cdch_close (uint8_t dev_addr);
124+
void cdch_init (void);
125+
bool cdch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
126+
bool cdch_set_config (uint8_t dev_addr, uint8_t itf_num);
127+
bool cdch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
128+
void cdch_close (uint8_t dev_addr);
129129

130130
#ifdef __cplusplus
131131
}

src/class/hid/hid_host.c

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -247,33 +247,37 @@ static bool config_set_protocol (uint8_t dev_addr, tusb_control_requ
247247
static bool config_get_report_desc (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
248248
static bool config_get_report_desc_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
249249

250-
uint16_t hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
250+
static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);
251+
252+
bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
251253
{
252254
(void) max_len;
253255

254-
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0);
256+
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
257+
258+
// len = interface + hid + n*endpoints
259+
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) + desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
260+
TU_ASSERT(max_len >= drv_len);
255261

256-
uint16_t drv_len = sizeof(tusb_desc_interface_t);
257262
uint8_t const *p_desc = (uint8_t const *) desc_itf;
258263

259264
//------------- HID descriptor -------------//
260265
p_desc = tu_desc_next(p_desc);
261266
tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
262-
TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType, 0);
267+
TU_ASSERT(HID_DESC_TYPE_HID == desc_hid->bDescriptorType);
263268

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

269274
//------------- Endpoint Descriptor -------------//
270-
drv_len += tu_desc_len(p_desc);
271275
p_desc = tu_desc_next(p_desc);
272276
tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
273-
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType, 0);
277+
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);
274278

275279
// TODO also open endpoint OUT
276-
TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep), 0 );
280+
TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
277281

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

293-
drv_len += desc_itf->bNumEndpoints*sizeof(tusb_desc_endpoint_t);
294-
295-
return drv_len;
297+
return true;
296298
}
297299

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

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

374-
TU_LOG2("HID Get Report Descriptor\r\n");
375-
tusb_control_request_t const new_request =
378+
// Driver is mounted without report descriptor
379+
config_driver_mount_complete(dev_addr, instance, NULL, 0);
380+
}else
376381
{
377-
.bmRequestType_bit =
382+
TU_LOG2("HID Get Report Descriptor\r\n");
383+
tusb_control_request_t const new_request =
378384
{
379-
.recipient = TUSB_REQ_RCPT_INTERFACE,
380-
.type = TUSB_REQ_TYPE_STANDARD,
381-
.direction = TUSB_DIR_IN
382-
},
383-
.bRequest = TUSB_REQ_GET_DESCRIPTOR,
384-
.wValue = tu_u16(hid_itf->report_desc_type, 0),
385-
.wIndex = itf_num,
386-
.wLength = hid_itf->report_desc_len
387-
};
385+
.bmRequestType_bit =
386+
{
387+
.recipient = TUSB_REQ_RCPT_INTERFACE,
388+
.type = TUSB_REQ_TYPE_STANDARD,
389+
.direction = TUSB_DIR_IN
390+
},
391+
.bRequest = TUSB_REQ_GET_DESCRIPTOR,
392+
.wValue = tu_u16(hid_itf->report_desc_type, 0),
393+
.wIndex = itf_num,
394+
.wLength = hid_itf->report_desc_len
395+
};
396+
397+
TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
398+
}
388399

389-
TU_ASSERT(tuh_control_xfer(dev_addr, &new_request, usbh_get_enum_buf(), config_get_report_desc_complete));
390400
return true;
391401
}
392402

393403
static bool config_get_report_desc_complete(uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result)
394404
{
395405
TU_ASSERT(XFER_RESULT_SUCCESS == result);
396406

397-
uint8_t const itf_num = (uint8_t) request->wIndex;
398-
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
399-
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
407+
uint8_t const itf_num = (uint8_t) request->wIndex;
408+
uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
400409

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

413+
config_driver_mount_complete(dev_addr, instance, desc_report, desc_len);
414+
415+
return true;
416+
}
417+
418+
static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
419+
{
420+
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
421+
404422
// enumeration is complete
405423
tuh_hid_mount_cb(dev_addr, instance, desc_report, desc_len);
406424

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

410428
// notify usbh that driver enumeration is complete
411-
usbh_driver_set_config_complete(dev_addr, itf_num);
412-
413-
return true;
429+
usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num);
414430
}
415431

416432
//--------------------------------------------------------------------+

src/class/hid/hid_host.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ uint8_t tuh_hid_parse_report_descriptor(tuh_hid_report_info_t* reports_info_arr,
9797
// Invoked when device with hid interface is mounted
9898
// Report descriptor is also available for use. tuh_hid_parse_report_descriptor()
9999
// can be used to parse common/simple enough descriptor.
100+
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
101+
// therefore report_desc = NULL, desc_len = 0
100102
void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report_desc, uint16_t desc_len);
101103

102104
// Invoked when device with hid interface is un-mounted
@@ -119,11 +121,11 @@ TU_ATTR_WEAK void tuh_hid_set_protocol_complete_cb(uint8_t dev_addr, uint8_t ins
119121
//--------------------------------------------------------------------+
120122
// Internal Class Driver API
121123
//--------------------------------------------------------------------+
122-
void hidh_init (void);
123-
uint16_t hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
124-
bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
125-
bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
126-
void hidh_close (uint8_t dev_addr);
124+
void hidh_init (void);
125+
bool hidh_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
126+
bool hidh_set_config (uint8_t dev_addr, uint8_t itf_num);
127+
bool hidh_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
128+
void hidh_close (uint8_t dev_addr);
127129

128130
#ifdef __cplusplus
129131
}

src/class/msc/msc_host.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,22 +360,22 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
360360
static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
361361
static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
362362

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

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

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

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

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

391391
p_msc->itf_num = desc_itf->bInterfaceNumber;
392392

393-
return drv_len;
393+
return true;
394394
}
395395

396396
bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)

src/class/msc/msc_host.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,11 @@ TU_ATTR_WEAK void tuh_msc_umount_cb(uint8_t dev_addr);
106106
// Internal Class Driver API
107107
//--------------------------------------------------------------------+
108108

109-
void msch_init (void);
110-
uint16_t msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
111-
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
112-
bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
113-
void msch_close (uint8_t dev_addr);
109+
void msch_init (void);
110+
bool msch_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
111+
bool msch_set_config (uint8_t dev_addr, uint8_t itf_num);
112+
void msch_close (uint8_t dev_addr);
113+
bool msch_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
114114

115115
#ifdef __cplusplus
116116
}

src/common/tusb_common.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,23 @@
7373
#include "tusb_error.h" // TODO remove
7474
#include "tusb_timeout.h" // TODO remove
7575

76+
//--------------------------------------------------------------------+
77+
// Internal Helper used by Host and Device Stack
78+
//--------------------------------------------------------------------+
79+
80+
// Check if endpoint descriptor is valid per USB specs
81+
bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
82+
83+
// Bind all endpoint of a interface descriptor to class driver
84+
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
85+
86+
// Calculate total length of n interfaces (depending on IAD)
87+
uint16_t tu_desc_get_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len);
88+
89+
//--------------------------------------------------------------------+
90+
// Internal Inline Functions
91+
//--------------------------------------------------------------------+
92+
7693
//------------- Mem -------------//
7794
#define tu_memclr(buffer, size) memset((buffer), 0, (size))
7895
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))

0 commit comments

Comments
 (0)