usb: device_next: do a little more cleanup on shutdown
At the shutdown of USB device stack we have to cleanup and
remove all registered class instances and string descriptors
from a configuration.
Signed-off-by: Johann Fischer <johann.fischer@nordicsemi.no>
diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c
index 7470acc..1464d84 100644
--- a/subsys/usb/device_next/usbd_class.c
+++ b/subsys/usb/device_next/usbd_class.c
@@ -257,6 +257,27 @@
return 0;
}
+int usbd_class_remove_all(struct usbd_contex *const uds_ctx,
+ const uint8_t cfg)
+{
+ struct usbd_config_node *cfg_nd;
+ struct usbd_class_node *c_nd;
+ sys_snode_t *node;
+
+ cfg_nd = usbd_config_get(uds_ctx, cfg);
+ if (cfg_nd == NULL) {
+ return -ENODATA;
+ }
+
+ while ((node = sys_slist_get(&cfg_nd->class_list))) {
+ c_nd = CONTAINER_OF(node, struct usbd_class_node, node);
+ atomic_clear_bit(&c_nd->data->state, USBD_CCTX_REGISTERED);
+ LOG_DBG("Remove class node %p from configuration %u", c_nd, cfg);
+ }
+
+ return 0;
+}
+
/*
* All the functions below are part of public USB device support API.
*/
diff --git a/subsys/usb/device_next/usbd_class.h b/subsys/usb/device_next/usbd_class.h
index caa4262..a4d6793 100644
--- a/subsys/usb/device_next/usbd_class.h
+++ b/subsys/usb/device_next/usbd_class.h
@@ -93,4 +93,15 @@
struct usbd_class_node *usbd_class_get_by_req(struct usbd_contex *uds_ctx,
uint8_t request);
+/**
+ * @brief Remove all registered class instances from a configuration
+ *
+ * @param[in] uds_ctx Pointer to device context
+ * @param[in] cfg Configuration number (bConfigurationValue)
+ *
+ * @return 0 on success, other values on fail.
+ */
+int usbd_class_remove_all(struct usbd_contex *const uds_ctx,
+ const uint8_t cfg);
+
#endif /* ZEPHYR_INCLUDE_USBD_CLASS_H */
diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c
index 48cc0a6..c8ca933 100644
--- a/subsys/usb/device_next/usbd_core.c
+++ b/subsys/usb/device_next/usbd_core.c
@@ -13,6 +13,7 @@
#include <zephyr/usb/usbd.h>
#include "usbd_device.h"
+#include "usbd_desc.h"
#include "usbd_config.h"
#include "usbd_init.h"
#include "usbd_ch9.h"
@@ -199,6 +200,23 @@
int usbd_device_shutdown_core(struct usbd_contex *const uds_ctx)
{
+ struct usbd_config_node *cfg_nd;
+ int ret;
+
+ SYS_SLIST_FOR_EACH_CONTAINER(&uds_ctx->configs, cfg_nd, node) {
+ uint8_t cfg_value = usbd_config_get_value(cfg_nd);
+
+ ret = usbd_class_remove_all(uds_ctx, cfg_value);
+ if (ret) {
+ LOG_ERR("Failed to cleanup registered classes, %d", ret);
+ }
+ }
+
+ ret = usbd_desc_remove_all(uds_ctx);
+ if (ret) {
+ LOG_ERR("Failed to cleanup descriptors, %d", ret);
+ }
+
return udc_shutdown(uds_ctx->dev);
}
diff --git a/subsys/usb/device_next/usbd_desc.c b/subsys/usb/device_next/usbd_desc.c
index 9390fa1..89a1a1a 100644
--- a/subsys/usb/device_next/usbd_desc.c
+++ b/subsys/usb/device_next/usbd_desc.c
@@ -11,6 +11,7 @@
#include <zephyr/usb/usbd.h>
#include <zephyr/drivers/hwinfo.h>
+#include "usbd_desc.h"
#include "usbd_device.h"
#include <zephyr/logging/log.h>
@@ -117,6 +118,19 @@
return NULL;
}
+int usbd_desc_remove_all(struct usbd_contex *const uds_ctx)
+{
+ struct usbd_desc_node *tmp;
+ sys_snode_t *node;
+
+ while ((node = sys_slist_get(&uds_ctx->descriptors))) {
+ tmp = CONTAINER_OF(node, struct usbd_desc_node, node);
+ LOG_DBG("Remove descriptor node %p", tmp);
+ }
+
+ return 0;
+}
+
int usbd_add_descriptor(struct usbd_contex *const uds_ctx,
struct usbd_desc_node *const desc_nd)
{
diff --git a/subsys/usb/device_next/usbd_desc.h b/subsys/usb/device_next/usbd_desc.h
index e52d22f..ab796ef 100644
--- a/subsys/usb/device_next/usbd_desc.h
+++ b/subsys/usb/device_next/usbd_desc.h
@@ -23,4 +23,17 @@
void *usbd_get_descriptor(struct usbd_contex *uds_ctx,
const uint8_t type, const uint8_t idx);
+/**
+ * @brief Remove all descriptors from an USB device context
+ *
+ * This removes all loose descriptors like string descriptors.
+ * Descriptors like configuration, or interface are not touched
+ * by this.
+ *
+ * @param[in] uds_ctx Pointer to device context
+ *
+ * @return 0 on success, other values on fail.
+ */
+int usbd_desc_remove_all(struct usbd_contex *const uds_ctx);
+
#endif /* ZEPHYR_INCLUDE_USBD_DESC_H */