summaryrefslogtreecommitdiff
path: root/tinyusb/host
diff options
context:
space:
mode:
Diffstat (limited to 'tinyusb/host')
-rw-r--r--tinyusb/host/ehci/ehci.c36
-rw-r--r--tinyusb/host/ehci/ehci.h19
-rw-r--r--tinyusb/host/usbh.c52
-rw-r--r--tinyusb/host/usbh.h34
-rw-r--r--tinyusb/host/usbh_hcd.h4
5 files changed, 104 insertions, 41 deletions
diff --git a/tinyusb/host/ehci/ehci.c b/tinyusb/host/ehci/ehci.c
index d3cf5b6a8..bb12c117e 100644
--- a/tinyusb/host/ehci/ehci.c
+++ b/tinyusb/host/ehci/ehci.c
@@ -273,10 +273,10 @@ tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
queue_head_init(p_qhd, dev_addr, max_packet_size, 0, TUSB_XFER_CONTROL);
- //------------- insert to async list -------------//
- // TODO might need to to disable async list first
if (dev_addr != 0)
{
+ //------------- insert to async list -------------//
+ // TODO might need to to disable async list first
list_insert( (ehci_link_t*) get_async_head(usbh_device_info_pool[dev_addr].core_id),
(ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
}
@@ -351,6 +351,7 @@ tusb_error_t hcd_pipe_control_xfer(uint8_t dev_addr, tusb_std_request_t const *
tusb_error_t hcd_pipe_control_close(uint8_t dev_addr)
{
+ //------------- TODO pipe handle validate -------------//
ehci_qhd_t * const p_qhd = get_control_qhd(dev_addr);
p_qhd->qtd_overlay.halted = 1;
@@ -400,9 +401,24 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
return (pipe_handle_t) { .dev_addr = dev_addr, .xfer_type = p_endpoint_desc->bmAttributes.xfer, .index = index};
}
+static inline void insert_qtd_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new) ATTR_ALWAYS_INLINE;
+static inline void insert_qtd_to_qhd(ehci_qhd_t *p_qhd, ehci_qtd_t *p_qtd_new)
+{
+ if (p_qhd->p_qtd_list_head == NULL) // empty list
+ {
+ p_qhd->p_qtd_list_head = p_qhd->p_qtd_list_tail = p_qtd_new;
+ p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head;
+ }else
+ {
+ p_qhd->p_qtd_list_tail->next.address = (uint32_t) p_qtd_new;
+ p_qhd->p_qtd_list_tail = p_qtd_new;
+ }
+}
+
+
tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
{
- //------------- pipe handle validate -------------//
+ //------------- TODO pipe handle validate -------------//
//------------- find a free qtd -------------//
uint8_t index=0;
@@ -413,16 +429,15 @@ tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t t
ASSERT( index < EHCI_MAX_QTD, TUSB_ERROR_EHCI_NOT_ENOUGH_QTD);
//------------- set up QTD -------------//
- ehci_qhd_t *p_qhd = &ehci_data.device[pipe_hdl.dev_addr].qhd[index];
-
+ ehci_qhd_t *p_qhd = &ehci_data.device[pipe_hdl.dev_addr].qhd[pipe_hdl.index];
ehci_qtd_t *p_qtd = &ehci_data.device[pipe_hdl.dev_addr].qtd[index];
+
queue_td_init(p_qtd, (uint32_t) buffer, total_bytes);
p_qtd->pid = p_qhd->pid_non_control;
p_qtd->int_on_complete = 1;
-
- p_qhd->p_qtd_list_head = p_qtd;
- p_qhd->qtd_overlay.next.address = (uint32_t) p_qtd;
+ //------------- insert TD to TD list -------------//
+ insert_qtd_to_qhd(p_qhd, p_qtd);
return TUSB_ERROR_NONE;
}
@@ -445,7 +460,7 @@ static inline ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
static inline tusb_std_request_t* const get_control_request_ptr(uint8_t dev_addr)
{
- return &ehci_data.control_request[dev_addr];
+ return &usbh_device_info_pool[dev_addr].control_request;
}
// TODO subject to pure function
@@ -483,7 +498,8 @@ static void queue_head_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, uint16_t max_pa
//------------- HCD Management Data -------------//
p_qhd->used = 1;
- p_qhd->p_qtd_list_head = NULL;
+ p_qhd->p_qtd_list_head = NULL;
+ p_qhd->p_qtd_list_tail = NULL;
p_qhd->pid_non_control = (endpoint_addr & 0x80) ? EHCI_PID_IN : EHCI_PID_OUT; // PID for TD under this endpoint
}
diff --git a/tinyusb/host/ehci/ehci.h b/tinyusb/host/ehci/ehci.h
index cfd37c494..290d5f088 100644
--- a/tinyusb/host/ehci/ehci.h
+++ b/tinyusb/host/ehci/ehci.h
@@ -201,10 +201,10 @@ typedef struct {
uint8_t list_index;
uint8_t reserved;
- ehci_qtd_t *p_qtd_list_head; // head of the TD list scheduled
+ ehci_qtd_t *p_qtd_list_head; // head of the scheduled TD list
+ ehci_qtd_t *p_qtd_list_tail; // tail of the scheduled TD list
+ uint32_t reserved_2;
- volatile uint32_t status; // TODO will remove volatile after remove all HcdQHD function
- uint16_t *pActualTransferCount; /* total transferred bytes of a usb request */
}ATTR_ALIGNED(32) ehci_qhd_t;
/// Highspeed Isochronous Transfer Descriptor (section 3.3)
@@ -440,8 +440,7 @@ typedef struct {
ehci_qhd_t async_head[CONTROLLER_HOST_NUMBER]; /// head qhd of async list, also is used as control endpoint for address 0
ehci_qhd_t period_head[CONTROLLER_HOST_NUMBER];
- //------------- Data for Address 0 -------------//
- // qhd: addr0 use async head (dummy) as Queue Head
+ //------------- Data for Address 0 (use async head as its queue head) -------------//
ehci_qtd_t addr0_qtd[3];
struct {
@@ -450,13 +449,11 @@ typedef struct {
ehci_qtd_t qtd[3];
}control;
- ehci_qhd_t qhd[EHCI_MAX_QHD] ; ///< Queue Head Pool
- ehci_qtd_t qtd[EHCI_MAX_QTD] ; ///< Queue Element Transfer Pool
-// ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool
-// ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool
+ ehci_qhd_t qhd[EHCI_MAX_QHD] ; ///< Queue Head Pool
+ ehci_qtd_t qtd[EHCI_MAX_QTD] ATTR_ALIGNED(32) ; ///< Queue Element Transfer Pool
+// ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool
+// ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool
}device[TUSB_CFG_HOST_DEVICE_MAX];
-
- tusb_std_request_t control_request[TUSB_CFG_HOST_DEVICE_MAX+1]; // including address zero, 32-byte alignment breaker
}ehci_data_t;
#ifdef __cplusplus
diff --git a/tinyusb/host/usbh.c b/tinyusb/host/usbh.c
index 3c2010c06..1bef861b3 100644
--- a/tinyusb/host/usbh.c
+++ b/tinyusb/host/usbh.c
@@ -52,11 +52,24 @@
//--------------------------------------------------------------------+
#define ENUM_QUEUE_DEPTH 5
+// TODO fix number of class driver
+class_driver_t const class_host_drivers[TUSB_CLASS_MAX_CONSEC_NUMBER] =
+{
+ [TUSB_CLASS_HID] = {
+ .init = hidh_init,
+ .install_subtask = hidh_install_subtask
+ },
+
+ [TUSB_CLASS_MSC] = {
+ .init = msch_init,
+ .install_subtask = msch_install_subtask
+ }
+};
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
-usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1]; // including zero-address
+usbh_device_info_t usbh_device_info_pool[TUSB_CFG_HOST_DEVICE_MAX+1] TUSB_CFG_ATTR_USBRAM; // including zero-address
//------------- Enumeration Task Data -------------//
OSAL_TASK_DEF(enum_task, usbh_enumeration_task, 128, OSAL_PRIO_HIGH);
@@ -94,9 +107,11 @@ tusb_error_t usbh_init(void)
ASSERT_PTR(enum_queue_hdl, TUSB_ERROR_OSAL_QUEUE_FAILED);
//------------- class init -------------//
-#if HOST_CLASS_HID
- hidh_init();
-#endif
+ for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
+ {
+ if (class_host_drivers[class_code].init)
+ class_host_drivers[class_code].init();
+ }
return TUSB_ERROR_NONE;
}
@@ -108,7 +123,9 @@ tusb_error_t usbh_control_xfer_subtask(uint8_t dev_addr, tusb_std_request_t cons
OSAL_SUBTASK_BEGIN
+ usbh_device_info_pool[dev_addr].control_request = *p_request;
(void) hcd_pipe_control_xfer(dev_addr, p_request, data);
+
osal_semaphore_wait(usbh_device_info_pool[dev_addr].sem_hdl, OSAL_TIMEOUT_NORMAL, &error); // careful of local variable without static
SUBTASK_ASSERT_STATUS_WITH_HANDLER(error, tusbh_device_mount_failed_cb(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL) );
@@ -242,7 +259,7 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
// update configuration info
usbh_device_info_pool[new_addr].interface_count = ((tusb_descriptor_configuration_t*) enum_data_buffer)->bNumInterfaces;
- //------------- parse configuration -------------//
+ //------------- parse configuration & install drivers -------------//
p_desc = enum_data_buffer + sizeof(tusb_descriptor_configuration_t);
// parse each interfaces
@@ -250,21 +267,20 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
{
TASK_ASSERT( TUSB_DESC_INTERFACE == ((tusb_descriptor_interface_t*) p_desc)->bDescriptorType ); // TODO should we skip this descriptor and advance
- // NOTE: cannot use switch (conflicted with OSAL_NONE task)
- if (TUSB_CLASS_UNSPECIFIED == ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass)
+ uint8_t class_code = ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass;
+ if (class_code == 0)
{
- TASK_ASSERT( false ); // corrupted data
- }
-#if HOST_CLASS_HID
- else if ( TUSB_CLASS_HID == ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass)
+ TASK_ASSERT( false ); // corrupted data, abort enumeration
+ } else if ( class_code < TUSB_CLASS_MAX_CONSEC_NUMBER)
{
- uint16_t length;
- OSAL_SUBTASK_INVOKED_AND_WAIT ( hidh_install_subtask(new_addr, p_desc, &length) );
- p_desc += length;
- }
-#endif
- // unsupported class
- else
+ if ( class_host_drivers[class_code].install_subtask )
+ {
+ uint16_t length;
+ OSAL_SUBTASK_INVOKED_AND_WAIT ( // parameters in task/sub_task must be static storage (static or global)
+ class_host_drivers[ ((tusb_descriptor_interface_t*) p_desc)->bInterfaceClass ].install_subtask(new_addr, p_desc, &length) );
+ p_desc += length;
+ }
+ } else // unsupported class (not enable or yet implemented)
{
do
{
diff --git a/tinyusb/host/usbh.h b/tinyusb/host/usbh.h
index 1f7e492c2..feb13b7e0 100644
--- a/tinyusb/host/usbh.h
+++ b/tinyusb/host/usbh.h
@@ -63,6 +63,36 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+#define CLASS_TABLE(ENTRY_EXPANDER) \
+ ENTRY_EXPANDER(TUSB_CLASS_AUDIO)\
+ ENTRY_EXPANDER(TUSB_CLASS_CDC)\
+ ENTRY_EXPANDER(TUSB_CLASS_HID)\
+ ENTRY_EXPANDER(TUSB_CLASS_PHYSICAL)\
+ ENTRY_EXPANDER(TUSB_CLASS_IMAGE)\
+ ENTRY_EXPANDER(TUSB_CLASS_PRINTER)\
+ ENTRY_EXPANDER(TUSB_CLASS_MSC)\
+ ENTRY_EXPANDER(TUSB_CLASS_HUB)\
+ ENTRY_EXPANDER(TUSB_CLASS_CDC_DATA)\
+ ENTRY_EXPANDER(TUSB_CLASS_SMART_CARD)\
+ ENTRY_EXPANDER(TUSB_CLASS_CONTENT_SECURITY)\
+ ENTRY_EXPANDER(TUSB_CLASS_VIDEO)\
+ ENTRY_EXPANDER(TUSB_CLASS_PERSONAL_HEALTHCARE)\
+ ENTRY_EXPANDER(TUSB_CLASS_AUDIO_VIDEO)\
+
+#define CLASS_LOOKUP_EXPAND(class_code)
+
+#define CLASS_LOOKUP_INIT_FUNCTION(class_code)\
+
+#define CLASS_EXPANDER_INIT(class_code)\
+
+
+
+// TUSB_CLASS_DIAGNOSTIC = 0xDC ,
+// TUSB_CLASS_WIRELESS_CONTROLLER = 0xE0 ,
+// TUSB_CLASS_MISC = 0xEF ,
+// TUSB_CLASS_APPLICATION_SPECIFIC = 0xEF ,
+// TUSB_CLASS_VENDOR_SPECIFIC = 0xFF
+
enum {
TUSB_FLAGS_CLASS_UNSPECIFIED = BIT_(0) , ///< 0
TUSB_FLAGS_CLASS_AUDIO = BIT_(1) , ///< 1
@@ -119,6 +149,10 @@ typedef uint32_t tusbh_flag_class_t;
typedef uint32_t tusb_handle_device_t;
typedef uint8_t tusbh_device_status_t;
+typedef struct {
+ void (* const init) (void);
+ tusb_error_t (* const install_subtask)(uint8_t, uint8_t const *, uint16_t*);
+} class_driver_t;
//--------------------------------------------------------------------+
// INTERNAL OBJECT & FUNCTION DECLARATION
//--------------------------------------------------------------------+
diff --git a/tinyusb/host/usbh_hcd.h b/tinyusb/host/usbh_hcd.h
index f36586dbf..e8a1d4c62 100644
--- a/tinyusb/host/usbh_hcd.h
+++ b/tinyusb/host/usbh_hcd.h
@@ -80,7 +80,7 @@ typedef struct { // TODO internal structure, re-order members
//------------- device descriptor info -------------//
uint16_t vendor_id;
uint16_t product_id;
- uint8_t configure_count; // bNumConfigurations alias
+ uint8_t configure_count; // bNumConfigurations alias
//------------- configuration descriptor info -------------//
uint8_t interface_count; // bNumInterfaces alias
@@ -88,7 +88,7 @@ typedef struct { // TODO internal structure, re-order members
uint8_t status; // value from enum tusbh_device_status_
// pipe_handle_t pipe_control; NOTE: use device address/handle instead
- tusb_std_request_t request_control;
+ tusb_std_request_t control_request;
OSAL_SEM_DEF(semaphore);
osal_semaphore_handle_t sem_hdl;