usb: device_next: Separate endpoint assignment from class data

Introduce usbd_class_iter for keeping endpoint assignment variables
and the single-linked list node. No functional changes right now, but
this paves the way for independent speed specific configurations.

Signed-off-by: Tomasz Moń <tomasz.mon@nordicsemi.no>
diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake
index 7e63904..f5bee7e 100644
--- a/cmake/linker_script/common/common-ram.cmake
+++ b/cmake/linker_script/common/common-ram.cmake
@@ -121,7 +121,7 @@
 if(CONFIG_USB_DEVICE_STACK OR CONFIG_USB_DEVICE_STACK_NEXT)
   zephyr_iterable_section(NAME usb_cfg_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
   zephyr_iterable_section(NAME usbd_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
-  zephyr_iterable_section(NAME usbd_class_node GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
+  zephyr_iterable_section(NAME usbd_class_iter GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN 4)
 endif()
 
 if(CONFIG_USB_HOST_STACK)
diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h
index 835f7f1..7aac5df 100644
--- a/include/zephyr/usb/usbd.h
+++ b/include/zephyr/usb/usbd.h
@@ -271,6 +271,32 @@
 	struct usbd_contex *uds_ctx;
 	/** Supported vendor request table, can be NULL */
 	const struct usbd_cctx_vendor_req *v_reqs;
+	/** Pointer to private data */
+	void *priv;
+};
+
+struct usbd_class_node {
+	/** Name of the USB device class instance */
+	const char *name;
+	/** Pointer to device support class API */
+	const struct usbd_class_api *api;
+	/** Pointer to USB device support class data */
+	struct usbd_class_data *data;
+};
+
+/**
+ * @cond INTERNAL_HIDDEN
+ *
+ * Variables necessary for per speed class management. For each speed (Full,
+ * High) there is separate `struct usbd_class_iter` pointing to the same
+ * `struct usbd_class_node` (because the class can only operate at one speed
+ * at a time).
+ */
+struct usbd_class_iter {
+	/** Node information for the slist. */
+	sys_snode_t node;
+	/** Pointer to public class node instance. */
+	struct usbd_class_node *const c_nd;
 	/** Bitmap of all endpoints assigned to the instance.
 	 *  The IN endpoints are mapped in the upper halfword.
 	 */
@@ -283,20 +309,9 @@
 	uint32_t iface_bm;
 	/** Variable to store the state of the class instance */
 	atomic_t state;
-	/** Pointer to private data */
-	void *priv;
 };
 
-struct usbd_class_node {
-	/** Node information for the slist. */
-	sys_snode_t node;
-	/** Name of the USB device class instance */
-	const char *name;
-	/** Pointer to device support class API */
-	const struct usbd_class_api *api;
-	/** Pointer to USB device support class data */
-	struct usbd_class_data *data;
-};
+/** @endcond */
 
 /**
  * @brief Get the USB device runtime context under which the class is registered
@@ -459,11 +474,14 @@
 #define USBD_DESC_SERIAL_NUMBER_DEFINE(d_name, d_string)		\
 	USBD_DESC_STRING_DEFINE(d_name, d_string, USBD_DUT_STRING_SERIAL_NUMBER)
 
-#define USBD_DEFINE_CLASS(class_name, class_api, class_data)		\
-	static STRUCT_SECTION_ITERABLE(usbd_class_node, class_name) = {	\
-		.name = STRINGIFY(class_name),				\
-		.api = class_api,					\
-		.data = class_data,					\
+#define USBD_DEFINE_CLASS(class_name, class_api, class_data)			\
+	static struct usbd_class_node class_name = {				\
+		.name = STRINGIFY(class_name),					\
+		.api = class_api,						\
+		.data = class_data,						\
+	};									\
+	static STRUCT_SECTION_ITERABLE(usbd_class_iter, class_name##_iter) = {	\
+		.c_nd = &class_name,						\
 	}
 
 /** @brief Helper to declare request table of usbd_cctx_vendor_req
diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c
index 8343cca..6bfe2d6 100644
--- a/samples/subsys/usb/common/sample_usbd_init.c
+++ b/samples/subsys/usb/common/sample_usbd_init.c
@@ -67,15 +67,16 @@
 		return NULL;
 	}
 
-	STRUCT_SECTION_FOREACH(usbd_class_node, node) {
+	STRUCT_SECTION_FOREACH(usbd_class_iter, iter) {
 		/* Pull everything that is enabled in our configuration. */
-		err = usbd_register_class(&sample_usbd, node->name, 1);
+		err = usbd_register_class(&sample_usbd, iter->c_nd->name, 1);
 		if (err) {
-			LOG_ERR("Failed to register %s (%d)", node->name, err);
+			LOG_ERR("Failed to register %s (%d)",
+				iter->c_nd->name, err);
 			return NULL;
 		}
 
-		LOG_DBG("Register %s", node->name);
+		LOG_DBG("Register %s", iter->c_nd->name);
 	}
 
 	/* Always use class code information from Interface Descriptors */
diff --git a/subsys/usb/device_next/usbd_ch9.c b/subsys/usb/device_next/usbd_ch9.c
index 17800c5..a89dc21 100644
--- a/subsys/usb/device_next/usbd_ch9.c
+++ b/subsys/usb/device_next/usbd_ch9.c
@@ -208,10 +208,10 @@
 static void sreq_feature_halt_notify(struct usbd_contex *const uds_ctx,
 				     const uint8_t ep, const bool halted)
 {
-	struct usbd_class_node *c_nd = usbd_class_get_by_ep(uds_ctx, ep);
+	struct usbd_class_iter *iter = usbd_class_get_by_ep(uds_ctx, ep);
 
-	if (c_nd != NULL) {
-		usbd_class_feature_halt(c_nd, ep, halted);
+	if (iter != NULL) {
+		usbd_class_feature_halt(iter->c_nd, ep, halted);
 	}
 }
 
@@ -455,7 +455,7 @@
 	struct usb_cfg_descriptor *cfg_desc;
 	struct usbd_config_node *cfg_nd;
 	enum usbd_speed get_desc_speed;
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	uint16_t len;
 
 	/*
@@ -502,10 +502,10 @@
 
 	net_buf_add_mem(buf, cfg_desc, MIN(net_buf_tailroom(buf), cfg_desc->bLength));
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
 		struct usb_desc_header **dhp;
 
-		dhp = usbd_class_get_desc(c_nd, get_desc_speed);
+		dhp = usbd_class_get_desc(iter->c_nd, get_desc_speed);
 		if (dhp == NULL) {
 			return -EINVAL;
 		}
@@ -721,28 +721,28 @@
 			  struct net_buf *const dbuf)
 {
 	struct usb_setup_packet *setup = usbd_get_setup_pkt(uds_ctx);
-	struct usbd_class_node *c_nd = NULL;
+	struct usbd_class_iter *iter = NULL;
 	int ret = 0;
 
 	switch (setup->RequestType.recipient) {
 	case USB_REQTYPE_RECIPIENT_ENDPOINT:
-		c_nd = usbd_class_get_by_ep(uds_ctx, setup->wIndex);
+		iter = usbd_class_get_by_ep(uds_ctx, setup->wIndex);
 		break;
 	case USB_REQTYPE_RECIPIENT_INTERFACE:
-		c_nd = usbd_class_get_by_iface(uds_ctx, setup->wIndex);
+		iter = usbd_class_get_by_iface(uds_ctx, setup->wIndex);
 		break;
 	case USB_REQTYPE_RECIPIENT_DEVICE:
-		c_nd = usbd_class_get_by_req(uds_ctx, setup->bRequest);
+		iter = usbd_class_get_by_req(uds_ctx, setup->bRequest);
 		break;
 	default:
 		break;
 	}
 
-	if (c_nd != NULL) {
+	if (iter != NULL) {
 		if (reqtype_is_to_device(setup)) {
-			ret = usbd_class_control_to_dev(c_nd, setup, dbuf);
+			ret = usbd_class_control_to_dev(iter->c_nd, setup, dbuf);
 		} else {
-			ret = usbd_class_control_to_host(c_nd, setup, dbuf);
+			ret = usbd_class_control_to_host(iter->c_nd, setup, dbuf);
 		}
 	} else {
 		errno = -ENOTSUP;
diff --git a/subsys/usb/device_next/usbd_class.c b/subsys/usb/device_next/usbd_class.c
index 21eddc1..7dc8e48 100644
--- a/subsys/usb/device_next/usbd_class.c
+++ b/subsys/usb/device_next/usbd_class.c
@@ -43,12 +43,12 @@
 	return len;
 }
 
-struct usbd_class_node *
+struct usbd_class_iter *
 usbd_class_get_by_config(struct usbd_contex *const uds_ctx,
 			 const uint8_t cnum,
 			 const uint8_t inum)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	struct usbd_config_node *cfg_nd;
 
 	cfg_nd = usbd_config_get(uds_ctx, cnum);
@@ -56,20 +56,20 @@
 		return NULL;
 	}
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		if (c_nd->data->iface_bm & BIT(inum)) {
-			return c_nd;
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		if (iter->iface_bm & BIT(inum)) {
+			return iter;
 		}
 	}
 
 	return NULL;
 }
 
-struct usbd_class_node *
+struct usbd_class_iter *
 usbd_class_get_by_iface(struct usbd_contex *const uds_ctx,
 			const uint8_t inum)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	struct usbd_config_node *cfg_nd;
 
 	cfg_nd = usbd_config_get_current(uds_ctx);
@@ -77,9 +77,9 @@
 		return NULL;
 	}
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		if (c_nd->data->iface_bm & BIT(inum)) {
-			return c_nd;
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		if (iter->iface_bm & BIT(inum)) {
+			return iter;
 		}
 	}
 
@@ -91,12 +91,12 @@
 			     struct net_buf *const buf)
 {
 	struct udc_buf_info *bi = udc_get_buf_info(buf);
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		if (bi->owner == c_nd) {
-			uint32_t ep_active = c_nd->data->ep_active;
-			uint32_t ep_assigned = c_nd->data->ep_assigned;
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		if (bi->owner == iter->c_nd) {
+			uint32_t ep_active = iter->ep_active;
+			uint32_t ep_assigned = iter->ep_assigned;
 
 			if (!usbd_ep_bm_is_set(&ep_active, bi->ep)) {
 				LOG_DBG("ep 0x%02x is not active", bi->ep);
@@ -135,11 +135,11 @@
 	return usbd_class_request(bi->owner, buf, err);
 }
 
-struct usbd_class_node *
+struct usbd_class_iter *
 usbd_class_get_by_ep(struct usbd_contex *const uds_ctx,
 		     const uint8_t ep)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	struct usbd_config_node *cfg_nd;
 	uint8_t ep_idx = USB_EP_GET_IDX(ep);
 	uint8_t cfg;
@@ -162,39 +162,39 @@
 		return NULL;
 	}
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		if (c_nd->data->ep_assigned & ep_bm) {
-			return c_nd;
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		if (iter->ep_assigned & ep_bm) {
+			return iter;
 		}
 	}
 
 	return NULL;
 }
 
-struct usbd_class_node *
+struct usbd_class_iter *
 usbd_class_get_by_req(struct usbd_contex *const uds_ctx,
 		      const uint8_t request)
 {
 	struct usbd_config_node *cfg_nd;
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 
 	cfg_nd = usbd_config_get_current(uds_ctx);
 	if (cfg_nd == NULL) {
 		return NULL;
 	}
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		if (c_nd->data->v_reqs == NULL) {
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		if (iter->c_nd->data->v_reqs == NULL) {
 			continue;
 		}
 
-		for (int i = 0; i < c_nd->data->v_reqs->len; i++) {
+		for (int i = 0; i < iter->c_nd->data->v_reqs->len; i++) {
 			/*
 			 * First instance always wins.
 			 * There is no other way to determine the recipient.
 			 */
-			if (c_nd->data->v_reqs->reqs[i] == request) {
-				return c_nd;
+			if (iter->c_nd->data->v_reqs->reqs[i] == request) {
+				return iter;
 			}
 		}
 	}
@@ -202,11 +202,11 @@
 	return NULL;
 }
 
