summaryrefslogtreecommitdiff
path: root/src/host
diff options
context:
space:
mode:
authorhathach <[email protected]>2023-08-04 12:07:39 +0700
committerhathach <[email protected]>2023-08-04 12:07:39 +0700
commit81aca17d6e9a17d5f37e7ff04988257a0be4ec3e (patch)
tree22cac9af80dae48e558490cb068132d1c7a679f0 /src/host
parentcfc146e18fe2aa0df4d77d435d4a4b7053361cd7 (diff)
parent61f00c0c4dab0469c2e8ebad8eda1a26ae742e46 (diff)
Merge branch 'master' into blackf407VE
Diffstat (limited to 'src/host')
-rw-r--r--src/host/hcd.h12
-rw-r--r--src/host/hub.c2
-rw-r--r--src/host/usbh.c125
-rw-r--r--src/host/usbh.h8
-rw-r--r--src/host/usbh_classdriver.h7
5 files changed, 88 insertions, 66 deletions
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 3355c18b2..d77dd6e2f 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -110,15 +110,15 @@ typedef struct
// clean/flush data cache: write cache -> memory.
// Required before an DMA TX transfer to make sure data is in memory
-void hcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+bool hcd_dcache_clean(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
// invalidate data cache: mark cache as invalid, next read will read from memory
// Required BOTH before and after an DMA RX transfer
-void hcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
// clean and invalidate data cache
// Required before an DMA transfer where memory is both read/write by DMA
-void hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
+bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) TU_ATTR_WEAK;
//--------------------------------------------------------------------+
// Controller API
@@ -171,11 +171,15 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
+
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
// clear stall, data toggle is also reset to DATA0
-bool hcd_edpt_clear_stall(uint8_t daddr, uint8_t ep_addr);
+bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
//--------------------------------------------------------------------+
// USBH implemented API
diff --git a/src/host/hub.c b/src/host/hub.c
index 182bd6ce8..16dd534d2 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -45,8 +45,8 @@ typedef struct
uint8_t itf_num;
uint8_t ep_in;
uint8_t port_count;
- uint8_t status_change; // data from status change interrupt endpoint
+ CFG_TUH_MEM_ALIGN uint8_t status_change;
CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status;
CFG_TUH_MEM_ALIGN hub_status_response_t hub_status;
} hub_interface_t;
diff --git a/src/host/usbh.c b/src/host/usbh.c
index f3e9d3858..49f8c78f1 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -38,18 +38,13 @@
//--------------------------------------------------------------------+
#ifndef CFG_TUH_TASK_QUEUE_SZ
-#define CFG_TUH_TASK_QUEUE_SZ 16
+ #define CFG_TUH_TASK_QUEUE_SZ 16
#endif
#ifndef CFG_TUH_INTERFACE_MAX
-#define CFG_TUH_INTERFACE_MAX 8
+ #define CFG_TUH_INTERFACE_MAX 8
#endif
-// Debug level, TUSB_CFG_DEBUG must be at least this level for debug message
-#define USBH_DEBUG 2
-
-#define TU_LOG_USBH(...) TU_LOG(USBH_DEBUG, __VA_ARGS__)
-
//--------------------------------------------------------------------+
// USBH-HCD common data structure
//--------------------------------------------------------------------+
@@ -256,7 +251,7 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
#if CFG_TUSB_OS == OPT_OS_NONE
// TODO rework time-related function later
-void osal_task_delay(uint32_t msec)
+TU_ATTR_WEAK void osal_task_delay(uint32_t msec)
{
const uint32_t start = hcd_frame_number(_usbh_controller);
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
@@ -322,12 +317,12 @@ bool tuh_init(uint8_t controller_id)
if ( tuh_inited() ) return true;
TU_LOG_USBH("USBH init on controller %u\r\n", controller_id);
- TU_LOG_INT(USBH_DEBUG, sizeof(usbh_device_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(hcd_event_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(_ctrl_xfer));
- TU_LOG_INT(USBH_DEBUG, sizeof(tuh_xfer_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(tu_fifo_t));
- TU_LOG_INT(USBH_DEBUG, sizeof(tu_edpt_stream_t));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(usbh_device_t));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(hcd_event_t));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(_ctrl_xfer));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tuh_xfer_t));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tu_fifo_t));
+ TU_LOG_INT(CFG_TUH_LOG_LEVEL, sizeof(tu_edpt_stream_t));
// Event queue
_usbh_q = osal_queue_create( &_usbh_qdef );
@@ -450,39 +445,28 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
TU_LOG_USBH("on EP %02X with %u bytes: %s\r\n", ep_addr, (unsigned int) event.xfer_complete.len,
tu_str_xfer_result[event.xfer_complete.result]);
- if (event.dev_addr == 0)
- {
+ if (event.dev_addr == 0) {
// device 0 only has control endpoint
TU_ASSERT(epnum == 0, );
usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
+ } else {
usbh_device_t* dev = get_device(event.dev_addr);
TU_VERIFY(dev && dev->connected, );
dev->ep_status[epnum][ep_dir].busy = 0;
dev->ep_status[epnum][ep_dir].claimed = 0;
- if ( 0 == epnum )
- {
- usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }else
- {
- uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
- if(drv_id < USBH_CLASS_DRIVER_COUNT)
- {
- TU_LOG_USBH("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result, event.xfer_complete.len);
- }
- else
- {
-#if CFG_TUH_API_EDPT_XFER
- tuh_xfer_cb_t complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb;
- if ( complete_cb )
- {
- tuh_xfer_t xfer =
- {
+ if ( 0 == epnum ) {
+ usbh_control_xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result,
+ event.xfer_complete.len);
+ }else {
+ // Prefer application callback over built-in one if available. This occurs when tuh_edpt_xfer() is used
+ // with enabled driver e.g HID endpoint
+ #if CFG_TUH_API_EDPT_XFER
+ tuh_xfer_cb_t const complete_cb = dev->ep_callback[epnum][ep_dir].complete_cb;
+ if ( complete_cb ) {
+ // re-construct xfer info
+ tuh_xfer_t xfer = {
.daddr = event.dev_addr,
.ep_addr = ep_addr,
.result = event.xfer_complete.result,
@@ -491,16 +475,21 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
.buffer = NULL, // not available
.complete_cb = complete_cb,
.user_data = dev->ep_callback[epnum][ep_dir].user_data
- };
+ };
- complete_cb(&xfer);
- }else
-#endif
- {
+ complete_cb(&xfer);
+ }else
+ #endif
+ {
+ uint8_t const drv_id = dev->ep2drv[epnum][ep_dir];
+ if ( drv_id < USBH_CLASS_DRIVER_COUNT ) {
+ TU_LOG_USBH("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
+ usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, (xfer_result_t) event.xfer_complete.result,
+ event.xfer_complete.len);
+ } else {
// no driver/callback responsible for this transfer
- TU_ASSERT(false, );
+ TU_ASSERT(false,);
}
-
}
}
}
@@ -565,7 +554,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer)
TU_LOG_USBH("[%u:%u] %s: ", rhport, daddr,
(xfer->setup->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && xfer->setup->bRequest <= TUSB_REQ_SYNCH_FRAME) ?
tu_str_std_request[xfer->setup->bRequest] : "Class Request");
- TU_LOG_PTR(USBH_DEBUG, xfer->setup);
+ TU_LOG_PTR(CFG_TUH_LOG_LEVEL, xfer->setup);
TU_LOG_USBH("\r\n");
if (xfer->complete_cb)
@@ -671,7 +660,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
if (request->wLength)
{
TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, dev_addr);
- TU_LOG_MEM(USBH_DEBUG, _ctrl_xfer.buffer, xferred_bytes, 2);
+ TU_LOG_MEM(CFG_TUH_LOG_LEVEL, _ctrl_xfer.buffer, xferred_bytes, 2);
}
_ctrl_xfer.actual_len = (uint16_t) xferred_bytes;
@@ -714,6 +703,25 @@ bool tuh_edpt_xfer(tuh_xfer_t* xfer)
return true;
}
+bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr) {
+ usbh_device_t* dev = get_device(daddr);
+ TU_VERIFY(dev);
+
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ // skip if not busy
+ TU_VERIFY(dev->ep_status[epnum][dir].busy);
+
+ bool const ret = hcd_edpt_abort_xfer(dev->rhport, daddr, ep_addr);
+ if (ret) {
+ // mark as ready if transfer is aborted
+ dev->ep_status[epnum][dir].busy = false;
+ }
+
+ return ret;
+}
+
//--------------------------------------------------------------------+
// USBH API For Class Driver
//--------------------------------------------------------------------+
@@ -745,7 +753,7 @@ void usbh_int_set(bool enabled)
// Endpoint API
//--------------------------------------------------------------------+
-// TODO has some duplication code with device, refactor later
+// Claim an endpoint for transfer
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
{
// Note: addr0 only use tuh_control_xfer
@@ -761,7 +769,7 @@ bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
return true;
}
-// TODO has some duplication code with device, refactor later
+// Release an claimed endpoint due to failed transfer attempt
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
{
// Note: addr0 only use tuh_control_xfer
@@ -777,7 +785,7 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
return true;
}
-// TODO has some duplication code with device, refactor later
+// Submit an transfer
bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes,
tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
@@ -791,7 +799,7 @@ bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * b
uint8_t const dir = tu_edpt_dir(ep_addr);
tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
- TU_LOG_USBH(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
+ TU_LOG_USBH(" Queue EP %02X with %u bytes ... \r\n", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like an race condition !
TU_ASSERT(ep_state->busy == 0);
@@ -844,14 +852,13 @@ bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep);
}
-bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
-{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
-
+bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) {
usbh_device_t* dev = get_device(dev_addr);
TU_VERIFY(dev);
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
return dev->ep_status[epnum][dir].busy;
}
@@ -1186,7 +1193,7 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu
TU_LOG_USBH("Device unplugged address = %u\r\n", daddr);
if (is_hub_addr(daddr)) {
- TU_LOG(USBH_DEBUG, " is a HUB device %u\r\n", daddr);
+ TU_LOG(CFG_TUH_LOG_LEVEL, " is a HUB device %u\r\n", daddr);
// Submit removed event If the device itself is a hub (un-rolled recursive)
// TODO a better to unroll recursrive is using array of removing_hubs and mark it here
@@ -1657,7 +1664,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
if( drv_id >= USBH_CLASS_DRIVER_COUNT )
{
- TU_LOG(USBH_DEBUG, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
+ TU_LOG(CFG_TUH_LOG_LEVEL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
}
}
@@ -1695,7 +1702,7 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
if (is_hub_addr(dev_addr))
{
- TU_LOG(USBH_DEBUG, "HUB address = %u is mounted\r\n", dev_addr);
+ TU_LOG(CFG_TUH_LOG_LEVEL, "HUB address = %u is mounted\r\n", dev_addr);
}else
{
// Invoke callback if available
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 0f969a46a..0d56f40c9 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -172,8 +172,12 @@ bool tuh_control_xfer(tuh_xfer_t* xfer);
// - sync : blocking if complete callback is NULL.
bool tuh_edpt_xfer(tuh_xfer_t* xfer);
-// Open an non-control endpoint
-bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep);
+// Open a non-control endpoint
+bool tuh_edpt_open(uint8_t daddr, tusb_desc_endpoint_t const * desc_ep);
+
+// Abort a queued transfer. Note: it can only abort transfer that has not been started
+// Return true if a queued transfer is aborted, false if there is no transfer to abort
+bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr);
// Set Configuration (control transfer)
// config_num = 0 will un-configure device. Note: config_num = config_descriptor_index + 1
diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h
index be9811641..308b4418a 100644
--- a/src/host/usbh_classdriver.h
+++ b/src/host/usbh_classdriver.h
@@ -35,6 +35,13 @@
extern "C" {
#endif
+// Level where CFG_TUSB_DEBUG must be at least for USBH is logged
+#ifndef CFG_TUH_LOG_LEVEL
+ #define CFG_TUH_LOG_LEVEL 2
+#endif
+
+#define TU_LOG_USBH(...) TU_LOG(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
+
enum {
USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS)
};