From 102b99a0e8b30a03bae917028fd064ff1480275b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 17 Mar 2022 20:48:32 +0700 Subject: [PATCH] add actual_len supported --- src/host/usbh.c | 46 ++++++++++++++++++++++++++-------------------- src/host/usbh.h | 8 ++++---- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/host/usbh.c b/src/host/usbh.c index 2d01c914..96dd390b 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -250,6 +250,7 @@ struct tuh_control_xfer_cb_t complete_cb; uintptr_t user_arg; + volatile uint16_t actual_len; uint8_t daddr; // device address that is transferring volatile uint8_t stage; }_ctrl_xfer; @@ -306,7 +307,7 @@ void osal_task_delay(uint32_t msec) #endif //--------------------------------------------------------------------+ -// Descriptors +// Descriptors Async //--------------------------------------------------------------------+ static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, @@ -455,7 +456,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, } //--------------------------------------------------------------------+ -// Asynchronous +// Descriptor Sync //--------------------------------------------------------------------+ #define _CONTROL_SYNC_API(_async_func, _timeout, ...) \ @@ -903,13 +904,13 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) usbh_unlock(); TU_VERIFY(is_idle); - const uint8_t rhport = usbh_get_rhport(daddr); TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->setup->bRequest] : "Unknown Request"); TU_LOG2_VAR(&xfer->setup); TU_LOG2("\r\n"); + _ctrl_xfer.actual_len = 0; _ctrl_xfer.daddr = daddr; _ctrl_xfer.request = (*xfer->setup); _ctrl_xfer.buffer = xfer->buffer; @@ -941,8 +942,15 @@ bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t* xfer) // TODO probably some timeout to prevent hanged } - // update result - //xfer->result = result; + // update xfer result + xfer->result = result; + if ( xfer->user_arg ) + { + // if user_arg is not NULL, it is also updated + *((xfer_result_t*) xfer->user_arg) = result; + } + + xfer->actual_len = _ctrl_xfer.actual_len; } return true; @@ -952,19 +960,16 @@ bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t* xfer, uint32_t tim { (void) timeout_ms; - xfer_result_t result = XFER_RESULT_INVALID; - tuh_control_xfer_t xfer_sync = (*xfer); - - xfer_sync.complete_cb = NULL; - xfer_sync.user_arg = (uintptr_t) &result; + // clear callback for sync + xfer->complete_cb = NULL; // TODO use timeout to wait - TU_VERIFY(tuh_control_xfer(daddr, &xfer_sync), XFER_RESULT_TIMEOUT); + TU_VERIFY(tuh_control_xfer(daddr, xfer)); - return result; + return true; } -TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage) +TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage) { usbh_lock(); _ctrl_xfer.stage = stage; @@ -982,7 +987,7 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) .ep_addr = 0, .result = result, .setup = &request, - .actual_len = 0, + .actual_len = (uint32_t) _ctrl_xfer.actual_len, .buffer = _ctrl_xfer.buffer, .complete_cb = _ctrl_xfer.complete_cb, .user_arg = _ctrl_xfer.user_arg @@ -1001,7 +1006,6 @@ static void _xfer_complete(uint8_t dev_addr, xfer_result_t result) static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) ep_addr; - (void) xferred_bytes; const uint8_t rhport = usbh_get_rhport(dev_addr); tusb_control_request_t const * request = &_ctrl_xfer.request; @@ -1020,20 +1024,22 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result if (request->wLength) { // DATA stage: initial data toggle is always 1 - set_control_xfer_stage(CONTROL_STAGE_DATA); + _set_control_xfer_stage(CONTROL_STAGE_DATA); return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength); } __attribute__((fallthrough)); case CONTROL_STAGE_DATA: - if (request->wLength) + if (xferred_bytes) { TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr); - TU_LOG2_MEM(_ctrl_xfer.buffer, request->wLength, 2); + TU_LOG2_MEM(_ctrl_xfer.buffer, xferred_bytes, 2); } + _ctrl_xfer.actual_len = xferred_bytes; + // ACK stage: toggle is always 1 - set_control_xfer_stage(CONTROL_STAGE_ACK); + _set_control_xfer_stage(CONTROL_STAGE_ACK); hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0); break; @@ -1083,7 +1089,7 @@ static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t h hcd_device_close(rhport, dev_addr); clear_device(dev); // abort on-going control xfer if any - if (_ctrl_xfer.daddr == dev_addr) set_control_xfer_stage(CONTROL_STAGE_IDLE); + if (_ctrl_xfer.daddr == dev_addr) _set_control_xfer_stage(CONTROL_STAGE_IDLE); } } } diff --git a/src/host/usbh.h b/src/host/usbh.h index 801938a3..e6897d8d 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -50,7 +50,7 @@ struct tuh_control_xfer_s xfer_result_t result; tusb_control_request_t const* setup; - uint32_t actual_len; + uint32_t actual_len; // excluding setup packet uint8_t* buffer; tuh_control_xfer_cb_t complete_cb; @@ -115,7 +115,8 @@ static inline bool tuh_ready(uint8_t daddr) // Carry out a control transfer // true on success, false if there is on-going control transfer or incorrect parameters -// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable +// Note: blocking if complete callback is NULL. In this case 'xfer->result' will be updated +// and if 'user_arg' point to a xfer_result_t variable, it will be updated as well. bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); //bool tuh_edpt_xfer(uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); @@ -123,7 +124,6 @@ bool tuh_control_xfer(uint8_t daddr, tuh_control_xfer_t* xfer); // Set Configuration (control transfer) // config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1 // true on success, false if there is on-going control transfer or incorrect parameters -// Blocking if complete callback is NULL, in this case 'user_arg' must contain xfer_result_t variable bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg); @@ -132,7 +132,7 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num, //--------------------------------------------------------------------+ // Sync (blocking) version of tuh_control_xfer() -// return transfer result +// xfer contents will be updated to reflect the transfer bool tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t * xfer, uint32_t timeout_ms); //--------------------------------------------------------------------+