-static struct usbd_class_node *usbd_class_node_get(const char *name)
+static struct usbd_class_iter *usbd_class_iter_get(const char *name)
 {
-	STRUCT_SECTION_FOREACH(usbd_class_node, c_nd) {
-		if (strcmp(name, c_nd->name) == 0) {
-			return c_nd;
+	STRUCT_SECTION_FOREACH(usbd_class_iter, iter) {
+		if (strcmp(name, iter->c_nd->name) == 0) {
+			return iter;
 		}
 	}
 
@@ -216,7 +216,7 @@
 }
 
 static int usbd_class_append(struct usbd_contex *const uds_ctx,
-			     struct usbd_class_node *const c_nd,
+			     struct usbd_class_iter *const iter,
 			     const uint8_t cfg)
 {
 	struct usbd_config_node *cfg_nd;
@@ -226,13 +226,13 @@
 		return -ENODATA;
 	}
 
-	sys_slist_append(&cfg_nd->class_list, &c_nd->node);
+	sys_slist_append(&cfg_nd->class_list, &iter->node);
 
 	return 0;
 }
 
 static int usbd_class_remove(struct usbd_contex *const uds_ctx,
-			     struct usbd_class_node *const c_nd,
+			     struct usbd_class_iter *const iter,
 			     const uint8_t cfg)
 {
 	struct usbd_config_node *cfg_nd;
@@ -242,7 +242,7 @@
 		return -ENODATA;
 	}
 
-	if (!sys_slist_find_and_remove(&cfg_nd->class_list, &c_nd->node)) {
+	if (!sys_slist_find_and_remove(&cfg_nd->class_list, &iter->node)) {
 		return -ENODATA;
 	}
 
@@ -253,7 +253,7 @@
 			  const uint8_t cfg)
 {
 	struct usbd_config_node *cfg_nd;
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	sys_snode_t *node;
 
 	cfg_nd = usbd_config_get(uds_ctx, cfg);
@@ -262,10 +262,10 @@
 	}
 
 	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);
