Skip to content

Commit 1c94702

Browse files
jfischer-nonashif
authored andcommitted
drivers: udc: add opaque pointer to store upper layer private data
Add an opaque pointer to store upper layer private data and initialize it with the USB device context during controller initialization. Use the pointer in event processing to get the correct context. Fixes commit 48f2a4b ("usb: device_next: remove initialized state checks in event processing") Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no> (cherry picked from commit 5ddaa3b)
1 parent da137a5 commit 1c94702

File tree

4 files changed

+44
-16
lines changed

4 files changed

+44
-16
lines changed

drivers/usb/udc/udc_common.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,13 +739,14 @@ int udc_disable(const struct device *dev)
739739
return ret;
740740
}
741741

742-
int udc_init(const struct device *dev, udc_event_cb_t event_cb)
742+
int udc_init(const struct device *dev,
743+
udc_event_cb_t event_cb, const void *const event_ctx)
743744
{
744745
const struct udc_api *api = dev->api;
745746
struct udc_data *data = dev->data;
746747
int ret;
747748

748-
if (event_cb == NULL) {
749+
if (event_cb == NULL || event_ctx == NULL) {
749750
return -EINVAL;
750751
}
751752

@@ -757,6 +758,7 @@ int udc_init(const struct device *dev, udc_event_cb_t event_cb)
757758
}
758759

759760
data->event_cb = event_cb;
761+
data->event_ctx = event_ctx;
760762

761763
ret = api->init(dev);
762764
if (ret == 0) {

include/zephyr/drivers/usb/udc.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,10 @@ struct udc_data {
277277
struct udc_device_caps caps;
278278
/** Driver access mutex */
279279
struct k_mutex mutex;
280-
/** Callback to submit an UDC event to upper layer */
280+
/** Callback to submit an UDC event to higher layer */
281281
udc_event_cb_t event_cb;
282+
/** Opaque pointer to store higher layer context */
283+
const void *event_ctx;
282284
/** USB device controller status */
283285
atomic_t status;
284286
/** Internal used Control Sequence Stage */
@@ -345,14 +347,16 @@ static inline bool udc_is_suspended(const struct device *dev)
345347
* After initialization controller driver should be able to detect
346348
* power state of the bus and signal power state changes.
347349
*
348-
* @param[in] dev Pointer to device struct of the driver instance
349-
* @param[in] event_cb Event callback from the higher layer (USB device stack)
350+
* @param[in] dev Pointer to device struct of the driver instance
351+
* @param[in] event_cb Event callback from the higher layer (USB device stack)
352+
* @param[in] event_ctx Opaque pointer to higher layer context
350353
*
351354
* @return 0 on success, all other values should be treated as error.
352355
* @retval -EINVAL on parameter error (no callback is passed)
353356
* @retval -EALREADY already initialized
354357
*/
355-
int udc_init(const struct device *dev, udc_event_cb_t event_cb);
358+
int udc_init(const struct device *dev,
359+
udc_event_cb_t event_cb, const void *const event_ctx);
356360

357361
/**
358362
* @brief Enable USB device controller
@@ -702,6 +706,24 @@ static inline struct udc_buf_info *udc_get_buf_info(const struct net_buf *const
702706
return (struct udc_buf_info *)net_buf_user_data(buf);
703707
}
704708

709+
710+
/**
711+
* @brief Get pointer to higher layer context
712+
*
713+
* The address of the context is passed as an argument to the udc_init()
714+
* function and is stored in the UDC data.
715+
*
716+
* @param[in] dev Pointer to device struct of the driver instance
717+
*
718+
* @return Opaque pointer to higher layer context
719+
*/
720+
static inline const void *udc_get_event_ctx(const struct device *dev)
721+
{
722+
struct udc_data *data = dev->data;
723+
724+
return data->event_ctx;
725+
}
726+
705727
/**
706728
* @}
707729
*/

subsys/usb/device_next/usbd_core.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -187,24 +187,24 @@ static void usbd_thread(void *p1, void *p2, void *p3)
187187
ARG_UNUSED(p2);
188188
ARG_UNUSED(p3);
189189

190+
struct usbd_context *uds_ctx;
190191
struct udc_event event;
191192

192193
while (true) {
193194
k_msgq_get(&usbd_msgq, &event, K_FOREVER);
194195

195-
STRUCT_SECTION_FOREACH(usbd_context, uds_ctx) {
196-
if (uds_ctx->dev == event.dev) {
197-
usbd_event_handler(uds_ctx, &event);
198-
}
199-
}
196+
uds_ctx = (void *)udc_get_event_ctx(event.dev);
197+
__ASSERT(uds_ctx != NULL && usbd_is_initialized(uds_ctx),
198+
"USB device is not initialized");
199+
usbd_event_handler(uds_ctx, &event);
200200
}
201201
}
202202

203203
int usbd_device_init_core(struct usbd_context *const uds_ctx)
204204
{
205205
int ret;
206206

207-
ret = udc_init(uds_ctx->dev, usbd_event_carrier);
207+
ret = udc_init(uds_ctx->dev, usbd_event_carrier, uds_ctx);
208208
if (ret != 0) {
209209
LOG_ERR("Failed to init device driver");
210210
return ret;

tests/drivers/udc/src/main.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static K_KERNEL_STACK_DEFINE(test_udc_stack, 512);
2424
static struct k_thread test_udc_thread_data;
2525
static K_SEM_DEFINE(ep_queue_sem, 0, 1);
2626
static uint8_t last_used_ep;
27+
static uint8_t test_event_ctx;
2728

2829
static int test_udc_event_handler(const struct device *dev,
2930
const struct udc_event *const event)
@@ -57,6 +58,9 @@ static void test_udc_thread(void *p1, void *p2, void *p3)
5758
while (true) {
5859
k_msgq_get(&test_msgq, &event, K_FOREVER);
5960

61+
zassert_equal(udc_get_event_ctx(event.dev), &test_event_ctx,
62+
"Wrong pointer to higher layer context");
63+
6064
switch (event.type) {
6165
case UDC_EVT_VBUS_REMOVED:
6266
LOG_DBG("VBUS remove event");
@@ -368,7 +372,7 @@ static void test_udc_ep_mps(uint8_t type)
368372
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
369373
zassert_true(device_is_ready(dev), "UDC device not ready");
370374

371-
err = udc_init(dev, test_udc_event_handler);
375+
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
372376
zassert_ok(err, "Failed to initialize UDC driver");
373377

374378
err = udc_enable(dev);
@@ -476,7 +480,7 @@ ZTEST(udc_driver_test, test_udc_not_initialized)
476480
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
477481
zassert_true(device_is_ready(dev), "UDC device not ready");
478482

479-
err = udc_init(dev, NULL);
483+
err = udc_init(dev, NULL, NULL);
480484
zassert_equal(err, -EINVAL, "Not failed to initialize UDC");
481485

482486
err = udc_shutdown(dev);
@@ -515,7 +519,7 @@ ZTEST(udc_driver_test, test_udc_initialized)
515519
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
516520
zassert_true(device_is_ready(dev), "UDC device not ready");
517521

518-
err = udc_init(dev, test_udc_event_handler);
522+
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
519523
zassert_ok(err, "Failed to initialize UDC driver");
520524

521525
test_udc_set_address(dev, 0);
@@ -548,7 +552,7 @@ ZTEST(udc_driver_test, test_udc_enabled)
548552
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
549553
zassert_true(device_is_ready(dev), "UDC device not ready");
550554

551-
err = udc_init(dev, test_udc_event_handler);
555+
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
552556
zassert_ok(err, "Failed to initialize UDC driver");
553557

554558
err = udc_enable(dev);

0 commit comments

Comments
 (0)