Prechádzať zdrojové kódy

feat: host add event callback mechanism similar to device

* fix: fix warning for speed_table
* fix(port/dwc2/usb_hc_dwc2): add roothub.speed init
* feat(usbh_core): add event_callback
* fix(usbh_hub): fix event device reset port
* fix(usbh_hub): remove event init when init failed
* feat(usbh_core): add default dummy_event_callback
* fix(usbh_hub): emit reset event only on successful reset
* fix(usbh_core): emit interface start only on successful connect class driver
* feat(usbh_core): change event_callback to typedef
* feat(port): update port usbh init params
* doc: update usbh_initialize desc
* fix(usbh_core): check result from ret == 0 change to ret >= 0
---------

Signed-off-by: egahp <2687434412@qq.com>
Egahp 4 mesiacov pred
rodič
commit
5d5b61a606

+ 21 - 3
class/hub/usbh_hub.c

@@ -238,6 +238,7 @@ int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
 {
     struct usb_setup_packet roothub_setup;
     struct usb_setup_packet *setup;
+    int ret;
 
     if (hub->is_roothub) {
         setup = &roothub_setup;
@@ -246,9 +247,22 @@ int usbh_hub_set_feature(struct usbh_hub *hub, uint8_t port, uint8_t feature)
         setup->wValue = feature;
         setup->wIndex = port;
         setup->wLength = 0;
-        return usbh_roothub_control(hub->bus, setup, NULL);
+
+        ret = usbh_roothub_control(hub->bus, setup, NULL);
+
+        if ((feature == HUB_PORT_FEATURE_RESET) && (ret >= 0)) {
+            hub->bus->event_handler(hub->bus->busid, hub->index, port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_RESET);
+        }
+
+        return ret;
     } else {
-        return _usbh_hub_set_feature(hub, port, feature);
+        ret = _usbh_hub_set_feature(hub, port, feature);
+
+        if ((feature == HUB_PORT_FEATURE_RESET) && (ret >= 0)) {
+            hub->bus->event_handler(hub->bus->busid, hub->index, port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_RESET);
+        }
+
+        return ret;
     }
 }
 
@@ -470,6 +484,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
     int ret;
     size_t flags;
 
+    (void)speed_table;
+
     if (!hub->connected) {
         return;
     }
@@ -560,6 +576,8 @@ static void usbh_hub_events(struct usbh_hub *hub)
 
             /* Last, check connect status */
             if (portstatus & HUB_PORT_STATUS_CONNECTION) {
+                hub->bus->event_handler(hub->bus->busid, hub->index, port + 1, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_CONNECTED);
+
                 ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_RESET);
                 if (ret < 0) {
                     USB_LOG_ERR("Failed to reset port %u, errorcode: %d\r\n", port + 1, ret);
@@ -641,7 +659,6 @@ static void usbh_hub_events(struct usbh_hub *hub)
                 child = &hub->child[port];
                 /** release child sources */
                 usbh_hubport_release(child);
-                USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hub->bus->busid, hub->index, port + 1);
             }
         }
     }
@@ -660,6 +677,7 @@ static void usbh_hub_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
     struct usbh_bus *bus = (struct usbh_bus *)CONFIG_USB_OSAL_THREAD_GET_ARGV;
 
     usb_hc_init(bus);
+    bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_INIT);
     while (1) {
         ret = usb_osal_mq_recv(bus->hub_mq, (uintptr_t *)&hub, USB_OSAL_WAITING_FOREVER);
         if (ret < 0) {

+ 26 - 2
core/usbh_core.c

@@ -31,6 +31,15 @@ struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
 #define USB_DEV_ADDR_MARK_OFFSET 5
 #define USB_DEV_ADDR_MARK_MASK   0x1f
 
+static void dummy_event_handler(uint8_t busid, uint8_t hub_index, uint8_t hub_port, uint8_t intf, uint8_t event)
+{
+    (void)busid;
+    (void)hub_index;
+    (void)hub_port;
+    (void)intf;
+    (void)event;
+}
+
 static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
 {
     uint8_t lastaddr = devgen->last;
@@ -593,6 +602,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
     }
 #endif
     USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
+    hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_CONFIGURED);
     /*search supported class driver*/
     for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
         intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
@@ -604,12 +614,15 @@ int usbh_enumerate(struct usbh_hubport *hport)
                         intf_desc->bInterfaceClass,
                         intf_desc->bInterfaceSubClass,
                         intf_desc->bInterfaceProtocol);
