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
0 commit comments