summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2022-03-20 00:17:39 +0700
committerGitHub <[email protected]>2022-03-20 00:17:39 +0700
commitae531a79f654d566790a4daae350730cdc0a01e9 (patch)
treea67cd9c595a0038f7eecf6f4fcaadf4064a9ac9b /src
parent1915d69cb8da8372b35a5067420c57ddb65d2cb1 (diff)
parenta270d8d6236124244f5a1447d57b35f4cfa4909c (diff)
Merge pull request #1403 from hathach/host-edpt-xfer
Host edpt xfer
Diffstat (limited to 'src')
-rw-r--r--src/class/cdc/cdc_host.c38
-rw-r--r--src/class/cdc/cdc_host.h6
-rw-r--r--src/class/hid/hid.h2
-rw-r--r--src/class/hid/hid_host.c317
-rw-r--r--src/class/msc/msc_host.c51
-rw-r--r--src/host/hub.c221
-rw-r--r--src/host/hub.h14
-rw-r--r--src/host/usbh.c1066
-rw-r--r--src/host/usbh.h92
-rw-r--r--src/host/usbh_classdriver.h13
-rw-r--r--src/portable/ehci/ehci.c25
-rw-r--r--src/tusb.h2
-rw-r--r--src/tusb_option.h4
13 files changed, 1031 insertions, 820 deletions
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index 8ca3dfbcb..044085e81 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -120,32 +120,35 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is
return usbh_edpt_xfer(dev_addr, ep_in, p_buffer, length);
}
-bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb)
+bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb)
{
cdch_data_t const * p_cdc = get_itf(dev_addr);
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
- .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0),
- .wIndex = p_cdc->itf_num,
- .wLength = 0
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = CDC_REQUEST_SET_CONTROL_LINE_STATE,
+ .wValue = (rts ? 2 : 0) | (dtr ? 1 : 0),
+ .wIndex = p_cdc->itf_num,
+ .wLength = 0
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = NULL,
.complete_cb = complete_cb,
- .user_arg = 0
+ .user_data = 0
};
- return tuh_control_xfer(dev_addr, &xfer);
+ return tuh_control_xfer(&xfer);
}
//--------------------------------------------------------------------+
@@ -158,6 +161,7 @@ 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)
{
+ (void) rhport;
(void) max_len;
// Only support ACM subclass
@@ -193,7 +197,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
// 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) );
+ TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) );
p_cdc->ep_notif = desc_ep->bEndpointAddress;
drv_len += tu_desc_len(p_desc);
@@ -214,7 +218,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
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);
- TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));
+ TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep));
if ( tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN )
{
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index 67162a0ca..33dbd2efb 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -42,14 +42,14 @@
* \defgroup CDC_Serial_Host Host
* @{ */
-bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_control_xfer_cb_t complete_cb);
+bool tuh_cdc_set_control_line_state(uint8_t dev_addr, bool dtr, bool rts, tuh_xfer_cb_t complete_cb);
-static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb)
+static inline bool tuh_cdc_connect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb)
{
return tuh_cdc_set_control_line_state(dev_addr, true, true, complete_cb);
}
-static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_control_xfer_cb_t complete_cb)
+static inline bool tuh_cdc_disconnect(uint8_t dev_addr, tuh_xfer_cb_t complete_cb)
{
return tuh_cdc_set_control_line_state(dev_addr, false, false, complete_cb);
}
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index 940454bd9..44a464be1 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -43,7 +43,7 @@
/** \defgroup ClassDriver_HID_Common Common Definitions
* @{ */
- /// USB HID Descriptor
+/// USB HID Descriptor
typedef struct TU_ATTR_PACKED
{
uint8_t bLength; /**< Numeric expression that is the total size of the HID descriptor */
diff --git a/src/class/hid/hid_host.c b/src/class/hid/hid_host.c
index a825858ab..ce3d1598c 100644
--- a/src/class/hid/hid_host.c
+++ b/src/class/hid/hid_host.c
@@ -103,70 +103,80 @@ uint8_t tuh_hid_get_protocol(uint8_t dev_addr, uint8_t instance)
return hid_itf->protocol_mode;
}
-static bool set_protocol_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void set_protocol_complete(tuh_xfer_t* xfer)
{
- uint8_t const itf_num = (uint8_t) xfer->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) tu_le16toh(xfer->setup->wIndex);
+ uint8_t const daddr = xfer->daddr;
+ uint8_t const instance = get_instance_id_by_itfnum(daddr, itf_num);
+ hidh_interface_t* hid_itf = get_instance(daddr, instance);
- if (XFER_RESULT_SUCCESS == result) hid_itf->protocol_mode = (uint8_t) xfer->request.wValue;
+ if (XFER_RESULT_SUCCESS == xfer->result)
+ {
+ hid_itf->protocol_mode = (uint8_t) tu_le16toh(xfer->setup->wValue);
+ }
if (tuh_hid_set_protocol_complete_cb)
{
- tuh_hid_set_protocol_complete_cb(dev_addr, instance, hid_itf->protocol_mode);
+ tuh_hid_set_protocol_complete_cb(daddr, instance, hid_itf->protocol_mode);
}
-
- return true;
}
-bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol)
-{
- hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
- TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE);
+static bool _hidh_set_protocol(uint8_t dev_addr, uint8_t itf_num, uint8_t protocol, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
TU_LOG2("HID Set Protocol = %d\r\n", protocol);
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
- .wValue = protocol,
- .wIndex = hid_itf->itf_num,
- .wLength = 0
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
+ .wValue = protocol,
+ .wIndex = itf_num,
+ .wLength = 0
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = NULL,
- .complete_cb = set_protocol_complete,
- .user_arg = 0
+ .complete_cb = complete_cb,
+ .user_data = user_data
};
- TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
-static bool set_report_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+bool tuh_hid_set_protocol(uint8_t dev_addr, uint8_t instance, uint8_t protocol)
+{
+ hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
+ TU_VERIFY(hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE);
+
+ return _hidh_set_protocol(dev_addr, hid_itf->itf_num, protocol, set_protocol_complete, 0);
+}
+
+static void set_report_complete(tuh_xfer_t* xfer)
{
TU_LOG2("HID Set Report complete\r\n");
if (tuh_hid_set_report_complete_cb)
{
- uint8_t const itf_num = (uint8_t) xfer->request.wIndex;
- uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
+ uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ uint8_t const instance = get_instance_id_by_itfnum(xfer->daddr, itf_num);
- uint8_t const report_type = tu_u16_high(xfer->request.wValue);
- uint8_t const report_id = tu_u16_low(xfer->request.wValue);
+ uint8_t const report_type = tu_u16_high(xfer->setup->wValue);
+ uint8_t const report_id = tu_u16_low(xfer->setup->wValue);
- tuh_hid_set_report_complete_cb(dev_addr, instance, report_id, report_type, (result == XFER_RESULT_SUCCESS) ? xfer->request.wLength : 0);
+ tuh_hid_set_report_complete_cb(xfer->daddr, instance, report_id, report_type,
+ (xfer->result == XFER_RESULT_SUCCESS) ? xfer->setup->wLength : 0);
}
-
- return true;
}
bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t report_type, void* report, uint16_t len)
@@ -174,28 +184,64 @@ bool tuh_hid_set_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, u
hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
TU_LOG2("HID Set Report: id = %u, type = %u, len = %u\r\n", report_id, report_type, len);
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_REPORT,
- .wValue = tu_u16(report_type, report_id),
- .wIndex = hid_itf->itf_num,
- .wLength = len
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = HID_REQ_CONTROL_SET_REPORT,
+ .wValue = tu_u16(report_type, report_id),
+ .wIndex = hid_itf->itf_num,
+ .wLength = len
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = report,
.complete_cb = set_report_complete,
- .user_arg = 0
+ .user_data = 0
+ };
+
+ TU_ASSERT( tuh_control_xfer(&xfer) );
+ return true;
+}
+
+static bool _hidh_set_idle(uint8_t dev_addr, uint8_t itf_num, uint16_t idle_rate, tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ // SET IDLE request, device can stall if not support this request
+ TU_LOG2("HID Set Idle \r\n");
+ tusb_control_request_t const request =
+ {
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = HID_REQ_CONTROL_SET_IDLE,
+ .wValue = idle_rate,
+ .wIndex = itf_num,
+ .wLength = 0
};
- TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) );
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
+ };
+
+ TU_ASSERT( tuh_control_xfer(&xfer) );
+
return true;
}
@@ -210,7 +256,13 @@ bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance)
// claim endpoint
TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_in) );
- return usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size);
+ if ( !usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size) )
+ {
+ usbh_edpt_claim(dev_addr, hid_itf->ep_in);
+ return false;
+ }
+
+ return true;
}
//bool tuh_n_hid_n_ready(uint8_t dev_addr, uint8_t instance)
@@ -270,14 +322,9 @@ void hidh_close(uint8_t dev_addr)
// Enumeration
//--------------------------------------------------------------------+
-static bool config_set_protocol (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-static bool config_get_report_desc (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-static bool config_get_report_desc_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-
-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) rhport;
(void) max_len;
TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass);
@@ -309,7 +356,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
for(int i = 0; i < desc_itf->bNumEndpoints; i++)
{
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType);
- TU_ASSERT( usbh_edpt_open(rhport, dev_addr, desc_ep) );
+ TU_ASSERT( tuh_edpt_open(dev_addr, desc_ep) );
if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
{
@@ -341,121 +388,93 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
return true;
}
-bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num)
-{
- uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
- hidh_interface_t* hid_itf = get_instance(dev_addr, instance);
-
- // Idle rate = 0 mean only report when there is changes
- uint16_t const idle_rate = 0;
-
- // SET IDLE request, device can stall if not support this request
- TU_LOG2("HID Set Idle \r\n");
- tuh_control_xfer_t const xfer =
- {
- .request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_IDLE,
- .wValue = idle_rate,
- .wIndex = itf_num,
- .wLength = 0
- },
-
- .buffer = NULL,
- .complete_cb = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? config_set_protocol : config_get_report_desc,
- .user_arg = 0
- };
+//--------------------------------------------------------------------+
+// Set Configure
+//--------------------------------------------------------------------+
- TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) );
+enum {
+ CONFG_SET_IDLE,
+ CONFIG_SET_PROTOCOL,
+ CONFIG_GET_REPORT_DESC,
+ CONFIG_COMPLETE
+};
- return true;
-}
+static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len);
+static void process_set_config(tuh_xfer_t* xfer);
-// Force device to work in BOOT protocol
-static bool config_set_protocol(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+bool hidh_set_config(uint8_t dev_addr, uint8_t itf_num)
{
- // Stall is a valid response for SET_IDLE, therefore we could ignore its result
- (void) result;
-
- uint8_t const itf_num = (uint8_t) xfer->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);
+ tusb_control_request_t request;
+ request.wIndex = tu_htole16((uint16_t) itf_num);
- TU_LOG2("HID Set Protocol to Boot Mode\r\n");
- hid_itf->protocol_mode = HID_PROTOCOL_BOOT;
- tuh_control_xfer_t const new_xfer =
- {
- .request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HID_REQ_CONTROL_SET_PROTOCOL,
- .wValue = HID_PROTOCOL_BOOT,
- .wIndex = hid_itf->itf_num,
- .wLength = 0
- },
+ tuh_xfer_t xfer;
+ xfer.daddr = dev_addr;
+ xfer.result = XFER_RESULT_SUCCESS;
+ xfer.setup = &request;
+ xfer.user_data = CONFG_SET_IDLE;
- .buffer = NULL,
- .complete_cb = config_get_report_desc,
- .user_arg = 0
- };
+ // fake request to kick-off the set config process
+ process_set_config(&xfer);
- TU_ASSERT( tuh_control_xfer(dev_addr, &new_xfer) );
return true;
}
-static bool config_get_report_desc(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void process_set_config(tuh_xfer_t* xfer)
{
- // We can be here after SET_IDLE or SET_PROTOCOL (boot device)
- // Trigger assert if result is not successful with set protocol
- if ( xfer->request.bRequest != HID_REQ_CONTROL_SET_IDLE )
+ // Stall is a valid response for SET_IDLE, therefore we could ignore its result
+ if ( xfer->setup->bRequest != HID_REQ_CONTROL_SET_IDLE )
{
- TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
}
- uint8_t const itf_num = (uint8_t) xfer->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);
+ uintptr_t const state = xfer->user_data;
+ uint8_t const itf_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ uint8_t const daddr = xfer->daddr;
- // Get Report Descriptor if possible
- // using usbh enumeration buffer since report descriptor can be very long
- 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);
+ uint8_t const instance = get_instance_id_by_itfnum(daddr, itf_num);
+ hidh_interface_t* hid_itf = get_instance(daddr, instance);
- // Driver is mounted without report descriptor
- config_driver_mount_complete(dev_addr, instance, NULL, 0);
- }else
+ switch(state)
{
- TU_ASSERT(tuh_descriptor_get_hid_report(dev_addr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, config_get_report_desc_complete, 0));
- }
+ case CONFG_SET_IDLE:
+ {
+ // Idle rate = 0 mean only report when there is changes
+ const uint16_t idle_rate = 0;
+ const uintptr_t next_state = (hid_itf->itf_protocol != HID_ITF_PROTOCOL_NONE) ? CONFIG_SET_PROTOCOL : CONFIG_GET_REPORT_DESC;
+ _hidh_set_idle(daddr, itf_num, idle_rate, process_set_config, next_state);
+ }
+ break;
- return true;
-}
+ case CONFIG_SET_PROTOCOL:
+ _hidh_set_protocol(daddr, hid_itf->itf_num, HID_PROTOCOL_BOOT, process_set_config, CONFIG_GET_REPORT_DESC);
+ break;
-static bool config_get_report_desc_complete(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
-{
- TU_ASSERT(XFER_RESULT_SUCCESS == result);
+ case CONFIG_GET_REPORT_DESC:
+ // Get Report Descriptor if possible
+ // using usbh enumeration buffer since report descriptor can be very long
+ 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);
- uint8_t const itf_num = (uint8_t) xfer->request.wIndex;
- uint8_t const instance = get_instance_id_by_itfnum(dev_addr, itf_num);
+ // Driver is mounted without report descriptor
+ config_driver_mount_complete(daddr, instance, NULL, 0);
+ }else
+ {
+ tuh_descriptor_get_hid_report(daddr, itf_num, hid_itf->report_desc_type, 0, usbh_get_enum_buf(), hid_itf->report_desc_len, process_set_config, CONFIG_COMPLETE);
+ }
+ break;
- uint8_t const* desc_report = usbh_get_enum_buf();
- uint16_t const desc_len = xfer->request.wLength;
+ case CONFIG_COMPLETE:
+ {
+ uint8_t const* desc_report = usbh_get_enum_buf();
+ uint16_t const desc_len = tu_le16toh(xfer->setup->wLength);
- config_driver_mount_complete(dev_addr, instance, desc_report, desc_len);
+ config_driver_mount_complete(daddr, instance, desc_report, desc_len);
+ }
+ break;
- return true;
+ default: break;
+ }
}
static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
diff --git a/src/class/msc/msc_host.c b/src/class/msc/msc_host.c
index c009e5088..c54a63f37 100644
--- a/src/class/msc/msc_host.c
+++ b/src/class/msc/msc_host.c
@@ -358,13 +358,14 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
// MSC Enumeration
//--------------------------------------------------------------------+
-static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
+static void config_get_maxlun_complete (tuh_xfer_t* xfer);
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
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);
bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
{
+ (void) rhport;
TU_VERIFY (MSC_SUBCLASS_SCSI == desc_itf->bInterfaceSubClass &&
MSC_PROTOCOL_BOT == desc_itf->bInterfaceProtocol);
@@ -378,7 +379,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
for(uint32_t i=0; i<2; i++)
{
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));
+ TU_ASSERT(tuh_edpt_open(dev_addr, ep_desc));
if ( tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
{
@@ -405,47 +406,47 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
//------------- Get Max Lun -------------//
TU_LOG2("MSC Get Max Lun\r\n");
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN
- },
- .bRequest = MSC_REQ_GET_MAX_LUN,
- .wValue = 0,
- .wIndex = itf_num,
- .wLength = 1
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
},
+ .bRequest = MSC_REQ_GET_MAX_LUN,
+ .wValue = 0,
+ .wIndex = itf_num,
+ .wLength = 1
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = &p_msc->max_lun,
.complete_cb = config_get_maxlun_complete,
- .user_arg = 0
+ .user_data = 0
};
- TU_ASSERT(tuh_control_xfer(dev_addr, &xfer));
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
-static bool config_get_maxlun_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void config_get_maxlun_complete (tuh_xfer_t* xfer)
{
- (void) xfer;
-
- msch_interface_t* p_msc = get_itf(dev_addr);
+ uint8_t const daddr = xfer->daddr;
+ msch_interface_t* p_msc = get_itf(daddr);
// STALL means zero
- p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
+ p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
p_msc->max_lun++; // MAX LUN is minus 1 by specs
// TODO multiple LUN support
TU_LOG2("SCSI Test Unit Ready\r\n");
uint8_t const lun = 0;
- tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
-
- return true;
+ tuh_msc_test_unit_ready(daddr, lun, config_test_unit_ready_complete);
}
static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
@@ -483,7 +484,7 @@ static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw
// Capacity response field: Block size and Last LBA are both Big-Endian
scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) ((void*) _msch_buffer);
p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
- p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
+ p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
// Mark enumeration is complete
p_msc->mounted = true;
diff --git a/src/host/hub.c b/src/host/hub.c
index c1909cb5c..9e546f6f7 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -78,89 +78,98 @@ static char const* const _hub_feature_str[] =
// HUB
//--------------------------------------------------------------------+
bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_OTHER,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HUB_REQUEST_CLEAR_FEATURE,
- .wValue = feature,
- .wIndex = hub_port,
- .wLength = 0
+ .recipient = TUSB_REQ_RCPT_OTHER,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = HUB_REQUEST_CLEAR_FEATURE,
+ .wValue = feature,
+ .wIndex = hub_port,
+ .wLength = 0
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = hub_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = NULL,
.complete_cb = complete_cb,
- .user_arg = user_arg
+ .user_data = user_data
};
TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
- TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_OTHER,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = HUB_REQUEST_SET_FEATURE,
- .wValue = feature,
- .wIndex = hub_port,
- .wLength = 0
+ .recipient = TUSB_REQ_RCPT_OTHER,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = HUB_REQUEST_SET_FEATURE,
+ .wValue = feature,
+ .wIndex = hub_port,
+ .wLength = 0
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = hub_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = NULL,
.complete_cb = complete_cb,
- .user_arg = user_arg
+ .user_data = user_data
};
TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
- TU_ASSERT( tuh_control_xfer(hub_addr, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_OTHER,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN
- },
- .bRequest = HUB_REQUEST_GET_STATUS,
- .wValue = 0,
- .wIndex = hub_port,
- .wLength = 4
+ .recipient = TUSB_REQ_RCPT_OTHER,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
},
+ .bRequest = HUB_REQUEST_GET_STATUS,
+ .wValue = 0,
+ .wIndex = hub_port,
+ .wLength = 4
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = hub_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = resp,
.complete_cb = complete_cb,
- .user_arg = user_arg
+ .user_data = user_data
};
TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port);
- TU_ASSERT( tuh_control_xfer( hub_addr, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
@@ -174,6 +183,8 @@ void hub_init(void)
bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
{
+ (void) rhport;
+
TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass &&
0 == itf_desc->bInterfaceSubClass);
@@ -190,7 +201,7 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType &&
TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0);
- TU_ASSERT(usbh_edpt_open(rhport, dev_addr, desc_ep));
+ TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep));
hub_interface_t* p_hub = get_itf(dev_addr);
@@ -219,8 +230,8 @@ bool hub_edpt_status_xfer(uint8_t dev_addr)
// Set Configure
//--------------------------------------------------------------------+
-static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
+static void config_set_port_power (tuh_xfer_t* xfer);
+static void config_port_power_complete (tuh_xfer_t* xfer);
bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
{
@@ -228,38 +239,41 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
TU_ASSERT(itf_num == p_hub->itf_num);
// Get Hub Descriptor
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_CLASS,
- .direction = TUSB_DIR_IN
- },
- .bRequest = HUB_REQUEST_GET_DESCRIPTOR,
- .wValue = 0,
- .wIndex = 0,
- .wLength = sizeof(descriptor_hub_desc_t)
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_CLASS,
+ .direction = TUSB_DIR_IN
},
+ .bRequest = HUB_REQUEST_GET_DESCRIPTOR,
+ .wValue = 0,
+ .wIndex = 0,
+ .wLength = sizeof(descriptor_hub_desc_t)
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = dev_addr,
+ .ep_addr = 0,
+ .setup = &request,
.buffer = _hub_buffer,
.complete_cb = config_set_port_power,
- .user_arg = 0
+ .user_data = 0
};
- TU_ASSERT( tuh_control_xfer(dev_addr, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
-static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void config_set_port_power (tuh_xfer_t* xfer)
{
- (void) xfer;
- TU_ASSERT(XFER_RESULT_SUCCESS == result);
+ TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, );
- hub_interface_t* p_hub = get_itf(dev_addr);
+ uint8_t const daddr = xfer->daddr;
+ hub_interface_t* p_hub = get_itf(daddr);
// only use number of ports in hub descriptor
descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer;
@@ -269,38 +283,38 @@ static bool config_set_port_power (uint8_t dev_addr, tuh_control_xfer_t const *
// Set Port Power to be able to detect connection, starting with port 1
uint8_t const hub_port = 1;
- return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
+ hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
}
-static bool config_port_power_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void config_port_power_complete (tuh_xfer_t* xfer)
{
- TU_ASSERT(XFER_RESULT_SUCCESS == result);
- hub_interface_t* p_hub = get_itf(dev_addr);
+ TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, );
+
+ uint8_t const daddr = xfer->daddr;
+ hub_interface_t* p_hub = get_itf(daddr);
- if (xfer->request.wIndex == p_hub->port_count)
+ if (xfer->setup->wIndex == p_hub->port_count)
{
// All ports are power -> queue notification status endpoint and
// complete the SET CONFIGURATION
- TU_ASSERT( usbh_edpt_xfer(dev_addr, p_hub->ep_in, &p_hub->status_change, 1) );
+ TU_ASSERT( usbh_edpt_xfer(daddr, p_hub->ep_in, &p_hub->status_change, 1), );
- usbh_driver_set_config_complete(dev_addr, p_hub->itf_num);
+ usbh_driver_set_config_complete(daddr, p_hub->itf_num);
}else
{
// power next port
- uint8_t const hub_port = (uint8_t) (xfer->request.wIndex + 1);
- return hub_port_set_feature(dev_addr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
+ uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1);
+ hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
}
-
- return true;
}
//--------------------------------------------------------------------+
// Connection Changes
//--------------------------------------------------------------------+
-static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
-static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result);
+static void connection_get_status_complete (tuh_xfer_t* xfer);
+static void connection_clear_conn_change_complete (tuh_xfer_t* xfer);
+static void connection_port_reset_complete (tuh_xfer_t* xfer);
// callback as response of interrupt endpoint polling
bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
@@ -328,12 +342,13 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
return true;
}
-static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void connection_get_status_complete (tuh_xfer_t* xfer)
{
- TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
- hub_interface_t* p_hub = get_itf(dev_addr);
- uint8_t const port_num = (uint8_t) xfer->request.wIndex;
+ uint8_t const daddr = xfer->daddr;
+ hub_interface_t* p_hub = get_itf(daddr);
+ uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
// Connection change
if (p_hub->port_status.change.connection)
@@ -342,7 +357,7 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t
//TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, );
// Acknowledge Port Connection Change
- hub_port_clear_feature(dev_addr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
+ hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
}else
{
// Other changes are: Enable, Suspend, Over Current, Reset, L1 state
@@ -350,65 +365,61 @@ static bool connection_get_status_complete (uint8_t dev_addr, tuh_control_xfer_t
// prepare for next hub status
// TODO continue with status_change, or maybe we can do it again with status
- hub_edpt_status_xfer(dev_addr);
+ hub_edpt_status_xfer(daddr);
}
-
- return true;
}
-static bool connection_clear_conn_change_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void connection_clear_conn_change_complete (tuh_xfer_t* xfer)
{
- TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
- hub_interface_t* p_hub = get_itf(dev_addr);
- uint8_t const port_num = (uint8_t) xfer->request.wIndex;
+ uint8_t const daddr = xfer->daddr;
+ hub_interface_t* p_hub = get_itf(daddr);
+ uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
if ( p_hub->port_status.status.connection )
{
// Reset port if attach event
- hub_port_reset(dev_addr, port_num, connection_port_reset_complete, 0);
+ hub_port_reset(daddr, port_num, connection_port_reset_complete, 0);
}else
{
// submit detach event
hcd_event_t event =
{
- .rhport = usbh_get_rhport(dev_addr),
+ .rhport = usbh_get_rhport(daddr),
.event_id = HCD_EVENT_DEVICE_REMOVE,
.connection =
{
- .hub_addr = dev_addr,
+ .hub_addr = daddr,
.hub_port = port_num
}
};
hcd_event_handler(&event, false);
}
-
- return true;
}
-static bool connection_port_reset_complete (uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void connection_port_reset_complete (tuh_xfer_t* xfer)
{
- TU_ASSERT(result == XFER_RESULT_SUCCESS);
+ TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
- // hub_interface_t* p_hub = get_itf(dev_addr);
- uint8_t const port_num = (uint8_t) xfer->request.wIndex;
+ uint8_t const daddr = xfer->daddr;
+ // hub_interface_t* p_hub = get_itf(daddr);
+ uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
// submit attach event
hcd_event_t event =
{
- .rhport = usbh_get_rhport(dev_addr),
+ .rhport = usbh_get_rhport(daddr),
.event_id = HCD_EVENT_DEVICE_ATTACH,
.connection =
{
- .hub_addr = dev_addr,
+ .hub_addr = daddr,
.hub_port = port_num
}
};
hcd_event_handler(&event, false);
-
- return true;
}
#endif
diff --git a/src/host/hub.h b/src/host/hub.h
index 30cf3dd1c..390740e1f 100644
--- a/src/host/hub.h
+++ b/src/host/hub.h
@@ -173,31 +173,31 @@ TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"
// Clear feature
bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Set feature
bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get port status
bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get status from Interrupt endpoint
bool hub_edpt_status_xfer(uint8_t dev_addr);
// Reset a port
static inline bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_arg);
+ return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data);
}
// Clear Reset Change
static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_arg);
+ return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data);
}
diff --git a/src/host/usbh.c b/src/host/usbh.c
index c7dfaddf6..f534070de 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -82,8 +82,7 @@ typedef struct {
uint8_t speed;
// Device State
- struct TU_ATTR_PACKED
- {
+ struct TU_ATTR_PACKED {
volatile uint8_t connected : 1;
volatile uint8_t addressed : 1;
volatile uint8_t configured : 1;
@@ -109,6 +108,14 @@ typedef struct {
tu_edpt_state_t ep_status[CFG_TUH_ENDPOINT_MAX][2];
+#if CFG_TUH_API_EDPT_XFER
+ // TODO array can be CFG_TUH_ENDPOINT_MAX-1
+ struct {
+ tuh_xfer_cb_t complete_cb;
+ uintptr_t user_data;
+ }ep_callback[CFG_TUH_ENDPOINT_MAX][2];
+#endif
+
} usbh_device_t;
//--------------------------------------------------------------------+
@@ -223,6 +230,8 @@ TU_ATTR_ALWAYS_INLINE static inline void usbh_unlock(void)
#else
+#define _usbh_mutex NULL
+
#define usbh_lock()
#define usbh_unlock()
@@ -241,9 +250,14 @@ static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
// We will only execute control transfer one at a time.
struct
{
- tuh_control_xfer_t xfer;
- uint8_t daddr; // device address that is transferring
+ tusb_control_request_t request TU_ATTR_ALIGNED(4);
+ uint8_t* buffer;
+ tuh_xfer_cb_t complete_cb;
+ uintptr_t user_data;
+
+ uint8_t daddr;
volatile uint8_t stage;
+ volatile uint16_t actual_len;
}_ctrl_xfer;
//------------- Helper Function -------------//
@@ -251,7 +265,7 @@ struct
TU_ATTR_ALWAYS_INLINE
static inline usbh_device_t* get_device(uint8_t dev_addr)
{
- TU_ASSERT(dev_addr, NULL);
+ TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL);
return &_usbh_devices[dev_addr-1];
}
@@ -265,15 +279,17 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
//--------------------------------------------------------------------+
bool tuh_mounted(uint8_t dev_addr)
{
- return get_device(dev_addr)->configured;
+ usbh_device_t* dev = get_device(dev_addr);
+ TU_VERIFY(dev);
+ return dev->configured;
}
bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
{
*vid = *pid = 0;
- TU_VERIFY(tuh_mounted(dev_addr));
usbh_device_t const* dev = get_device(dev_addr);
+ TU_VERIFY(dev && dev->configured);
*vid = dev->vid;
*pid = dev->pid;
@@ -283,7 +299,8 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
tusb_speed_t tuh_speed_get (uint8_t dev_addr)
{
- return (tusb_speed_t) (dev_addr ? get_device(dev_addr)->speed : _dev0.speed);
+ usbh_device_t* dev = get_device(dev_addr);
+ return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed);
}
#if CFG_TUSB_OS == OPT_OS_NONE
@@ -297,210 +314,6 @@ void osal_task_delay(uint32_t msec)
#endif
//--------------------------------------------------------------------+
-// Descriptors
-//--------------------------------------------------------------------+
-
-static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- tuh_control_xfer_t const xfer =
- {
- .request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_IN
- },
- .bRequest = TUSB_REQ_GET_DESCRIPTOR,
- .wValue = tu_htole16( TU_U16(type, index) ),
- .wIndex = tu_htole16(language_id),
- .wLength = tu_htole16(len)
- },
-
- .buffer = buffer,
- .complete_cb = complete_cb,
- .user_arg = user_arg
- };
-
- return tuh_control_xfer(daddr, &xfer);
-}
-
-bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_arg);
-}
-
-bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- len = tu_min16(len, sizeof(tusb_desc_device_t));
- return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_arg);
-}
-
-bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_arg);
-}
-
-//------------- String Descriptor -------------//
-
-bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_arg);
-}
-
-// Get manufacturer string descriptor
-bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- TU_VERIFY(tuh_mounted(daddr));
- usbh_device_t const* dev = get_device(daddr);
- if (dev->i_manufacturer == 0) {
- return false;
- }
- return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_arg);
-}
-
-// Get product string descriptor
-bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- TU_VERIFY(tuh_mounted(daddr));
- usbh_device_t const* dev = get_device(daddr);
- if (dev->i_product == 0) {
- return false;
- }
- return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_arg);
-}
-
-// Get serial string descriptor
-bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- TU_VERIFY(tuh_mounted(daddr));
- usbh_device_t const* dev = get_device(daddr);
- if (dev->i_serial == 0) {
- return false;
- }
- return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_arg);
-}
-
-// Get HID report descriptor
-bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- TU_LOG2("HID Get Report Descriptor\r\n");
- tuh_control_xfer_t const xfer =
- {
- .request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_INTERFACE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_IN
- },
- .bRequest = TUSB_REQ_GET_DESCRIPTOR,
- .wValue = tu_htole16(TU_U16(desc_type, index)),
- .wIndex = tu_htole16((uint16_t) itf_num),
- .wLength = len
- },
-
- .buffer = buffer,
- .complete_cb = complete_cb,
- .user_arg = user_arg
- };
-
- return tuh_control_xfer(daddr, &xfer);
-}
-
-bool tuh_configuration_set(uint8_t daddr, uint8_t config_num,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg)
-{
- TU_LOG2("Set Configuration = %d\r\n", config_num);
-
- tuh_control_xfer_t const xfer =
- {
- .request =
- {
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_CONFIGURATION,
- .wValue = tu_htole16(config_num),
- .wIndex = 0,
- .wLength = 0
- },
-
- .buffer = NULL,
- .complete_cb = complete_cb,
- .user_arg = user_arg
- };
-
- return tuh_control_xfer(daddr, &xfer);
-}
-
-//--------------------------------------------------------------------+
-// Asynchronous
-//--------------------------------------------------------------------+
-
-#define _CONTROL_SYNC_API(_async_func, _timeout, ...) \
- (void) _timeout; \
- xfer_result_t result = XFER_RESULT_INVALID;\
- /* TODO use timeout to wait */ \
- TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
- return (uint8_t) result
-
-uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get, timeout_ms, daddr, type, index, buffer, len);
-}
-
-uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- len = tu_min16(len, sizeof(tusb_desc_device_t));
- return tuh_descriptor_get_sync(daddr, TUSB_DESC_DEVICE, 0, buffer, len, timeout_ms);
-}
-
-uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- return tuh_descriptor_get_sync(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, timeout_ms);
-}
-
-uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, timeout_ms, daddr, itf_num, desc_type, index, buffer, len);
-}
-
-uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get_string, timeout_ms, daddr, index, language_id, buffer, len);
-}
-
-uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, timeout_ms, daddr, language_id, buffer, len);
-}
-
-uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get_product_string, timeout_ms, daddr, language_id, buffer, len);
-}
-
-uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms)
-{
- _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, timeout_ms, daddr, language_id, buffer, len);
-}
-
-//--------------------------------------------------------------------+
// CLASS-USBD API (don't require to verify parameters)
//--------------------------------------------------------------------+
@@ -524,7 +337,8 @@ bool tuh_init(uint8_t rhport)
TU_LOG2("USBH init\r\n");
TU_LOG2_INT(sizeof(usbh_device_t));
TU_LOG2_INT(sizeof(hcd_event_t));
- TU_LOG2_INT(sizeof(tuh_control_xfer_t));
+ TU_LOG2_INT(sizeof(_ctrl_xfer));
+ TU_LOG2_INT(sizeof(tuh_xfer_t));
// Event queue
_usbh_q = osal_queue_create( &_usbh_qdef );
@@ -629,6 +443,8 @@ void tuh_task(void)
else
{
usbh_device_t* dev = get_device(event.dev_addr);
+ TU_ASSERT(dev, );
+
dev->ep_status[epnum][ep_dir].busy = 0;
dev->ep_status[epnum][ep_dir].claimed = 0;
@@ -638,10 +454,38 @@ void tuh_task(void)
}else
{
uint8_t drv_id = dev->ep2drv[epnum][ep_dir];
- TU_ASSERT(drv_id < USBH_CLASS_DRIVER_COUNT, );
+ if(drv_id < USBH_CLASS_DRIVER_COUNT)
+ {
+ TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
+ usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, 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 =
+ {
+ .daddr = event.dev_addr,
+ .ep_addr = ep_addr,
+ .result = event.xfer_complete.result,
+ .actual_len = event.xfer_complete.len,
+ .buflen = 0, // not available
+ .buffer = NULL, // not available
+ .complete_cb = complete_cb,
+ .user_data = dev->ep_callback[epnum][ep_dir].user_data
+ };
- TU_LOG2("%s xfer callback\r\n", usbh_class_drivers[drv_id].name);
- usbh_class_drivers[drv_id].xfer_cb(event.dev_addr, ep_addr, event.xfer_complete.result, event.xfer_complete.len);
+ complete_cb(&xfer);
+ }else
+#endif
+ {
+ // no driver/callback responsible for this transfer
+ TU_ASSERT(false, );
+ }
+
+ }
}
}
}
@@ -657,108 +501,217 @@ void tuh_task(void)
}
//--------------------------------------------------------------------+
-// USBH API For Class Driver
+// Control transfer
//--------------------------------------------------------------------+
-uint8_t usbh_get_rhport(uint8_t dev_addr)
+static void _control_blocking_complete_cb(tuh_xfer_t* xfer)
{
- return (dev_addr == 0) ? _dev0.rhport : get_device(dev_addr)->rhport;
+ // update result
+ *((xfer_result_t*) xfer->user_data) = xfer->result;
}
-uint8_t* usbh_get_enum_buf(void)
+// TODO timeout_ms is not supported yet
+bool tuh_control_xfer (tuh_xfer_t* xfer)
{
- return _usbh_ctrl_buf;
-}
+ // EP0 with setup packet
+ TU_VERIFY(xfer->ep_addr == 0 && xfer->setup);
-void usbh_int_set(bool enabled)
-{
- // TODO all host controller
- if (enabled)
+ // pre-check to help reducing mutex lock
+ TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
+
+ uint8_t const daddr = xfer->daddr;
+
+ // TODO probably better to use semaphore as resource management than mutex
+ usbh_lock();
+
+ bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
+ if (is_idle)
{
- hcd_int_enable(TUH_OPT_RHPORT);
+ _ctrl_xfer.stage = CONTROL_STAGE_SETUP;
+ _ctrl_xfer.daddr = daddr;
+ _ctrl_xfer.actual_len = 0;
+
+ _ctrl_xfer.request = (*xfer->setup);
+ _ctrl_xfer.buffer = xfer->buffer;
+ _ctrl_xfer.complete_cb = xfer->complete_cb;
+ _ctrl_xfer.user_data = xfer->user_data;
+ }
+
+ 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");
+
+ if (xfer->complete_cb)
+ {
+ TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) );
}else
{
- hcd_int_disable(TUH_OPT_RHPORT);
+ // blocking if complete callback is not provided
+ // change callback to internal blocking, and result as user argument
+ volatile xfer_result_t result = XFER_RESULT_INVALID;
+
+ // use user_data to point to xfer_result_t
+ _ctrl_xfer.user_data = (uintptr_t) &result;
+ _ctrl_xfer.complete_cb = _control_blocking_complete_cb;
+
+ TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.request) );
+
+ while (result == XFER_RESULT_INVALID)
+ {
+ // only need to call task if not preempted RTOS
+ #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
+ tuh_task();
+ #endif
+
+ // TODO probably some timeout to prevent hanged
+ }
+
+ // update transfer result
+ xfer->result = result;
+ xfer->actual_len = _ctrl_xfer.actual_len;
}
+
+ return true;
}
-//--------------------------------------------------------------------+
-// HCD Event Handler
-//--------------------------------------------------------------------+
+TU_ATTR_ALWAYS_INLINE static inline void _set_control_xfer_stage(uint8_t stage)
+{
+ usbh_lock();
+ _ctrl_xfer.stage = stage;
+ usbh_unlock();
+}
-void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info)
+static void _xfer_complete(uint8_t daddr, xfer_result_t result)
{
- if (dev_addr)
+ TU_LOG2("\r\n");
+
+ // duplicate xfer since user can execute control transfer within callback
+ tusb_control_request_t const request = _ctrl_xfer.request;
+ tuh_xfer_t xfer_temp =
{
- usbh_device_t const* dev = get_device(dev_addr);
+ .daddr = daddr,
+ .ep_addr = 0,
+ .result = result,
+ .setup = &request,
+ .actual_len = (uint32_t) _ctrl_xfer.actual_len,
+ .buffer = _ctrl_xfer.buffer,
+ .complete_cb = _ctrl_xfer.complete_cb,
+ .user_data = _ctrl_xfer.user_data
+ };
- devtree_info->rhport = dev->rhport;
- devtree_info->hub_addr = dev->hub_addr;
- devtree_info->hub_port = dev->hub_port;
- devtree_info->speed = dev->speed;
- }else
+ usbh_lock();
+ _ctrl_xfer.stage = CONTROL_STAGE_IDLE;
+ usbh_unlock();
+
+ if (xfer_temp.complete_cb)
{
- devtree_info->rhport = _dev0.rhport;
- devtree_info->hub_addr = _dev0.hub_addr;
- devtree_info->hub_port = _dev0.hub_port;
- devtree_info->speed = _dev0.speed;
+ xfer_temp.complete_cb(&xfer_temp);
}
}
-void hcd_event_handler(hcd_event_t const* event, bool in_isr)
+static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
{
- switch (event->event_id)
+ (void) ep_addr;
+
+ const uint8_t rhport = usbh_get_rhport(dev_addr);
+ tusb_control_request_t const * request = &_ctrl_xfer.request;
+
+ if (XFER_RESULT_SUCCESS != result)
{
- default:
- osal_queue_send(_usbh_q, event, in_isr);
- break;
- }
-}
+ TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED");
-void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
-{
- hcd_event_t event =
+ // terminate transfer if any stage failed
+ _xfer_complete(dev_addr, result);
+ }else
{
- .rhport = 0, // TODO correct rhport
- .event_id = HCD_EVENT_XFER_COMPLETE,
- .dev_addr = dev_addr,
- .xfer_complete =
+ switch(_ctrl_xfer.stage)
{
- .ep_addr = ep_addr,
- .result = result,
- .len = xferred_bytes
+ case CONTROL_STAGE_SETUP:
+ if (request->wLength)
+ {
+ // DATA stage: initial data toggle is always 1
+ _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 (xferred_bytes)
+ {
+ TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr);
+ 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);
+ hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, 1-request->bmRequestType_bit.direction), NULL, 0);
+ break;
+
+ case CONTROL_STAGE_ACK:
+ _xfer_complete(dev_addr, result);
+ break;
+
+ default: return false;
}
- };
+ }
- hcd_event_handler(&event, in_isr);
+ return true;
}
-void hcd_event_device_attach(uint8_t rhport, bool in_isr)
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+
+bool tuh_edpt_xfer(tuh_xfer_t* xfer)
{
- hcd_event_t event =
- {
- .rhport = rhport,
- .event_id = HCD_EVENT_DEVICE_ATTACH
- };
+ uint8_t const daddr = xfer->daddr;
+ uint8_t const ep_addr = xfer->ep_addr;
- event.connection.hub_addr = 0;
- event.connection.hub_port = 0;
+ TU_VERIFY(daddr && ep_addr);
- hcd_event_handler(&event, in_isr);
+ TU_VERIFY(usbh_edpt_claim(daddr, ep_addr));
+
+ if ( !usbh_edpt_xfer_with_callback(daddr, ep_addr, xfer->buffer, xfer->buflen, xfer->complete_cb, xfer->user_data) )
+ {
+ usbh_edpt_release(daddr, ep_addr);
+ return false;
+ }
+
+ return true;
}
-void hcd_event_device_remove(uint8_t hostid, bool in_isr)
+//--------------------------------------------------------------------+
+// USBH API For Class Driver
+//--------------------------------------------------------------------+
+
+uint8_t usbh_get_rhport(uint8_t dev_addr)
{
- hcd_event_t event =
- {
- .rhport = hostid,
- .event_id = HCD_EVENT_DEVICE_REMOVE
- };
+ usbh_device_t* dev = get_device(dev_addr);
+ return dev ? dev->rhport : _dev0.rhport;
+}
- event.connection.hub_addr = 0;
- event.connection.hub_port = 0;
+uint8_t* usbh_get_enum_buf(void)
+{
+ return _usbh_ctrl_buf;
+}
- hcd_event_handler(&event, in_isr);
+void usbh_int_set(bool enabled)
+{
+ // TODO all host controller
+ if (enabled)
+ {
+ hcd_int_enable(TUH_OPT_RHPORT);
+ }else
+ {
+ hcd_int_disable(TUH_OPT_RHPORT);
+ }
}
//--------------------------------------------------------------------+
@@ -768,55 +721,58 @@ void hcd_event_device_remove(uint8_t hostid, bool in_isr)
// TODO has some duplication code with device, refactor later
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
{
- // addr0 is always available
- if (dev_addr == 0) return true;
+ usbh_device_t* dev = get_device(dev_addr);
- usbh_device_t* dev = get_device(dev_addr);
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
- tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
+ // addr0 only use tuh_control_xfer
+ TU_ASSERT(dev);
-#if TUSB_OPT_MUTEX
- return tu_edpt_claim(ep_state, _usbh_mutex);
-#else
- return tu_edpt_claim(ep_state, NULL);
-#endif
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ return tu_edpt_claim(&dev->ep_status[epnum][dir], _usbh_mutex);
}
// TODO has some duplication code with device, refactor later
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
{
- // addr0 is always available
- if (dev_addr == 0) return true;
+ usbh_device_t* dev = get_device(dev_addr);
- usbh_device_t* dev = get_device(dev_addr);
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
- tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
+ // addr0 only use tuh_control_xfer
+ TU_ASSERT(dev);
-#if TUSB_OPT_MUTEX
- return tu_edpt_release(ep_state, _usbh_mutex);
-#else
- return tu_edpt_release(ep_state, NULL);
-#endif
+ uint8_t const epnum = tu_edpt_number(ep_addr);
+ uint8_t const dir = tu_edpt_dir(ep_addr);
+
+ return tu_edpt_release(&dev->ep_status[epnum][dir], _usbh_mutex);
}
// TODO has some duplication code with device, refactor later
-bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+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)
{
- uint8_t const epnum = tu_edpt_number(ep_addr);
- uint8_t const dir = tu_edpt_dir(ep_addr);
+ (void) complete_cb;
+ (void) user_data;
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);
+ tu_edpt_state_t* ep_state = &dev->ep_status[epnum][dir];
TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
// Attempt to transfer on a busy endpoint, sound like an race condition !
- TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
+ TU_ASSERT(ep_state->busy == 0);
// Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
// could return and USBH task can preempt and clear the busy
- dev->ep_status[epnum][dir].busy = true;
+ ep_state->busy = 1;
+
+#if CFG_TUH_API_EDPT_XFER
+ dev->ep_callback[epnum][dir].complete_cb = complete_cb;
+ dev->ep_callback[epnum][dir].user_data = user_data;
+#endif
if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
{
@@ -825,9 +781,9 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_
}else
{
// HCD error, mark endpoint as ready to allow next transfer
- dev->ep_status[epnum][dir].busy = false;
- dev->ep_status[epnum][dir].claimed = 0;
- TU_LOG2("failed\r\n");
+ ep_state->busy = 0;
+ ep_state->claimed = 0;
+ TU_LOG1("Failed\r\n");
TU_BREAKPOINT();
return false;
}
@@ -850,12 +806,11 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, &ep0_desc);
}
-bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
+bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
{
- usbh_device_t* dev = get_device(dev_addr);
- TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed));
+ TU_ASSERT( tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr)) );
- return hcd_edpt_open(rhport, dev_addr, 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)
@@ -864,167 +819,308 @@ bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
uint8_t const dir = tu_edpt_dir(ep_addr);
usbh_device_t* dev = get_device(dev_addr);
+ TU_VERIFY(dev);
return dev->ep_status[epnum][dir].busy;
}
//--------------------------------------------------------------------+
-// Control transfer
+// HCD Event Handler
//--------------------------------------------------------------------+
-static bool _control_blocking_complete_cb(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+void hcd_devtree_get_info(uint8_t dev_addr, hcd_devtree_info_t* devtree_info)
{
- (void) daddr;
+ usbh_device_t const* dev = get_device(dev_addr);
- // update result
- *((xfer_result_t*) xfer->user_arg) = result;
+ if (dev)
+ {
+ devtree_info->rhport = dev->rhport;
+ devtree_info->hub_addr = dev->hub_addr;
+ devtree_info->hub_port = dev->hub_port;
+ devtree_info->speed = dev->speed;
+ }else
+ {
+ devtree_info->rhport = _dev0.rhport;
+ devtree_info->hub_addr = _dev0.hub_addr;
+ devtree_info->hub_port = _dev0.hub_port;
+ devtree_info->speed = _dev0.speed;
+ }
+}
- return true;
+void hcd_event_handler(hcd_event_t const* event, bool in_isr)
+{
+ switch (event->event_id)
+ {
+ default:
+ osal_queue_send(_usbh_q, event, in_isr);
+ break;
+ }
}
-bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer)
+void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, uint32_t xferred_bytes, xfer_result_t result, bool in_isr)
{
- // pre-check to help reducing mutex lock
- TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
+ hcd_event_t event =
+ {
+ .rhport = 0, // TODO correct rhport
+ .event_id = HCD_EVENT_XFER_COMPLETE,
+ .dev_addr = dev_addr,
+ .xfer_complete =
+ {
+ .ep_addr = ep_addr,
+ .result = result,
+ .len = xferred_bytes
+ }
+ };
- // TODO probably better to use semaphore as resource management than mutex
- usbh_lock();
+ hcd_event_handler(&event, in_isr);
+}
- bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
- if (is_idle) _ctrl_xfer.stage = CONTROL_STAGE_SETUP;
+void hcd_event_device_attach(uint8_t rhport, bool in_isr)
+{
+ hcd_event_t event =
+ {
+ .rhport = rhport,
+ .event_id = HCD_EVENT_DEVICE_ATTACH
+ };
- usbh_unlock();
+ event.connection.hub_addr = 0;
+ event.connection.hub_port = 0;
- TU_VERIFY(is_idle);
+ hcd_event_handler(&event, in_isr);
+}
- const uint8_t rhport = usbh_get_rhport(daddr);
+void hcd_event_device_remove(uint8_t hostid, bool in_isr)
+{
+ hcd_event_t event =
+ {
+ .rhport = hostid,
+ .event_id = HCD_EVENT_DEVICE_REMOVE
+ };
- TU_LOG2("[%u:%u] %s: ", rhport, daddr, xfer->request.bRequest <= TUSB_REQ_SYNCH_FRAME ? tu_str_std_request[xfer->request.bRequest] : "Unknown Request");
- TU_LOG2_VAR(&xfer->request);
- TU_LOG2("\r\n");
+ event.connection.hub_addr = 0;
+ event.connection.hub_port = 0;
- _ctrl_xfer.daddr = daddr;
- _ctrl_xfer.xfer = (*xfer);
+ hcd_event_handler(&event, in_isr);
+}
- if (xfer->complete_cb)
- {
- TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) );
- }else
+//--------------------------------------------------------------------+
+// Descriptors Async
+//--------------------------------------------------------------------+
+
+// generic helper to get a descriptor
+// if blocking, user_data could be pointed to xfer_result
+static bool _get_descriptor(uint8_t daddr, uint8_t type, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ tusb_control_request_t const request =
{
- // user_arg must point to xfer_result_t to hold result
- TU_VERIFY(xfer->user_arg);
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = tu_htole16( TU_U16(type, index) ),
+ .wIndex = tu_htole16(language_id),
+ .wLength = tu_htole16(len)
+ };
- // blocking if complete callback is not provided
- // change callback to internal blocking, and result as user argument
- volatile xfer_result_t* result = (volatile xfer_result_t*) xfer->user_arg;
+ tuh_xfer_t xfer =
+ {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = buffer,
+ .complete_cb = complete_cb,
+ .user_data = user_data
+ };
- _ctrl_xfer.xfer.complete_cb = _control_blocking_complete_cb;
- *result = XFER_RESULT_INVALID;
+ bool const ret = tuh_control_xfer(&xfer);
- TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_ctrl_xfer.xfer.request) );
+ // if blocking, user_data could be pointed to xfer_result
+ if ( !complete_cb && user_data )
+ {
+ *((xfer_result_t*) user_data) = xfer.result;
+ }
- while ((*result) == XFER_RESULT_INVALID)
- {
- // only need to call task if not preempted RTOS
- #if CFG_TUSB_OS == OPT_OS_NONE || CFG_TUSB_OS == OPT_OS_PICO
- tuh_task();
- #endif
+ return ret;
+}
- // TODO probably some timeout to prevent hanged
- }
- }
+bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ return _get_descriptor(daddr, type, index, 0x0000, buffer, len, complete_cb, user_data);
+}
- return true;
+bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ len = tu_min16(len, sizeof(tusb_desc_device_t));
+ return tuh_descriptor_get(daddr, TUSB_DESC_DEVICE, 0, buffer, len, complete_cb, user_data);
}
-uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms)
+bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- (void) timeout_ms;
+ return tuh_descriptor_get(daddr, TUSB_DESC_CONFIGURATION, index, buffer, len, complete_cb, user_data);
+}
- xfer_result_t result = XFER_RESULT_INVALID;
- tuh_control_xfer_t xfer_sync = (*xfer);
+//------------- String Descriptor -------------//
- xfer_sync.complete_cb = NULL;
- xfer_sync.user_arg = (uintptr_t) &result;
+bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ return _get_descriptor(daddr, TUSB_DESC_STRING, index, language_id, buffer, len, complete_cb, user_data);
+}
- // TODO use timeout to wait
- TU_VERIFY(tuh_control_xfer(daddr, &xfer_sync), XFER_RESULT_TIMEOUT);
+// Get manufacturer string descriptor
+bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ usbh_device_t const* dev = get_device(daddr);
+ TU_VERIFY(dev && dev->i_manufacturer);
+ return tuh_descriptor_get_string(daddr, dev->i_manufacturer, language_id, buffer, len, complete_cb, user_data);
+}
- return result;
+// Get product string descriptor
+bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
+{
+ usbh_device_t const* dev = get_device(daddr);
+ TU_VERIFY(dev && dev->i_product);
+ return tuh_descriptor_get_string(daddr, dev->i_product, language_id, buffer, len, complete_cb, user_data);
}
-TU_ATTR_ALWAYS_INLINE static inline void set_control_xfer_stage(uint8_t stage)
+// Get serial string descriptor
+bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- usbh_lock();
- _ctrl_xfer.stage = stage;
- usbh_unlock();
+ usbh_device_t const* dev = get_device(daddr);
+ TU_VERIFY(dev && dev->i_serial);
+ return tuh_descriptor_get_string(daddr, dev->i_serial, language_id, buffer, len, complete_cb, user_data);
}
-static void _xfer_complete(uint8_t dev_addr, xfer_result_t result)
+// Get HID report descriptor
+// if blocking, user_data could be pointed to xfer_result
+bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- TU_LOG2("\r\n");
+ TU_LOG2("HID Get Report Descriptor\r\n");
+ tusb_control_request_t const request =
+ {
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_INTERFACE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_IN
+ },
+ .bRequest = TUSB_REQ_GET_DESCRIPTOR,
+ .wValue = tu_htole16(TU_U16(desc_type, index)),
+ .wIndex = tu_htole16((uint16_t) itf_num),
+ .wLength = len
+ };
- // duplicate xfer since user can execute control transfer within callback
- tuh_control_xfer_t const xfer_temp = _ctrl_xfer.xfer;
+ tuh_xfer_t xfer =
+ {
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = buffer,
+ .complete_cb = complete_cb,
+ .user_data = user_data
+ };
- usbh_lock();
- _ctrl_xfer.stage = CONTROL_STAGE_IDLE;
- usbh_unlock();
+ bool const ret = tuh_control_xfer(&xfer);
- if (xfer_temp.complete_cb)
+ // if blocking, user_data could be pointed to xfer_result
+ if ( !complete_cb && user_data )
{
- xfer_temp.complete_cb(dev_addr, &xfer_temp, result);
+ *((xfer_result_t*) user_data) = xfer.result;
}
+
+ return ret;
}
-static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
+bool tuh_configuration_set(uint8_t daddr, uint8_t config_num,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data)
{
- (void) ep_addr;
- (void) xferred_bytes;
-
- const uint8_t rhport = usbh_get_rhport(dev_addr);
- tusb_control_request_t const * request = &_ctrl_xfer.xfer.request;
+ TU_LOG2("Set Configuration = %d\r\n", config_num);
- if (XFER_RESULT_SUCCESS != result)
+ tusb_control_request_t const request =
{
- TU_LOG2("[%u:%u] Control %s\r\n", rhport, dev_addr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED");
+ .bmRequestType_bit =
+ {
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
+ },
+ .bRequest = TUSB_REQ_SET_CONFIGURATION,
+ .wValue = tu_htole16(config_num),
+ .wIndex = 0,
+ .wLength = 0
+ };
- // terminate transfer if any stage failed
- _xfer_complete(dev_addr, result);
- }else
+ tuh_xfer_t xfer =
{
- switch(_ctrl_xfer.stage)
- {
- case CONTROL_STAGE_SETUP:
- if (request->wLength)
- {
- // DATA stage: initial data toggle is always 1
- set_control_xfer_stage(CONTROL_STAGE_DATA);
- return hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.xfer.buffer, request->wLength);
- }
- __attribute__((fallthrough));
+ .daddr = daddr,
+ .ep_addr = 0,
+ .setup = &request,
+ .buffer = NULL,
+ .complete_cb = complete_cb,
+ .user_data = user_data
+ };
- case CONTROL_STAGE_DATA:
- if (request->wLength)
- {
- TU_LOG2("[%u:%u] Control data:\r\n", rhport, dev_addr);
- TU_LOG2_MEM(_ctrl_xfer.xfer.buffer, request->wLength, 2);
- }
+ return tuh_control_xfer(&xfer);
+}
- // ACK stage: toggle is always 1
- 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;
+//--------------------------------------------------------------------+
+// Descriptor Sync
+//--------------------------------------------------------------------+
- case CONTROL_STAGE_ACK:
- _xfer_complete(dev_addr, result);
- break;
+#define _CONTROL_SYNC_API(_async_func, ...) \
+ xfer_result_t result = XFER_RESULT_INVALID;\
+ TU_VERIFY(_async_func(__VA_ARGS__, NULL, (uintptr_t) &result), XFER_RESULT_TIMEOUT); \
+ return (uint8_t) result
- default: return false;
- }
- }
+uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get, daddr, type, index, buffer, len);
+}
- return true;
+uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_device, daddr, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_configuration, daddr, index, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_hid_report, daddr, itf_num, desc_type, index, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_string, daddr, index, language_id, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_manufacturer_string, daddr, language_id, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_product_string, daddr, language_id, buffer, len);
+}
+
+uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len)
+{
+ _CONTROL_SYNC_API(tuh_descriptor_get_serial_string, daddr, language_id, buffer, len);
}
//--------------------------------------------------------------------+
@@ -1062,7 +1158,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);
}
}
}
@@ -1094,20 +1190,22 @@ enum {
};
static bool enum_request_set_addr(void);
-static bool parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
+static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
static void enum_full_complete(void);
// process device enumeration
-static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfer, xfer_result_t result)
+static void process_enumeration(tuh_xfer_t* xfer)
{
- if (XFER_RESULT_SUCCESS != result)
+ if (XFER_RESULT_SUCCESS != xfer->result)
{
// stop enumeration, maybe we could retry this
enum_full_complete();
- return false;
+ return;
}
- uintptr_t const state = xfer->user_arg;
+ uint8_t const daddr = xfer->daddr;
+ uintptr_t const state = xfer->user_data;
+
switch(state)
{
#if CFG_TUH_HUB
@@ -1122,7 +1220,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
{
// device unplugged while delaying, nothing else to do
enum_full_complete();
- return false;
+ return;
}
_dev0.speed = (port_status.status.high_speed) ? TUSB_SPEED_HIGH :
@@ -1138,7 +1236,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
case ENUM_HUB_GET_STATUS_2:
osal_task_delay(RESET_DELAY);
- TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2) );
+ TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), );
break;
case ENUM_HUB_CLEAR_RESET_2:
@@ -1149,7 +1247,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
// Acknowledge Port Reset Change if Reset Successful
if (port_status.change.reset)
{
- TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR) );
+ TU_ASSERT( hub_port_clear_reset_change(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_SET_ADDR), );
}
}
break;
@@ -1159,11 +1257,11 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
{
// TODO probably doesn't need to open/close each enumeration
uint8_t const addr0 = 0;
- TU_ASSERT( usbh_edpt_control_open(addr0, 8) );
+ TU_ASSERT( usbh_edpt_control_open(addr0, 8), );
// Get first 8 bytes of device descriptor for Control Endpoint size
TU_LOG2("Get 8 byte of Device Descriptor\r\n");
- TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR));
+ TU_ASSERT(tuh_descriptor_get_device(addr0, _usbh_ctrl_buf, 8, process_enumeration, ENUM_SET_ADDR), );
}
break;
@@ -1182,7 +1280,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
else
{
// after RESET_DELAY the hub_port_reset() already complete
- TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2) );
+ TU_ASSERT( hub_port_reset(_dev0.hub_addr, _dev0.hub_port, process_enumeration, ENUM_HUB_GET_STATUS_2), );
break;
}
#endif
@@ -1194,27 +1292,29 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
case ENUM_GET_DEVICE_DESC:
{
- uint8_t const new_addr = (uint8_t const) xfer->request.wValue;
+ uint8_t const new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue);
usbh_device_t* new_dev = get_device(new_addr);
+ TU_ASSERT(new_dev, );
new_dev->addressed = 1;
// TODO close device 0, may not be needed
hcd_device_close(_dev0.rhport, 0);
// open control pipe for new address
- TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size) );
+ TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_size), );
// Get full device descriptor
TU_LOG2("Get Device Descriptor\r\n");
- TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC));
+ TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_ctrl_buf, sizeof(tusb_desc_device_t), process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC), );
}
break;
case ENUM_GET_9BYTE_CONFIG_DESC:
{
tusb_desc_device_t const * desc_device = (tusb_desc_device_t const*) _usbh_ctrl_buf;
- usbh_device_t* dev = get_device(dev_addr);
+ usbh_device_t* dev = get_device(daddr);
+ TU_ASSERT(dev, );
dev->vid = desc_device->idVendor;
dev->pid = desc_device->idProduct;
@@ -1227,7 +1327,7 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
// Get 9-byte for total length
uint8_t const config_idx = CONFIG_NUM - 1;
TU_LOG2("Get Configuration[0] Descriptor (9 bytes)\r\n");
- TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC) );
+ TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, 9, process_enumeration, ENUM_GET_FULL_CONFIG_DESC), );
}
break;
@@ -1239,34 +1339,36 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
uint16_t const total_len = tu_le16toh( tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)) );
// TODO not enough buffer to hold configuration descriptor
- TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE);
+ TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE, );
// Get full configuration descriptor
uint8_t const config_idx = CONFIG_NUM - 1;
TU_LOG2("Get Configuration[0] Descriptor\r\n");
- TU_ASSERT( tuh_descriptor_get_configuration(dev_addr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG) );
+ TU_ASSERT( tuh_descriptor_get_configuration(daddr, config_idx, _usbh_ctrl_buf, total_len, process_enumeration, ENUM_SET_CONFIG), );
}
break;
case ENUM_SET_CONFIG:
// Parse configuration & set up drivers
// Driver open aren't allowed to make any usb transfer yet
- TU_ASSERT( parse_configuration_descriptor(dev_addr, (tusb_desc_configuration_t*) _usbh_ctrl_buf) );
+ TU_ASSERT( _parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), );
- TU_ASSERT( tuh_configuration_set(dev_addr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER) );
+ TU_ASSERT( tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), );
break;
case ENUM_CONFIG_DRIVER:
{
TU_LOG2("Device configured\r\n");
- usbh_device_t* dev = get_device(dev_addr);
+ usbh_device_t* dev = get_device(daddr);
+ TU_ASSERT(dev, );
+
dev->configured = 1;
// Start the Set Configuration process for interfaces (itf = DRVID_INVALID)
// Since driver can perform control transfer within its set_config, this is done asynchronously.
// The process continue with next interface when class driver complete its sequence with usbh_driver_set_config_complete()
// TODO use separated API instead of using DRVID_INVALID
- usbh_driver_set_config_complete(dev_addr, DRVID_INVALID);
+ usbh_driver_set_config_complete(daddr, DRVID_INVALID);
}
break;
@@ -1275,8 +1377,6 @@ static bool process_enumeration(uint8_t dev_addr, tuh_control_xfer_t const * xfe
enum_full_complete();
break;
}
-
- return true;
}
static bool enum_new_device(hcd_event_t* event)
@@ -1297,13 +1397,13 @@ static bool enum_new_device(hcd_event_t* event)
_dev0.speed = hcd_port_speed_get(_dev0.rhport );
TU_LOG2("%s Speed\r\n", tu_str_speed[_dev0.speed]);
- //enum_request_addr0_device_desc();
- tuh_control_xfer_t const xfer =
- {
- .complete_cb = process_enumeration,
- .user_arg = ENUM_ADDR0_DEVICE_DESC
- };
- process_enumeration(0, &xfer, XFER_RESULT_SUCCESS);
+ // fake transfer to kick-off the enumeration process
+ tuh_xfer_t xfer;
+ xfer.daddr = 0;
+ xfer.result = XFER_RESULT_SUCCESS;
+ xfer.user_data = ENUM_ADDR0_DEVICE_DESC;
+
+ process_enumeration(&xfer);
}
#if CFG_TUH_HUB
@@ -1322,15 +1422,29 @@ static bool enum_new_device(hcd_event_t* event)
return true;
}
+TU_ATTR_ALWAYS_INLINE
+static inline bool is_hub_addr(uint8_t daddr)
+{
+ return daddr > CFG_TUH_DEVICE_MAX;
+}
+
static uint8_t get_new_address(bool is_hub)
{
- uint8_t const start = (is_hub ? CFG_TUH_DEVICE_MAX : 0) + 1;
- uint8_t const count = (is_hub ? CFG_TUH_HUB : CFG_TUH_DEVICE_MAX);
+ uint8_t start;
+ uint8_t end;
+ if ( is_hub )
+ {
+ start = CFG_TUH_DEVICE_MAX;
+ end = start + CFG_TUH_HUB;
+ }else
+ {
+ start = 0;
+ end = start + CFG_TUH_DEVICE_MAX;
+ }
- for (uint8_t i=0; i < count; i++)
+ for ( uint8_t idx = start; idx < end; idx++)
{
- uint8_t const addr = start + i;
- if (!get_device(addr)->connected) return addr;
+ if (!_usbh_devices[idx].connected) return (idx+1);
}
return ADDR_INVALID;
}
@@ -1354,34 +1468,36 @@ static bool enum_request_set_addr(void)
new_dev->connected = 1;
new_dev->ep0_size = desc_device->bMaxPacketSize0;
- tuh_control_xfer_t const xfer =
+ tusb_control_request_t const request =
{
- .request =
+ .bmRequestType_bit =
{
- .bmRequestType_bit =
- {
- .recipient = TUSB_REQ_RCPT_DEVICE,
- .type = TUSB_REQ_TYPE_STANDARD,
- .direction = TUSB_DIR_OUT
- },
- .bRequest = TUSB_REQ_SET_ADDRESS,
- .wValue = tu_htole16(new_addr),
- .wIndex = 0,
- .wLength = 0
+ .recipient = TUSB_REQ_RCPT_DEVICE,
+ .type = TUSB_REQ_TYPE_STANDARD,
+ .direction = TUSB_DIR_OUT
},
+ .bRequest = TUSB_REQ_SET_ADDRESS,
+ .wValue = tu_htole16(new_addr),
+ .wIndex = 0,
+ .wLength = 0
+ };
+ tuh_xfer_t xfer =
+ {
+ .daddr = 0, // dev0
+ .ep_addr = 0,
+ .setup = &request,
.buffer = NULL,
.complete_cb = process_enumeration,
- .user_arg = ENUM_GET_DEVICE_DESC
+ .user_data = ENUM_GET_DEVICE_DESC
};
- uint8_t const addr0 = 0;
- TU_ASSERT( tuh_control_xfer(addr0, &xfer) );
+ TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
-static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
+static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
{
usbh_device_t* dev = get_device(dev_addr);
@@ -1497,8 +1613,14 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num)
{
enum_full_complete();
- // Invoke callback if available
- if (tuh_mount_cb) tuh_mount_cb(dev_addr);
+#if CFG_TUH_HUB
+ // skip device mount callback for hub
+ if ( !is_hub_addr(dev_addr) )
+#endif
+ {
+ // Invoke callback if available
+ if (tuh_mount_cb) tuh_mount_cb(dev_addr);
+ }
}
}
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 3bd40c50d..e883ac90b 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -39,17 +39,34 @@
//--------------------------------------------------------------------+
// forward declaration
-struct tuh_control_xfer_s;
-typedef struct tuh_control_xfer_s tuh_control_xfer_t;
+struct tuh_xfer_s;
+typedef struct tuh_xfer_s tuh_xfer_t;
-typedef bool (*tuh_control_xfer_cb_t)(uint8_t daddr, tuh_control_xfer_t const * xfer, xfer_result_t result);
+typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer);
-struct tuh_control_xfer_s
+// Note1: layout and order of this will be changed in near future
+// it is advised to initialize it using member name
+// Note2: not all field is available/meaningful in callback, some info is not saved by
+// usbh to save SRAM
+struct tuh_xfer_s
{
- tusb_control_request_t request TU_ATTR_ALIGNED(4);
- uint8_t* buffer;
- tuh_control_xfer_cb_t complete_cb;
- uintptr_t user_arg;
+ uint8_t daddr;
+ uint8_t ep_addr;
+
+ xfer_result_t result;
+ uint32_t actual_len; // excluding setup packet
+
+ union
+ {
+ tusb_control_request_t const* setup; // setup packet pointer if control transfer
+ uint32_t buflen; // expected length if not control transfer (not available in callback)
+ };
+
+ uint8_t* buffer; // not available in callback if not control transfer
+ tuh_xfer_cb_t complete_cb;
+ uintptr_t user_data;
+
+ // uint32_t timeout_ms; // place holder, not supported yet
};
//--------------------------------------------------------------------+
@@ -104,21 +121,28 @@ static inline bool tuh_ready(uint8_t daddr)
return tuh_mounted(daddr) && !tuh_suspended(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
-bool tuh_control_xfer (uint8_t daddr, tuh_control_xfer_t const* xfer);
+//--------------------------------------------------------------------+
+// Transfer API
+//--------------------------------------------------------------------+
-// Sync (blocking) version of tuh_control_xfer()
-// return transfer result
-uint8_t tuh_control_xfer_sync(uint8_t daddr, tuh_control_xfer_t const* xfer, uint32_t timeout_ms);
+// Submit a control transfer
+// - async: complete callback invoked when finished.
+// - sync : blocking if complete callback is NULL.
+bool tuh_control_xfer(tuh_xfer_t* xfer);
+
+// Submit a bulk/interrupt transfer
+// - async: complete callback invoked when finished.
+// - 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);
// 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);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
//--------------------------------------------------------------------+
// Descriptors Asynchronous (non-blocking)
@@ -127,43 +151,43 @@ bool tuh_configuration_set(uint8_t daddr, uint8_t config_num,
// Get an descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get device descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_device(uint8_t daddr, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get configuration descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_configuration(uint8_t daddr, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get HID report descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get string descriptor (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
+// Blocking if complete callback is NULL, in this case 'user_data' must contain xfer_result_t variable
bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get manufacturer string descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get product string descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_product_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get serial string descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
- tuh_control_xfer_cb_t complete_cb, uintptr_t user_arg);
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
//--------------------------------------------------------------------+
// Descriptors Synchronous (blocking)
@@ -171,35 +195,35 @@ bool tuh_descriptor_get_serial_string(uint8_t daddr, uint16_t language_id, void*
// Sync (blocking) version of tuh_descriptor_get()
// return transfer result
-uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_sync(uint8_t daddr, uint8_t type, uint8_t index, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_device()
// return transfer result
-uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_device_sync(uint8_t daddr, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_configuration()
// return transfer result
-uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_configuration_sync(uint8_t daddr, uint8_t index, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_hid_report()
// return transfer result
-uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8_t desc_type, uint8_t index, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_string()
// return transfer result
-uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_manufacturer_string()
// return transfer result
-uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_product_string()
// return transfer result
-uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_product_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len);
// Sync (blocking) version of tuh_descriptor_get_serial_string()
// return transfer result
-uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, uint8_t timeout_ms);
+uint8_t tuh_descriptor_get_serial_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len);
#ifdef __cplusplus
}
diff --git a/src/host/usbh_classdriver.h b/src/host/usbh_classdriver.h
index 0435eae70..c156afea0 100644
--- a/src/host/usbh_classdriver.h
+++ b/src/host/usbh_classdriver.h
@@ -63,11 +63,16 @@ void usbh_int_set(bool enabled);
// USBH Endpoint API
//--------------------------------------------------------------------+
-// Open an endpoint
-bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep);
+// Submit a usb transfer with callback support, require CFG_TUH_API_EDPT_XFER
+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);
+
+TU_ATTR_ALWAYS_INLINE
+static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+ return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0);
+}
-// Submit a usb transfer
-bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
// Claim an endpoint before submitting a transfer.
// If caller does not make any transfer, it must release endpoint for others.
diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c
index 8d420f26a..665f2380b 100644
--- a/src/portable/ehci/ehci.c
+++ b/src/portable/ehci/ehci.c
@@ -656,6 +656,26 @@ static void xfer_error_isr(uint8_t hostid)
}
}
+#if CFG_TUSB_DEBUG >= EHCI_DBG
+
+static inline void print_portsc(ehci_registers_t* regs)
+{
+ TU_LOG_HEX(EHCI_DBG, regs->portsc);
+ TU_LOG(EHCI_DBG, " Current Connect Status: %u\r\n", regs->portsc_bm.current_connect_status);
+ TU_LOG(EHCI_DBG, " Connect Status Change : %u\r\n", regs->portsc_bm.connect_status_change);
+ TU_LOG(EHCI_DBG, " Port Enabled : %u\r\n", regs->portsc_bm.port_enabled);
+ TU_LOG(EHCI_DBG, " Port Enabled Change : %u\r\n", regs->portsc_bm.port_enable_change);
+
+ TU_LOG(EHCI_DBG, " Port Reset : %u\r\n", regs->portsc_bm.port_reset);
+ TU_LOG(EHCI_DBG, " Port Power : %u\r\n", regs->portsc_bm.port_power);
+}
+
+#else
+
+#define print_portsc(_reg)
+
+#endif
+
//------------- Host Controller Driver's Interrupt Handler -------------//
void hcd_int_handler(uint8_t rhport)
{
@@ -675,9 +695,8 @@ void hcd_int_handler(uint8_t rhport)
if (int_status & EHCI_INT_MASK_PORT_CHANGE)
{
- uint32_t port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
-
- TU_LOG_HEX(EHCI_DBG, regs->portsc);
+ uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_ALL;
+ print_portsc(regs);
if (regs->portsc_bm.connect_status_change)
{
diff --git a/src/tusb.h b/src/tusb.h
index 222855fcb..b776d7d01 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -38,6 +38,8 @@
#include "osal/osal.h"
#include "common/tusb_fifo.h"
+#include "class/hid/hid.h"
+
//------------- HOST -------------//
#if CFG_TUH_ENABLED
#include "host/usbh.h"
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 0352faaed..bd87a953c 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -392,6 +392,10 @@
#define CFG_TUH_VENDOR 0
#endif
+#ifndef CFG_TUH_API_EDPT_XFER
+#define CFG_TUH_API_EDPT_XFER 0
+#endif
+
//------------------------------------------------------------------
// Configuration Validation
//------------------------------------------------------------------