Skip to content

Commit c8d5898

Browse files
committed
usb: start supporting USB_DEVICE_STACK_NEXT
1 parent 06dffbb commit c8d5898

File tree

9 files changed

+288
-7
lines changed

9 files changed

+288
-7
lines changed

Diff for: Kconfig

+20
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,23 @@ config ARDUINO_ENTRY
3131
default y
3232

3333
endif
34+
35+
if USB_DEVICE_STACK_NEXT
36+
37+
config USB_DEVICE_PRODUCT
38+
string "USB Device Product"
39+
default "Arduino Generic board"
40+
41+
config USB_DEVICE_MANUFACTURER
42+
string "USB Device Manufacturer"
43+
default "Arduino"
44+
45+
config USB_DEVICE_VID
46+
hex "USB Device Vendor ID"
47+
default 0x2341
48+
49+
config USB_DEVICE_PID
50+
hex "USB Device Product ID"
51+
default 0x0001
52+
53+
endif

Diff for: cores/arduino/SerialUSB.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ class SerialUSB_ : public ZephyrSerial {
3131
};
3232
} // namespace arduino
3333

34-
#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM)
34+
#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS))
3535
extern arduino::SerialUSB_ Serial;
3636
#endif

Diff for: cores/arduino/USB.cpp

+57-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <zephyr/usb/usb_device.h>
1111
#include <SerialUSB.h>
1212

13-
#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM)
13+
#if (DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm))
1414
const struct device *const usb_dev = DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), cdc_acm, 0));
1515

1616
void usb_status_cb(enum usb_dc_status_code cb_status, const uint8_t *param) {
@@ -40,6 +40,58 @@ static void _baudChangeHandler(const struct device *dev, uint32_t rate)
4040
}
4141
}
4242

