Skip to content

Commit 96f4f3f

Browse files
jfischer-nokartben
authored andcommitted
usb: host: move bus event handling to a separate thread
Handle them in separate contexts so that the request completion callback cannot be blocked, such as when a device connection is detected and requires configuration. Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
1 parent fa77524 commit 96f4f3f

File tree

1 file changed

+55
-15
lines changed

1 file changed

+55
-15
lines changed

subsys/usb/host/usbh_core.c

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022 Nordic Semiconductor ASA
2+
* Copyright (c) 2022,2025 Nordic Semiconductor ASA
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -20,13 +20,27 @@ LOG_MODULE_REGISTER(uhs, CONFIG_USBH_LOG_LEVEL);
2020
static K_KERNEL_STACK_DEFINE(usbh_stack, CONFIG_USBH_STACK_SIZE);
2121
static struct k_thread usbh_thread_data;
2222

23+
static K_KERNEL_STACK_DEFINE(usbh_bus_stack, CONFIG_USBH_STACK_SIZE);
24+
static struct k_thread usbh_bus_thread_data;
25+
2326
K_MSGQ_DEFINE(usbh_msgq, sizeof(struct uhc_event),
2427
CONFIG_USBH_MAX_UHC_MSG, sizeof(uint32_t));
2528

29+
K_MSGQ_DEFINE(usbh_bus_msgq, sizeof(struct uhc_event),
30+
CONFIG_USBH_MAX_UHC_MSG, sizeof(uint32_t));
31+
2632
static int usbh_event_carrier(const struct device *dev,
2733
const struct uhc_event *const event)
2834
{
29-
return k_msgq_put(&usbh_msgq, event, K_NO_WAIT);
35+
int err;
36+
37+
if (event->type == UHC_EVT_EP_REQUEST) {
38+
err = k_msgq_put(&usbh_msgq, event, K_NO_WAIT);
39+
} else {
40+
err = k_msgq_put(&usbh_bus_msgq, event, K_NO_WAIT);
41+
}
42+
43+
return err;
3044
}
3145

3246
static int discard_ep_request(struct usbh_contex *const ctx,
@@ -47,18 +61,6 @@ static ALWAYS_INLINE int usbh_event_handler(struct usbh_contex *const ctx,
4761
{
4862
int ret = 0;
4963

50-
if (event->type == UHC_EVT_EP_REQUEST) {
51-
struct usb_device *const udev = event->xfer->udev;
52-
usbh_udev_cb_t cb = event->xfer->cb;
53-
54-
if (event->xfer->cb) {
55-
ret = cb(udev, event->xfer);
56-
} else {
57-
ret = discard_ep_request(ctx, event->xfer);
58-
}
59-
return ret;
60-
}
61-
6264
switch (event->type) {
6365
case UHC_EVT_DEV_CONNECTED_LS:
6466
case UHC_EVT_DEV_CONNECTED_FS:
@@ -90,6 +92,23 @@ static ALWAYS_INLINE int usbh_event_handler(struct usbh_contex *const ctx,
9092
return ret;
9193
}
9294

95+
static void usbh_bus_thread(void *p1, void *p2, void *p3)
96+
{
97+
ARG_UNUSED(p1);
98+
ARG_UNUSED(p2);
99+
ARG_UNUSED(p3);
100+
101+
struct usbh_contex *uhs_ctx;
102+
struct uhc_event event;
103+
104+
while (true) {
105+
k_msgq_get(&usbh_bus_msgq, &event, K_FOREVER);
106+
107+
uhs_ctx = (void *)uhc_get_event_ctx(event.dev);
108+
usbh_event_handler(uhs_ctx, &event);
109+
}
110+
}
111+
93112
static void usbh_thread(void *p1, void *p2, void *p3)
94113
{
95114
ARG_UNUSED(p1);
@@ -98,12 +117,25 @@ static void usbh_thread(void *p1, void *p2, void *p3)
98117

99118
struct usbh_contex *uhs_ctx;
100119
struct uhc_event event;
120+
usbh_udev_cb_t cb;
121+
int ret;
101122

102123
while (true) {
103124
k_msgq_get(&usbh_msgq, &event, K_FOREVER);
104125

126+
__ASSERT(event.type == UHC_EVT_EP_REQUEST, "Wrong event type");
105127
uhs_ctx = (void *)uhc_get_event_ctx(event.dev);
106-
usbh_event_handler(uhs_ctx, &event);
128+
cb = event.xfer->cb;
129+
130+
if (event.xfer->cb) {
131+
ret = cb(event.xfer->udev, event.xfer);
132+
} else {
133+
ret = discard_ep_request(uhs_ctx, event.xfer);
134+
}
135+
136+
if (ret) {
137+
LOG_ERR("Failed to handle request completion callback");
138+
}
107139
}
108140
}
109141

@@ -138,6 +170,14 @@ static int uhs_pre_init(void)
138170

139171
k_thread_name_set(&usbh_thread_data, "usbh");
140172

173+
k_thread_create(&usbh_bus_thread_data, usbh_bus_stack,
174+
K_KERNEL_STACK_SIZEOF(usbh_bus_stack),
175+
usbh_bus_thread,
176+
NULL, NULL, NULL,
177+
K_PRIO_COOP(9), 0, K_NO_WAIT);
178+
179+
k_thread_name_set(&usbh_thread_data, "usbh_bus");
180+
141181
return 0;
142182
}
143183

0 commit comments

Comments
 (0)