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