43+
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
44+
45+
extern "C" {
46+
#include <zephyr/usb/usbd.h>
47+
struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb);
48+
}
49+
50+
struct usbd_context *_usbd;
51+
52+
int usb_disable() {
53+
return usbd_disable(_usbd);
54+
}
55+
56+
static void usbd_next_cb(struct usbd_context *const ctx, const struct usbd_msg *msg)
57+
{
58+
if (usbd_can_detect_vbus(ctx)) {
59+
if (msg->type == USBD_MSG_VBUS_READY) {
60+
usbd_enable(ctx);
61+
}
62+
63+
if (msg->type == USBD_MSG_VBUS_REMOVED) {
64+
usbd_disable(ctx);
65+
}
66+
}
67+
68+
if (msg->type == USBD_MSG_CDC_ACM_LINE_CODING) {
69+
uint32_t baudrate;
70+
uart_line_ctrl_get(ctx->dev, UART_LINE_CTRL_BAUD_RATE, &baudrate);
71+
_baudChangeHandler(nullptr, baudrate);
72+
}
73+
}
74+
75+
static int enable_usb_device_next(void)
76+
{
77+
int err;
78+
79+
//_usbd = usbd_init_device(usbd_next_cb);
80+
_usbd = usbd_init_device(nullptr);
81+
if (_usbd == NULL) {
82+
return -ENODEV;
83+
}
84+
85+
if (!usbd_can_detect_vbus(_usbd)) {
86+
err = usbd_enable(_usbd);
87+
if (err) {
88+
return err;
89+
}
90+
}
91+
return 0;
92+
}
93+
#endif /* defined(CONFIG_USB_DEVICE_STACK_NEXT) */
94+
4395
void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) {
4496
arduino::SerialUSB_* dev = (arduino::SerialUSB_*)k_timer_user_data_get(timer);
4597
dev->_baudChangeHandler();
@@ -48,6 +100,7 @@ void arduino::SerialUSB_::_baudChangeDispatch(struct k_timer *timer) {
48100

49101
void arduino::SerialUSB_::begin(unsigned long baudrate, uint16_t config) {
50102
if (!started) {
103+
#ifndef CONFIG_USB_DEVICE_STACK_NEXT
51104
usb_enable(NULL);
52105
#ifndef CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT
53106
k_timer_init(&baud_timer, SerialUSB_::_baudChangeDispatch, NULL);
@@ -56,6 +109,9 @@ void arduino::SerialUSB_::begin(unsigned long baudrate, uint16_t config) {
56109
#else
57110
cdc_acm_dte_rate_callback_set(usb_dev, ::_baudChangeHandler);
58111
#endif
112+
#else
113+
enable_usb_device_next();
114+
#endif
59115
ZephyrSerial::begin(baudrate, config);
60116
started = true;
61117
}

Diff for: cores/arduino/main.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,18 @@ extern "C" __attribute__((section(".entry_point"), used)) void entry_point(struc
7171
extern uintptr_t _ebss;
7272
extern uintptr_t __heap_start;
7373
extern uintptr_t __heap_end;
74+
extern uintptr_t kheap_llext_heap;
75+
extern uintptr_t kheap_llext_heap_size;
76+
7477
//__asm volatile ("cpsie i");
7578

7679
const size_t alignment = 4096;
77-
printk("Heap end: %p\n", &__heap_end);
78-
printk("Heap start: %p\n", &__heap_start);
80+
printk("System Heap end: %p\n", &__heap_end);
81+
printk("System Heap start: %p\n", &__heap_start);
82+
printk("Sketch Heap start: %p, size %p\n", &kheap_llext_heap, &kheap_llext_heap_size);
7983
// __heap_start = (__heap_start + (alignment - 1)) & ~(alignment - 1);
8084

81-
memcpy(&_sdata, &_sidata, &_edata - &_sdata);
85+
memcpy(&_sdata, &_sidata, (&_edata - &_sdata) * sizeof(uint32_t));
8286
memset(&_sbss, 0, &_ebss - &_sbss);
8387
__libc_init_array();
8488
main();

Diff for: cores/arduino/usb_device_descriptor.c

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright (c) 2025 Arduino SA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stdint.h>
8+
9+
#include <zephyr/device.h>
10+
#include <zephyr/usb/usbd.h>
11+
#include <zephyr/usb/bos.h>
12+
13+
#include <zephyr/logging/log.h>
14+
15+
#ifdef CONFIG_USB_DEVICE_STACK_NEXT
16+
17+
/* By default, do not register the USB DFU class DFU mode instance. */
18+
static const char *const blocklist[] = {
19+
"dfu_dfu",
20+
NULL,
21+
};
22+
23+
/* doc device instantiation start */
24+
USBD_DEVICE_DEFINE(usbd,
25+
DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)),
26+
CONFIG_USB_DEVICE_VID, CONFIG_USB_DEVICE_PID);
27+
/* doc device instantiation end */
28+
29+
/* doc string instantiation start */
30+
USBD_DESC_LANG_DEFINE(sample_lang);
31+
USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_USB_DEVICE_MANUFACTURER);
32+
USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_USB_DEVICE_PRODUCT);
33+
USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn);
34+
/* doc string instantiation end */
35+
36+
USBD_DESC_CONFIG_DEFINE(fs_cfg_desc, "FS Configuration");
37+
USBD_DESC_CONFIG_DEFINE(hs_cfg_desc, "HS Configuration");
38+
39+
/* doc configuration instantiation start */
40+
static const uint8_t attributes = 0;
41+
42+
/* Full speed configuration */
43+
USBD_CONFIGURATION_DEFINE(sample_fs_config,
44+
attributes,
45+
250, &fs_cfg_desc);
46+
47+
/* High speed configuration */
48+
USBD_CONFIGURATION_DEFINE(sample_hs_config,
49+
attributes,
50+
250, &hs_cfg_desc);
51+
/* doc configuration instantiation end */
52+
53+
/*
54+
* This does not yet provide valuable information, but rather serves as an
55+
* example, and will be improved in the future.
56+
*/
57+
static const struct usb_bos_capability_lpm bos_cap_lpm = {
58+
.bLength = sizeof(struct usb_bos_capability_lpm),
59+
.bDescriptorType = USB_DESC_DEVICE_CAPABILITY,
60+
.bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION,
61+
.bmAttributes = 0UL,
62+
};
63+
64+
USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm);
65+
66+
static void sample_fix_code_triple(struct usbd_context *uds_ctx,
67+
const enum usbd_speed speed)
68+
{
69+
/* Always use class code information from Interface Descriptors */
70+
if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) ||
71+
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
72+
IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) ||
73+
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
74+
/*
75+
* Class with multiple interfaces have an Interface
76+
* Association Descriptor available, use an appropriate triple
77+
* to indicate it.
78+
*/
79+
usbd_device_set_code_triple(uds_ctx, speed,
80+
USB_BCC_MISCELLANEOUS, 0x02, 0x01);
81+
} else {
82+
usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0);
83+
}
84+
}
85+
86+
struct usbd_context *usbd_setup_device(usbd_msg_cb_t msg_cb)
87+
{
88+
int err;
89+
90+
/* doc add string descriptor start */
91+
err = usbd_add_descriptor(&usbd, &sample_lang);
92+
if (err) {
93+
return NULL;
94+
}
95+
96+
err = usbd_add_descriptor(&usbd, &sample_mfr);
97+
if (err) {
98+
return NULL;
99+
}
100+
101+
err = usbd_add_descriptor(&usbd, &sample_product);
102+
if (err) {
103+
return NULL;
104+
}
105+
106+
err = usbd_add_descriptor(&usbd, &sample_sn);
107+
if (err) {
108+
return NULL;
109+
}
110+
/* doc add string descriptor end */
111+
112+
if (usbd_caps_speed(&usbd) == USBD_SPEED_HS) {
113+
err = usbd_add_configuration(&usbd, USBD_SPEED_HS,
114+
&sample_hs_config);
115+
if (err) {
116+
return NULL;
117+
}
118+
119+
err = usbd_register_all_classes(&usbd, USBD_SPEED_HS, 1,
120+
blocklist);
121+
if (err) {
122+
return NULL;
123+
}
124+
125+
sample_fix_code_triple(&usbd, USBD_SPEED_HS);
126+
}
127+
128+
/* doc configuration register start */
129+
err = usbd_add_configuration(&usbd, USBD_SPEED_FS,
130+
&sample_fs_config);
131+
if (err) {
132+
return NULL;
133+
}
134+
/* doc configuration register end */
135+
136+
/* doc functions register start */
137+
err = usbd_register_all_classes(&usbd, USBD_SPEED_FS, 1, blocklist);
138+
if (err) {
139+
return NULL;
140+
}
141+
/* doc functions register end */
142+
143+
sample_fix_code_triple(&usbd, USBD_SPEED_FS);
144+
145+
if (msg_cb != NULL) {
146+
/* doc device init-and-msg start */
147+
err = usbd_msg_register_cb(&usbd, msg_cb);
148+
if (err) {
149+
return NULL;
150+
}
151+
/* doc device init-and-msg end */
152+
}
153+
154+
if (0) {
155+
(void)usbd_device_set_bcd_usb(&usbd, USBD_SPEED_FS, 0x0201);
156+
(void)usbd_device_set_bcd_usb(&usbd, USBD_SPEED_HS, 0x0201);
157+
158+
err = usbd_add_descriptor(&usbd, &sample_usbext);
159+
if (err) {
160+
return NULL;
161+
}
162+
}
163+
164+
return &usbd;
165+
}
166+
167+
struct usbd_context *usbd_init_device(usbd_msg_cb_t msg_cb)
168+
{
169+
int err;
170+
171+
if (usbd_setup_device(msg_cb) == NULL) {
172+
return NULL;
173+
}
174+
175+
/* doc device init start */
176+
err = usbd_init(&usbd);
177+
if (err) {
178+
return NULL;
179+
}
180+
/* doc device init end */
181+
182+
return &usbd;
183+
}
184+
185+
#endif