-		usbd_class_shutdown(c_nd);
-		LOG_DBG("Remove class node %p from configuration %u", c_nd, cfg);
+		iter = CONTAINER_OF(node, struct usbd_class_iter, node);
+		atomic_clear_bit(&iter->state, USBD_CCTX_REGISTERED);
+		usbd_class_shutdown(iter->c_nd);
+		LOG_DBG("Remove class node %p from configuration %u", iter, cfg);
 	}
 
 	return 0;
@@ -279,12 +279,12 @@
 			const char *name,
 			const uint8_t cfg)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	struct usbd_class_data *data;
 	int ret;
 
-	c_nd = usbd_class_node_get(name);
-	if (c_nd == NULL) {
+	iter = usbd_class_iter_get(name);
+	if (iter == NULL) {
 		return -ENODEV;
 	}
 
@@ -296,19 +296,19 @@
 		goto register_class_error;
 	}
 
-	data = c_nd->data;
+	data = iter->c_nd->data;
 
 	/* TODO: does it still need to be atomic ? */
-	if (atomic_test_bit(&data->state, USBD_CCTX_REGISTERED)) {
+	if (atomic_test_bit(&iter->state, USBD_CCTX_REGISTERED)) {
 		LOG_WRN("Class instance already registered");
 		ret = -EBUSY;
 		goto register_class_error;
 	}
 
-	ret = usbd_class_append(uds_ctx, c_nd, cfg);
+	ret = usbd_class_append(uds_ctx, iter, cfg);
 	if (ret == 0) {
 		/* Initialize pointer back to the device struct */
-		atomic_set_bit(&data->state, USBD_CCTX_REGISTERED);
+		atomic_set_bit(&iter->state, USBD_CCTX_REGISTERED);
 		data->uds_ctx = uds_ctx;
 	}
 
@@ -321,12 +321,12 @@
 			  const char *name,
 			  const uint8_t cfg)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	struct usbd_class_data *data;
 	int ret;
 