-
+            hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, i, USBH_EVENT_INTERFACE_UNSUPPORTED);
             continue;
         }
         hport->config.intf[i].class_driver = class_driver;
         USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
         ret = CLASS_CONNECT(hport, i);
+        if (ret >= 0) {
+            hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, i, USBH_EVENT_INTERFACE_START);
+        }
     }
 
 errout:
@@ -629,12 +642,15 @@ void usbh_hubport_release(struct usbh_hubport *hport)
             if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) {
                 CLASS_DISCONNECT(hport, i);
             }
+            hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, i, USBH_EVENT_INTERFACE_STOP);
         }
         hport->config.config_desc.bNumInterfaces = 0;
         usbh_kill_urb(&hport->ep0_urb);
         if (hport->mutex) {
             usb_osal_mutex_delete(hport->mutex);
         }
+        USB_LOG_INFO("Device on Bus %u, Hub %u, Port %u disconnected\r\n", hport->bus->busid, hport->parent->index, hport->port);
+        hport->bus->event_handler(hport->bus->busid, hport->parent->index, hport->port, USB_INTERFACE_ANY, USBH_EVENT_DEVICE_DISCONNECTED);
     }
 }
 
@@ -651,7 +667,7 @@ static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_bas
     usb_slist_add_tail(&g_bus_head, &bus->list);
 }
 