Diff for: cores/arduino/zephyrSerial.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ void arduino::ZephyrSerial::flush() {
205205
#endif
206206

207207
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials)
208-
#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM)
208+
#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS))
209209
// If CDC USB, use that object as Serial (and SerialUSB)
210210
arduino::ZephyrSerial Serial(DEVICE_DT_GET(DT_PHANDLE_BY_IDX(DT_PATH(zephyr_user), serials, FIRST_UART_INDEX)));
211211
#endif

Diff for: cores/arduino/zephyrSerial.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class ZephyrSerial : public HardwareSerial
8282
} // namespace arduino
8383

8484
#if DT_NODE_HAS_PROP(DT_PATH(zephyr_user), serials)
85-
#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && CONFIG_USB_CDC_ACM)
85+
#if !(DT_NODE_HAS_PROP(DT_PATH(zephyr_user), cdc_acm) && (CONFIG_USB_CDC_ACM || CONFIG_USBD_CDC_ACM_CLASS))
8686
// If CDC USB, use that object as Serial (and SerialUSB)
8787
extern arduino::ZephyrSerial Serial;
8888
#endif

Diff for: loader/llext_exports.c

+14
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,20 @@ FORCE_EXPORT_SYM(setsockopt);
133133
FORCE_EXPORT_SYM(cdc_acm_dte_rate_callback_set);
134134
#endif
135135

136+
#if defined(CONFIG_USB_DEVICE_STACK_NEXT)
137+
FORCE_EXPORT_SYM(usbd_init);
138+
FORCE_EXPORT_SYM(usbd_add_descriptor);
139+
FORCE_EXPORT_SYM(usbd_device_set_bcd_usb);
140+
FORCE_EXPORT_SYM(usbd_msg_register_cb);
141+
FORCE_EXPORT_SYM(usbd_device_set_code_triple);
142+
FORCE_EXPORT_SYM(usbd_register_all_classes);
143+
FORCE_EXPORT_SYM(usbd_add_configuration);
144+
FORCE_EXPORT_SYM(usbd_caps_speed);
145+
FORCE_EXPORT_SYM(usbd_can_detect_vbus);
146+
FORCE_EXPORT_SYM(usbd_enable);
147+
FORCE_EXPORT_SYM(usbd_disable);
148+
#endif
149+
136150
EXPORT_SYMBOL(k_timer_init);
137151
EXPORT_SYMBOL(k_fatal_halt);
138152
EXPORT_SYMBOL(k_work_schedule);

Diff for: variants/linked/linker_script.ld

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ SECTIONS {
8282
. = ALIGN(4);
8383
_sdata = .;
8484
*(.data .data.* .tdata*)
85+
*(._usbd_context.static.usbd_)
86+
*(.ramfunc)
8587
. = ALIGN(4);
8688
_edata = .;
8789
} >RAM AT> FLASH

0 commit comments

Comments
 (0)