Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport v3.7-branch] drivers: udc: add opaque pointer to store upper layer private data #76757

Merged
merged 1 commit into from
Oct 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions drivers/usb/udc/udc_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,13 +739,14 @@ int udc_disable(const struct device *dev)
return ret;
}

int udc_init(const struct device *dev, udc_event_cb_t event_cb)
int udc_init(const struct device *dev,
udc_event_cb_t event_cb, const void *const event_ctx)
{
const struct udc_api *api = dev->api;
struct udc_data *data = dev->data;
int ret;

if (event_cb == NULL) {
if (event_cb == NULL || event_ctx == NULL) {
return -EINVAL;
}

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

data->event_cb = event_cb;
data->event_ctx = event_ctx;

ret = api->init(dev);
if (ret == 0) {
Expand Down
30 changes: 26 additions & 4 deletions include/zephyr/drivers/usb/udc.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,10 @@ struct udc_data {
struct udc_device_caps caps;
/** Driver access mutex */
struct k_mutex mutex;
/** Callback to submit an UDC event to upper layer */
/** Callback to submit an UDC event to higher layer */
udc_event_cb_t event_cb;
/** Opaque pointer to store higher layer context */
const void *event_ctx;
/** USB device controller status */
atomic_t status;
/** Internal used Control Sequence Stage */
Expand Down Expand Up @@ -345,14 +347,16 @@ static inline bool udc_is_suspended(const struct device *dev)
* After initialization controller driver should be able to detect
* power state of the bus and signal power state changes.
*
* @param[in] dev Pointer to device struct of the driver instance
* @param[in] event_cb Event callback from the higher layer (USB device stack)
* @param[in] dev Pointer to device struct of the driver instance
* @param[in] event_cb Event callback from the higher layer (USB device stack)
* @param[in] event_ctx Opaque pointer to higher layer context
*
* @return 0 on success, all other values should be treated as error.
* @retval -EINVAL on parameter error (no callback is passed)
* @retval -EALREADY already initialized
*/
int udc_init(const struct device *dev, udc_event_cb_t event_cb);
int udc_init(const struct device *dev,
udc_event_cb_t event_cb, const void *const event_ctx);

/**
* @brief Enable USB device controller
Expand Down Expand Up @@ -702,6 +706,24 @@ static inline struct udc_buf_info *udc_get_buf_info(const struct net_buf *const
return (struct udc_buf_info *)net_buf_user_data(buf);
}


/**
* @brief Get pointer to higher layer context
*
* The address of the context is passed as an argument to the udc_init()
* function and is stored in the UDC data.
*
* @param[in] dev Pointer to device struct of the driver instance
*
* @return Opaque pointer to higher layer context
*/
static inline const void *udc_get_event_ctx(const struct device *dev)
{
struct udc_data *data = dev->data;

return data->event_ctx;
}

/**
* @}
*/
Expand Down
12 changes: 6 additions & 6 deletions subsys/usb/device_next/usbd_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,24 +187,24 @@ static void usbd_thread(void *p1, void *p2, void *p3)
ARG_UNUSED(p2);
ARG_UNUSED(p3);

struct usbd_context *uds_ctx;
struct udc_event event;

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

STRUCT_SECTION_FOREACH(usbd_context, uds_ctx) {
if (uds_ctx->dev == event.dev) {
usbd_event_handler(uds_ctx, &event);
}
}
uds_ctx = (void *)udc_get_event_ctx(event.dev);
__ASSERT(uds_ctx != NULL && usbd_is_initialized(uds_ctx),
"USB device is not initialized");
usbd_event_handler(uds_ctx, &event);
}
}

int usbd_device_init_core(struct usbd_context *const uds_ctx)
{
int ret;

ret = udc_init(uds_ctx->dev, usbd_event_carrier);
ret = udc_init(uds_ctx->dev, usbd_event_carrier, uds_ctx);
if (ret != 0) {
LOG_ERR("Failed to init device driver");
return ret;
Expand Down
12 changes: 8 additions & 4 deletions tests/drivers/udc/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static K_KERNEL_STACK_DEFINE(test_udc_stack, 512);
static struct k_thread test_udc_thread_data;
static K_SEM_DEFINE(ep_queue_sem, 0, 1);
static uint8_t last_used_ep;
static uint8_t test_event_ctx;

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

zassert_equal(udc_get_event_ctx(event.dev), &test_event_ctx,
"Wrong pointer to higher layer context");

switch (event.type) {
case UDC_EVT_VBUS_REMOVED:
LOG_DBG("VBUS remove event");
Expand Down Expand Up @@ -368,7 +372,7 @@ static void test_udc_ep_mps(uint8_t type)
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
zassert_true(device_is_ready(dev), "UDC device not ready");

err = udc_init(dev, test_udc_event_handler);
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
zassert_ok(err, "Failed to initialize UDC driver");

err = udc_enable(dev);
Expand Down Expand Up @@ -476,7 +480,7 @@ ZTEST(udc_driver_test, test_udc_not_initialized)
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
zassert_true(device_is_ready(dev), "UDC device not ready");

err = udc_init(dev, NULL);
err = udc_init(dev, NULL, NULL);
zassert_equal(err, -EINVAL, "Not failed to initialize UDC");

err = udc_shutdown(dev);
Expand Down Expand Up @@ -515,7 +519,7 @@ ZTEST(udc_driver_test, test_udc_initialized)
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
zassert_true(device_is_ready(dev), "UDC device not ready");

err = udc_init(dev, test_udc_event_handler);
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
zassert_ok(err, "Failed to initialize UDC driver");

test_udc_set_address(dev, 0);
Expand Down Expand Up @@ -548,7 +552,7 @@ ZTEST(udc_driver_test, test_udc_enabled)
dev = DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0));
zassert_true(device_is_ready(dev), "UDC device not ready");

err = udc_init(dev, test_udc_event_handler);
err = udc_init(dev, test_udc_event_handler, &test_event_ctx);
zassert_ok(err, "Failed to initialize UDC driver");

err = udc_enable(dev);
Expand Down
Loading