diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c index 008c600c..be061cd8 100644 --- a/class/hub/usbh_hub.c +++ b/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) { diff --git a/core/usbh_core.c b/core/usbh_core.c index 43ff7961..8860716a 100644 --- a/core/usbh_core.c +++ b/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); diff --git a/core/usbh_core.h b/core/usbh_core.h index f56aaf4e..f5cca270 100644 --- a/core/usbh_core.h +++ b/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); diff --git a/docs/source/api/api_host.rst b/docs/source/api/api_host.rst index 3368f47f..28287a0b 100644 --- a/docs/source/api/api_host.rst +++ b/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 diff --git a/docs/source/quick_start/demo.rst b/docs/source/quick_start/demo.rst index 9c5e6569..ebb211a9 100644 --- a/docs/source/quick_start/demo.rst +++ b/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 diff --git a/docs/source/quick_start/rtthread.rst b/docs/source/quick_start/rtthread.rst index e9c4df5b..132015d9 100644 --- a/docs/source/quick_start/rtthread.rst +++ b/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` 章节 diff --git a/docs/source/quick_start/transplant.rst b/docs/source/quick_start/transplant.rst index a6dcf14e..710497d4 100644 --- a/docs/source/quick_start/transplant.rst +++ b/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: diff --git a/platform/rtthread/usb_msh.c b/platform/rtthread/usb_msh.c index a153ed05..fc5cdaee 100644 --- a/platform/rtthread/usb_msh.c +++ b/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; } diff --git a/port/dwc2/usb_hc_dwc2.c b/port/dwc2/usb_hc_dwc2.c index df706eda..8a7ad9a8 100644 --- a/port/dwc2/usb_hc_dwc2.c +++ b/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; } diff --git a/port/ehci/usb_glue_aic.c b/port/ehci/usb_glue_aic.c index 500bc02a..644f2e37 100644 --- a/port/ehci/usb_glue_aic.c +++ b/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; diff --git a/port/ehci/usb_glue_t113.c b/port/ehci/usb_glue_t113.c index 0c99897f..d10d4d9a 100644 --- a/port/ehci/usb_glue_t113.c +++ b/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; }