-int usbh_initialize(uint8_t busid, uintptr_t reg_base)
+int usbh_initialize(uint8_t busid, uintptr_t reg_base, usbh_event_handler_t event_handler)
 {
     struct usbh_bus *bus;
 
@@ -665,6 +681,12 @@ int usbh_initialize(uint8_t busid, uintptr_t reg_base)
 
     usbh_bus_init(bus, busid, reg_base);
 
+    if (event_handler) {
+        bus->event_handler = event_handler;
+    } else {
+        bus->event_handler = dummy_event_handler;
+    }
+
 #ifdef __ARMCC_VERSION /* ARM C Compiler */
     extern const int usbh_class_info$$Base;
     extern const int usbh_class_info$$Limit;
@@ -695,6 +717,8 @@ int usbh_deinitialize(uint8_t busid)
 
     bus = &g_usbhost_bus[busid];
 
+    bus->event_handler(bus->busid, USB_HUB_INDEX_ANY, USB_HUB_PORT_ANY, USB_INTERFACE_ANY, USBH_EVENT_DEINIT);
+
     usbh_hub_deinitialize(bus);
 
     usb_slist_remove(&g_bus_head, &bus->list);

+ 35 - 2
core/usbh_core.h

@@ -28,6 +28,35 @@
 extern "C" {
 #endif
 
+enum usbh_event_type {
+    /* USB HCD IRQ */
+    USBH_EVENT_ERROR,
+    USBH_EVENT_SOF,
+
+    /* USB DEVICE STATUS */
+    USBH_EVENT_DEVICE_RESET,
+    USBH_EVENT_DEVICE_CONNECTED,
+    USBH_EVENT_DEVICE_DISCONNECTED,
+    USBH_EVENT_DEVICE_CONFIGURED,
+    USBH_EVENT_DEVICE_WAKEUP,
+    USBH_EVENT_DEVICE_SUSPEND,
+    USBH_EVENT_DEVICE_RESUME,
+
+    /* USB DEVICE INTERFACE STATUS */
+    USBH_EVENT_INTERFACE_UNSUPPORTED,
+    USBH_EVENT_INTERFACE_START,
+    USBH_EVENT_INTERFACE_STOP,
+
+    /* USB FRAMEWORK STATUS */
+    USBH_EVENT_INIT,
+    USBH_EVENT_DEINIT,
+    USBH_EVENT_UNKNOWN,
+};
+
+#define USB_HUB_PORT_ANY  0
+#define USB_HUB_INDEX_ANY 0
+#define USB_INTERFACE_ANY 0xff
+
 #define USB_CLASS_MATCH_VENDOR        0x0001
 #define USB_CLASS_MATCH_PRODUCT       0x0002
 #define USB_CLASS_MATCH_INTF_CLASS    0x0004
@@ -60,6 +89,8 @@ extern "C" {
                      USB_GET_MULT(ep_desc->wMaxPacketSize));                 \
     } while (0)
 
+typedef void (*usbh_event_handler_t)(uint8_t busid, uint8_t hub_index, uint8_t hub_port, uint8_t intf, uint8_t event);
+
 struct usbh_class_info {
     uint8_t match_flags;           /* Used for product specific matches; range is inclusive */
     uint8_t bInterfaceClass;       /* Base device class code */
@@ -131,7 +162,7 @@ struct usbh_hub {
     uint8_t powerdelay;
     uint8_t tt_think;
     bool ismtt;
-    struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
+    struct usb_hub_descriptor hub_desc;       /* USB 2.0 only */
     struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
     struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
     struct usbh_hubport *parent;
@@ -168,6 +199,8 @@ struct usbh_bus {
     struct usbh_devaddr_map devgen;
     usb_osal_thread_t hub_thread;
     usb_osal_mq_t hub_mq;
+
+    void (*event_handler)(uint8_t busid, uint8_t hub_index, uint8_t hub_port, uint8_t intf, uint8_t event);
 };
 
 static inline void usbh_control_urb_fill(struct usbh_urb *urb,
@@ -274,7 +307,7 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
  */
 int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting);
 
-int usbh_initialize(uint8_t busid, uintptr_t reg_base);
+int usbh_initialize(uint8_t busid, uintptr_t reg_base, usbh_event_handler_t event_handler);
 int usbh_deinitialize(uint8_t busid);
 void *usbh_find_class_instance(const char *devname);
 struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port);

+ 2 - 1
docs/source/api/api_host.rst

@@ -126,10 +126,11 @@ usbh_initialize
 
 .. code-block:: C
 
-    int usbh_initialize(uint8_t busid, uint32_t reg_base);
+    int usbh_initialize(uint8_t busid, uint32_t reg_base, usbh_event_handler_t event_handler);
 
 - **busid**  bus id,从 0开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
 - **reg_base**  hcd 寄存器基地址
+- **event_handler**  host 事件回调函数,可以为NULL
 - **return**  0 表示正常其他表示错误
 
 usbh_find_class_instance

+ 1 - 1
docs/source/quick_start/demo.rst

@@ -203,7 +203,7 @@ USB Host 移植要点
 
 - 链接脚本修改参考 :ref:`usbh_link_script` 章节
 - 如果芯片带 cache,cache 修改参考 :ref:`usb_cache` 章节
-- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
+- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` 还有 `event_handler` 可缺省为NULL, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
 - 启动线程
 
 .. figure:: img/stm32_18.png

+ 1 - 1
docs/source/quick_start/rtthread.rst

@@ -56,7 +56,7 @@
 * USB IP 相关的 config 需要用户自己根据芯片实际情况修改
 * 在代码中实现 `usb_hc_low_level_init` 函数
 * 在 USB 中断函数中调用 `USBH_IRQHandler`,并传入 `busid`
-* 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
+* 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` 还有 `event_handler` 可缺省为NULL, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
 * 使用 `scons --target=mdk5` 或者 `scons` 进行编译,如果是mdk,需要使用 AC6 编译器
 * 链接脚本修改参考 :ref:`usbh_link_script` 章节
 * 如果芯片带 cache,cache 修改参考 :ref:`usb_cache` 章节

+ 2 - 2
docs/source/quick_start/transplant.rst

@@ -19,11 +19,11 @@ USB Host 移植要点
 - 拷贝 CherryUSB 源码到工程目录下,并按需添加源文件和头文件路径,头文件路径建议全部添加。其中 `usbh_core.c` 、 `usb_hc_xxx.c` 以及 **osal** 目录下源文件(根据不同的 os 选择对应的源文件)为必须添加项。而 `usb_hc_xxx.c` 是芯片所对应的 USB IP hcd 部分驱动,如果不知道自己芯片属于那个 USB IP,参考 **port** 目录下的不同 USB IP 的 readme。如果使用的 USB IP 没有支持,只能自己实现了
 - 拷贝 `cherryusb_config_template.h` 文件到自己工程目录下,命名为 `usb_config.h`,并添加相应的目录头文件路径
 - 实现 `usb_hc_low_level_init` 函数(该函数主要负责 USB 时钟、引脚、中断的初始化)。该函数可以放在你想要放的任何参与编译的 c 文件中。如何进行 USB 的时钟、引脚、中断等初始化,请自行根据你使用的芯片原厂提供的源码中进行添加。
-- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
+- 调用 `usbh_initialize` 并填入 `busid` 和 USB IP 的 `reg base` 还有 `event_handler` 可缺省为NULL, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS`
 - 在中断函数中调用 `USBH_IRQHandler`,并传入 `busid`, 如果你的 SDK 中中断入口已经存在 `USBH_IRQHandler` ,请更改 USB 协议栈中的名称
 - 链接脚本修改参考 :ref:`usbh_link_script` 章节
 - 如果芯片带 cache,cache 修改参考 :ref:`usb_cache` 章节
-- 调用 `usbh_initialize` ,填入 `busid` 和 USB IP 的 `reg base`, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS` 。基础的 cdc + hid + msc 参考 `usb_host.c` 文件,其余参考 **platform** 目录下适配
+- 调用 `usbh_initialize` ,填入 `busid` 和 USB IP 的 `reg base` 还有 `event_handler` 可缺省为NULL, `busid` 从 0 开始,不能超过 `CONFIG_USBHOST_MAX_BUS` 。基础的 cdc + hid + msc 参考 `usb_host.c` 文件,其余参考 **platform** 目录下适配
 
 .. _usbh_link_script:
 

+ 1 - 1
platform/rtthread/usb_msh.c

@@ -21,7 +21,7 @@ int usbh_init(int argc, char **argv)
 
     busid = atoi(argv[1]);
     reg_base = strtoll(argv[2], NULL, 16);
-    usbh_initialize(busid, reg_base);
+    usbh_initialize(busid, reg_base, NULL);
 
     return 0;
 }

+ 2 - 0
port/dwc2/usb_hc_dwc2.c

@@ -745,8 +745,10 @@ int usb_hc_init(struct usbh_bus *bus)
 
     USB_OTG_HOST->HCFG &= ~USB_OTG_HCFG_FSLSPCS;
     if (g_dwc2_hcd[bus->hcd.hcd_id].user_params.phy_type == DWC2_PHY_TYPE_PARAM_FS) {
+        bus->hcd.roothub.speed = USB_SPEED_FULL;
         USB_OTG_HOST->HCFG |= USB_OTG_HCFG_FSLSPCLKSEL_48_MHZ;
     } else {
+        bus->hcd.roothub.speed = USB_SPEED_HIGH;
         USB_OTG_HOST->HCFG |= USB_OTG_HCFG_FSLSPCLKSEL_30_60_MHZ;
     }
 

+ 2 - 2
port/ehci/usb_glue_aic.c

@@ -160,12 +160,12 @@ int __usbh_init(void)
 #endif
 
 #ifdef AIC_USING_USB0_HOST
-    usbh_initialize(bus_id, USB_HOST0_BASE);
+    usbh_initialize(bus_id, USB_HOST0_BASE, NULL);
     bus_id++;
 #endif
 
 #ifdef AIC_USING_USB1_HOST
-    usbh_initialize(bus_id, USB_HOST1_BASE);
+    usbh_initialize(bus_id, USB_HOST1_BASE, NULL);
     bus_id++;
 #endif
     return 0;

+ 2 - 2
port/ehci/usb_glue_t113.c

@@ -183,12 +183,12 @@ int __usbh_init(void)
 {
 #ifdef T113_USING_USB0_HOST
     /* USB0 MSC test OK */
-    usbh_initialize(0, USB0_BASE_ADDR);
+    usbh_initialize(0, USB0_BASE_ADDR, NULL);
 #endif
 
 #ifdef T113_USING_USB1_HOST
     /* USB1 MSC test OK */
-    usbh_initialize(1, USB1_BASE_ADDR);
+    usbh_initialize(1, USB1_BASE_ADDR, NULL);
 #endif
     return 0;
 }