-	c_nd = usbd_class_node_get(name);
-	if (c_nd == NULL) {
+	iter = usbd_class_iter_get(name);
+	if (iter == NULL) {
 		return -ENODEV;
 	}
 
@@ -338,18 +338,18 @@
 		goto unregister_class_error;
 	}
 
-	data = c_nd->data;
+	data = iter->c_nd->data;
 	/* TODO: does it still need to be atomic ? */
-	if (!atomic_test_bit(&data->state, USBD_CCTX_REGISTERED)) {
+	if (!atomic_test_bit(&iter->state, USBD_CCTX_REGISTERED)) {
 		LOG_WRN("Class instance not registered");
 		ret = -EBUSY;
 		goto unregister_class_error;
 	}
 
-	ret = usbd_class_remove(uds_ctx, c_nd, cfg);
+	ret = usbd_class_remove(uds_ctx, iter, cfg);
 	if (ret == 0) {
-		atomic_clear_bit(&data->state, USBD_CCTX_REGISTERED);
-		usbd_class_shutdown(c_nd);
+		atomic_clear_bit(&iter->state, USBD_CCTX_REGISTERED);
+		usbd_class_shutdown(iter->c_nd);
 		data->uds_ctx = NULL;
 	}
 
diff --git a/subsys/usb/device_next/usbd_class.h b/subsys/usb/device_next/usbd_class.h
index f6064b0..827342d 100644
--- a/subsys/usb/device_next/usbd_class.h
+++ b/subsys/usb/device_next/usbd_class.h
@@ -45,9 +45,9 @@
  * @param[in] uds_ctx Pointer to device context
  * @param[in] inum    Interface number
  *
- * @return Class node pointer or NULL
+ * @return Class iter pointer or NULL
  */
-struct usbd_class_node *usbd_class_get_by_iface(struct usbd_contex *uds_ctx,
+struct usbd_class_iter *usbd_class_get_by_iface(struct usbd_contex *uds_ctx,
 						uint8_t i_n);
 
 /**
@@ -57,9 +57,9 @@
  * @param[in] cnum    Configuration number
  * @param[in] inum    Interface number
  *
- * @return Class node pointer or NULL
+ * @return Class iter pointer or NULL
  */
-struct usbd_class_node *usbd_class_get_by_config(struct usbd_contex *uds_ctx,
+struct usbd_class_iter *usbd_class_get_by_config(struct usbd_contex *uds_ctx,
 						 uint8_t cnum,
 						 uint8_t inum);
 
@@ -71,9 +71,9 @@
  * @param[in] uds_ctx Pointer to device context
  * @param[in] ep      Endpoint address
  *
- * @return Class node pointer or NULL
+ * @return Class iter pointer or NULL
  */
-struct usbd_class_node *usbd_class_get_by_ep(struct usbd_contex *uds_ctx,
+struct usbd_class_iter *usbd_class_get_by_ep(struct usbd_contex *uds_ctx,
 					     uint8_t ep);
 
 /**
@@ -88,9 +88,9 @@
  * @param[in] uds_ctx Pointer to device context
  * @param[in] request bRequest value
  *
- * @return Class node pointer or NULL
+ * @return Class iter pointer or NULL
  */
-struct usbd_class_node *usbd_class_get_by_req(struct usbd_contex *uds_ctx,
+struct usbd_class_iter *usbd_class_get_by_req(struct usbd_contex *uds_ctx,
 					      uint8_t request);
 
 /**
diff --git a/subsys/usb/device_next/usbd_config.c b/subsys/usb/device_next/usbd_config.c
index 5ac859a..0efa6e0 100644
--- a/subsys/usb/device_next/usbd_config.c
+++ b/subsys/usb/device_next/usbd_config.c
@@ -44,13 +44,13 @@
 static void usbd_config_classes_enable(struct usbd_config_node *const cfg_nd,
 				       const bool enable)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
 		if (enable) {
-			usbd_class_enable(c_nd);
+			usbd_class_enable(iter->c_nd);
 		} else {
-			usbd_class_disable(c_nd);
+			usbd_class_disable(iter->c_nd);
 		}
 	}
 }
diff --git a/subsys/usb/device_next/usbd_core.c b/subsys/usb/device_next/usbd_core.c
index 40eed62..a5968d1 100644
--- a/subsys/usb/device_next/usbd_core.c
+++ b/subsys/usb/device_next/usbd_core.c
@@ -63,7 +63,7 @@
 				   struct udc_event *const event)
 {
 	struct usbd_config_node *cfg_nd;
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 
 	if (!usbd_state_is_configured(uds_ctx)) {
 		return;
@@ -75,16 +75,16 @@
 		return;
 	}
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
 		switch (event->type) {
 		case UDC_EVT_SUSPEND:
-			usbd_class_suspended(c_nd);
+			usbd_class_suspended(iter->c_nd);
 			break;
 		case UDC_EVT_RESUME:
-			usbd_class_resumed(c_nd);
+			usbd_class_resumed(iter->c_nd);
 			break;
 		case UDC_EVT_SOF:
-			usbd_class_sof(c_nd);
+			usbd_class_sof(iter->c_nd);
 			break;
 		default:
 			break;
@@ -253,10 +253,10 @@
 
 	k_thread_name_set(&usbd_thread_data, "usbd");
 
-	LOG_DBG("Available USB class nodes:");
-	STRUCT_SECTION_FOREACH(usbd_class_node, node) {
-		atomic_set(&node->data->state, 0);
-		LOG_DBG("\t%p, name %s", node, node->name);
+	LOG_DBG("Available USB class iterators:");
+	STRUCT_SECTION_FOREACH(usbd_class_iter, iter) {
+		atomic_set(&iter->state, 0);
+		LOG_DBG("\t%p->%p, name %s", iter, iter->c_nd, iter->c_nd->name);
 	}
 
 	return 0;
diff --git a/subsys/usb/device_next/usbd_data.ld b/subsys/usb/device_next/usbd_data.ld
index c748bd7..ab2c754 100644
--- a/subsys/usb/device_next/usbd_data.ld
+++ b/subsys/usb/device_next/usbd_data.ld
@@ -1,4 +1,4 @@
 #include <zephyr/linker/iterable_sections.h>
 
 ITERABLE_SECTION_RAM(usbd_contex, Z_LINK_ITERABLE_SUBALIGN)
-ITERABLE_SECTION_RAM(usbd_class_node, Z_LINK_ITERABLE_SUBALIGN)
+ITERABLE_SECTION_RAM(usbd_class_iter, Z_LINK_ITERABLE_SUBALIGN)
diff --git a/subsys/usb/device_next/usbd_init.c b/subsys/usb/device_next/usbd_init.c
index 76cfb9f..ac3814f 100644
--- a/subsys/usb/device_next/usbd_init.c
+++ b/subsys/usb/device_next/usbd_init.c
@@ -109,11 +109,10 @@
  * USB device configuration.
  */
 static int init_configuration_inst(struct usbd_contex *const uds_ctx,
-				   struct usbd_class_node *const c_nd,
+				   struct usbd_class_iter *const iter,
 				   uint32_t *const config_ep_bm,
 				   uint8_t *const nif)
 {
-	struct usbd_class_data *const data = c_nd->data;
 	struct usb_desc_header **dhp;
 	struct usb_if_descriptor *ifd = NULL;
 	struct usb_ep_descriptor *ed;
@@ -138,25 +137,25 @@
 
 	speed = usbd_caps_speed(uds_ctx);
 	LOG_DBG("Highest speed supported by the controller is %u", speed);
-	dhp = usbd_class_get_desc(c_nd, speed);
+	dhp = usbd_class_get_desc(iter->c_nd, speed);
 	if (dhp == NULL) {
 		return -EINVAL;
 	}
 
 	tmp_nif = *nif;
-	data->iface_bm = 0U;
-	data->ep_active = 0U;
+	iter->iface_bm = 0U;
+	iter->ep_active = 0U;
 
 	while (*dhp != NULL && (*dhp)->bLength != 0) {
 
 		if ((*dhp)->bDescriptorType == USB_DESC_INTERFACE) {
 			ifd = (struct usb_if_descriptor *)(*dhp);
 
-			data->ep_active |= class_ep_bm;
+			iter->ep_active |= class_ep_bm;
 
 			if (ifd->bAlternateSetting == 0) {
 				ifd->bInterfaceNumber = tmp_nif;
-				data->iface_bm |= BIT(tmp_nif);
+				iter->iface_bm |= BIT(tmp_nif);
 				tmp_nif++;
 			} else {
 				ifd->bInterfaceNumber = tmp_nif - 1;
@@ -194,10 +193,10 @@
 	}
 
 	*nif = tmp_nif;
-	data->ep_active |= class_ep_bm;
+	iter->ep_active |= class_ep_bm;
 
 	LOG_INF("Instance iface-bm 0x%08x ep-bm 0x%08x",
-		data->iface_bm, data->ep_active);
+		iter->iface_bm, iter->ep_active);
 
 	return 0;
 }
@@ -211,30 +210,30 @@
 			      struct usbd_config_node *const cfg_nd)
 {
 	struct usb_cfg_descriptor *cfg_desc = cfg_nd->desc;
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 	uint32_t config_ep_bm = 0;
 	size_t cfg_len = 0;
 	uint8_t nif = 0;
 	int ret;
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
 
-		ret = init_configuration_inst(uds_ctx, c_nd,
+		ret = init_configuration_inst(uds_ctx, iter,
 					      &config_ep_bm, &nif);
 		if (ret != 0) {
 			LOG_ERR("Failed to assign endpoint addresses");
 			return ret;
 		}
 
-		ret = usbd_class_init(c_nd);
+		ret = usbd_class_init(iter->c_nd);
 		if (ret != 0) {
 			LOG_ERR("Failed to initialize class instance");
 			return ret;
 		}
 
-		LOG_INF("Init class node %p, descriptor length %zu",
-			c_nd, usbd_class_desc_len(c_nd, usbd_caps_speed(uds_ctx)));
-		cfg_len += usbd_class_desc_len(c_nd, usbd_caps_speed(uds_ctx));
+		LOG_INF("Init class node %p, descriptor length %zu", iter->c_nd,
+			usbd_class_desc_len(iter->c_nd, usbd_caps_speed(uds_ctx)));
+		cfg_len += usbd_class_desc_len(iter->c_nd, usbd_caps_speed(uds_ctx));
 	}
 
 	/* Update wTotalLength and bNumInterfaces of configuration descriptor */
@@ -247,9 +246,9 @@
 		cfg_desc->wTotalLength);
 
 	/* Finally reset configuration's endpoint assignment */
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		c_nd->data->ep_assigned = c_nd->data->ep_active;
-		ret = unassign_eps(uds_ctx, &config_ep_bm, &c_nd->data->ep_active);
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		iter->ep_assigned = iter->ep_active;
+		ret = unassign_eps(uds_ctx, &config_ep_bm, &iter->ep_active);
 		if (ret != 0) {
 			return ret;
 		}
diff --git a/subsys/usb/device_next/usbd_interface.c b/subsys/usb/device_next/usbd_interface.c
index 1cd4292..7099ed3 100644
--- a/subsys/usb/device_next/usbd_interface.c
+++ b/subsys/usb/device_next/usbd_interface.c
@@ -51,7 +51,7 @@
 }
 
 static int usbd_interface_modify(struct usbd_contex *const uds_ctx,
-				 struct usbd_class_node *const node,
+				 struct usbd_class_iter *const iter,
 				 const enum ep_op op,
 				 const uint8_t iface,
 				 const uint8_t alt)
@@ -60,7 +60,7 @@
 	bool found_iface = false;
 	int ret;
 
-	dhp = usbd_class_get_desc(node, usbd_bus_speed(uds_ctx));
+	dhp = usbd_class_get_desc(iter->c_nd, usbd_bus_speed(uds_ctx));
 	if (dhp == NULL) {
 		return -EINVAL;
 	}
@@ -79,7 +79,7 @@
 			if (ifd->bInterfaceNumber == iface &&
 			    ifd->bAlternateSetting == alt) {
 				found_iface = true;
-				LOG_DBG("Found interface %u %p", iface, node);
+				LOG_DBG("Found interface %u %p", iface, iter);
 				if (ifd->bNumEndpoints == 0) {
 					LOG_INF("No endpoints, skip interface");
 					break;
@@ -89,14 +89,14 @@
 
 		if ((*dhp)->bDescriptorType == USB_DESC_ENDPOINT && found_iface) {
 			ed = (struct usb_ep_descriptor *)(*dhp);
-			ret = handle_ep_op(uds_ctx, op, ed, &node->data->ep_active);
+			ret = handle_ep_op(uds_ctx, op, ed, &iter->ep_active);
 			if (ret) {
 				return ret;
 			}
 
 			LOG_INF("Modify interface %u ep 0x%02x by op %u ep_bm %x",
 				iface, ed->bEndpointAddress,
-				op, node->data->ep_active);
+				op, iter->ep_active);
 		}
 
 		dhp++;
@@ -110,10 +110,10 @@
 int usbd_interface_shutdown(struct usbd_contex *const uds_ctx,
 			    struct usbd_config_node *const cfg_nd)
 {
-	struct usbd_class_node *c_nd;
+	struct usbd_class_iter *iter;
 
-	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, c_nd, node) {
-		uint32_t *ep_bm = &c_nd->data->ep_active;
+	SYS_SLIST_FOR_EACH_CONTAINER(&cfg_nd->class_list, iter, node) {
+		uint32_t *ep_bm = &iter->ep_active;
 
 		for (int idx = 1; idx < 16 && *ep_bm; idx++) {
 			uint8_t ep_in = USB_EP_DIR_IN | idx;
@@ -147,7 +147,7 @@
 
 	/* Set default alternate for all interfaces */
 	for (int i = 0; i < desc->bNumInterfaces; i++) {
-		struct usbd_class_node *class;
+		struct usbd_class_iter *class;
 		int ret;
 
 		class = usbd_class_get_by_config(uds_ctx, new_cfg, i);
@@ -168,7 +168,7 @@
 		       const uint8_t iface,
 		       const uint8_t alt)
 {
-	struct usbd_class_node *class;
+	struct usbd_class_iter *class;
 	uint8_t cur_alt;
 	int ret;
 
@@ -206,7 +206,7 @@
 		return ret;
 	}
 
-	usbd_class_update(class, iface, alt);
+	usbd_class_update(class->c_nd, iface, alt);
 	usbd_set_alt_value(uds_ctx, iface, alt);
 
 	return 0;
diff --git a/subsys/usb/device_next/usbd_shell.c b/subsys/usb/device_next/usbd_shell.c
index 22c903b..fd27c5d 100644
--- a/subsys/usb/device_next/usbd_shell.c
+++ b/subsys/usb/device_next/usbd_shell.c
@@ -397,10 +397,11 @@
 	entry->help = NULL;
 	entry->subcmd = NULL;
 
-	STRUCT_SECTION_FOREACH(usbd_class_node, node) {
-		if ((node->name != NULL) && (strlen(node->name) != 0)) {
+	STRUCT_SECTION_FOREACH(usbd_class_iter, iter) {
+		if ((iter->c_nd->name != NULL) &&
+		    (strlen(iter->c_nd->name) != 0)) {
 			if (match_idx == idx) {
-				entry->syntax = node->name;
+				entry->syntax = iter->c_nd->name;
 				break;
 			}