1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT zephyr_cdc_ncm_ethernet
8 
9 #include <zephyr/net/net_pkt.h>
10 #include <zephyr/net/ethernet.h>
11 
12 #include <eth.h>
13 
14 #include <zephyr/usb/usbd.h>
15 #include <zephyr/usb/usb_ch9.h>
16 #include <zephyr/usb/class/usb_cdc.h>
17 #include <zephyr/drivers/usb/udc.h>
18 
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(cdc_ncm, CONFIG_USBD_CDC_NCM_LOG_LEVEL);
21 
22 /* Set to 1 if you want to see hexdump of the packet in debug log level */
23 #define DUMP_PKT 0
24 
25 #define CDC_NCM_ALIGNMENT          4U
26 #define CDC_NCM_EP_MPS_INT         64U
27 #define CDC_NCM_INTERVAL_DEFAULT   50000UL
28 #define CDC_NCM_FS_INT_EP_INTERVAL USB_FS_INT_EP_INTERVAL(10000U)
29 #define CDC_NCM_HS_INT_EP_INTERVAL USB_HS_INT_EP_INTERVAL(10000U)
30 
31 #define NCM_USB_SPEED_FS 12000000UL
32 #define NCM_USB_SPEED_HS 480000000UL
33 
34 enum {
35 	CDC_NCM_IFACE_UP,
36 	CDC_NCM_DATA_IFACE_ENABLED,
37 	CDC_NCM_CLASS_SUSPENDED,
38 	CDC_NCM_OUT_ENGAGED,
39 };
40 
41 /* Chapter 6.2.7 table 6-4 */
42 #define CDC_NCM_RECV_MAX_DATAGRAMS_PER_NTB CONFIG_USBD_CDC_NCM_MAX_DGRAM_PER_NTB
43 #define CDC_NCM_RECV_NTB_MAX_SIZE 2048
44 
45 #define CDC_NCM_SEND_MAX_DATAGRAMS_PER_NTB 1
46 #define CDC_NCM_SEND_NTB_MAX_SIZE 2048
47 
48 /* Chapter 6.3 table 6-5 and 6-6 */
49 struct cdc_ncm_notification {
50 	union {
51 		uint8_t bmRequestType;
52 		struct usb_req_type_field RequestType;
53 	};
54 	uint8_t bNotificationType;
55 	uint16_t wValue;
56 	uint16_t wIndex;
57 	uint16_t wLength;
58 } __packed;
59 
60 enum ncm_notification_code {
61 	NETWORK_CONNECTION      = 0x00,
62 	RESPONSE_AVAILABLE      = 0x01,
63 	CONNECTION_SPEED_CHANGE = 0x2A,
64 };
65 
66 /* Chapter 3.2.1 table 3-1 */
67 #define NTH16_SIGNATURE 0x484D434E /* HMCN */
68 
69 struct nth16 {
70 	uint32_t dwSignature;
71 	uint16_t wHeaderLength;
72 	uint16_t wSequence;
73 	uint16_t wBlockLength;
74 	uint16_t wNdpIndex;
75 } __packed;
76 
77 /* Chapter 3.2.2 table 3-2 */
78 #define NTH32_SIGNATURE 0x686D636E /* hmcn */
79 
80 struct nth32 {
81 	uint32_t dwSignature;
82 	uint16_t wHeaderLength;
83 	uint16_t wSequence;
84 	uint32_t wBlockLength;
85 	uint32_t wNdpIndex;
86 } __packed;
87 
88 /* Chapter 3.3.1 table 3-3 */
89 #define NDP16_SIGNATURE_NCM0 0x304D434E /* 0MCN */
90 #define NDP16_SIGNATURE_NCM1 0x314D434E /* 1MCN */
91 
92 struct ndp16_datagram {
93 	uint16_t wDatagramIndex;
94 	uint16_t wDatagramLength;
95 } __packed;
96 
97 /* Chapter 3.3.2 table 3-4 */
98 #define NDP32_SIGNATURE_NCM0 0x306D636E /* 0mcn */
99 #define NDP32_SIGNATURE_NCM1 0x316D636E /* 1mcn */
100 
101 struct ndp32_datagram {
102 	uint32_t wDatagramIndex;
103 	uint32_t wDatagramLength;
104 } __packed;
105 
106 struct ndp16 {
107 	uint32_t dwSignature;
108 	uint16_t wLength;
109 	uint16_t wNextNdpIndex;
110 	struct ndp16_datagram datagram[];
111 } __packed;
112 
113 /* Chapter 6.2.1 table 6-3 */
114 struct ntb_parameters {
115 	uint16_t wLength;
116 	uint16_t bmNtbFormatsSupported;
117 	uint32_t dwNtbInMaxSize;
118 	uint16_t wNdbInDivisor;
119 	uint16_t wNdbInPayloadRemainder;
120 	uint16_t wNdbInAlignment;
121 	uint16_t wReserved;
122 	uint32_t dwNtbOutMaxSize;
123 	uint16_t wNdbOutDivisor;
124 	uint16_t wNdbOutPayloadRemainder;
125 	uint16_t wNdbOutAlignment;
126 	uint16_t wNtbOutMaxDatagrams;
127 } __packed;
128 
129 /* Chapter 6.2.7 table 6-4 */
130 struct ntb_input_size {
131 	uint32_t dwNtbInMaxSize;
132 	uint16_t wNtbInMaxDatagrams;
133 	uint16_t wReserved;
134 } __packed;
135 
136 #define NTB16_FORMAT_SUPPORTED BIT(0)
137 #define NTB32_FORMAT_SUPPORTED BIT(1)
138 
139 #define NTB_FORMAT_SUPPORTED (NTB16_FORMAT_SUPPORTED | \
140 			      COND_CODE_1(CONFIG_USBD_CDC_NCM_SUPPORT_NTB32, \
141 					  (NTB32_FORMAT_SUPPORTED), (0)))
142 
143 BUILD_ASSERT(!IS_ENABLED(CONFIG_USBD_CDC_NCM_SUPPORT_NTB32), "NTB32 not yet supported!");
144 
145 struct ncm_notify_network_connection {
146 	struct usb_setup_packet header;
147 } __packed;
148 
149 struct ncm_notify_connection_speed_change {
150 	struct usb_setup_packet header;
151 	uint32_t downlink;
152 	uint32_t uplink;
153 } __packed;
154 
155 union send_ntb {
156 	struct {
157 		struct nth16 nth;
158 		struct ndp16 ndp;
159 		struct ndp16_datagram ndp_datagram[CDC_NCM_SEND_MAX_DATAGRAMS_PER_NTB + 1];
160 	};
161 
162 	uint8_t data[CDC_NCM_SEND_NTB_MAX_SIZE];
163 } __packed;
164 
165 union recv_ntb {
166 	struct {
167 		struct nth16 nth;
168 	};
169 
170 	uint8_t data[CDC_NCM_RECV_NTB_MAX_SIZE];
171 } __packed;
172 
173 /*
174  * Transfers through two endpoints proceed in a synchronous manner,
175  * with maximum block of CDC_NCM_SEND_NTB_MAX_SIZE.
176  */
177 UDC_BUF_POOL_DEFINE(cdc_ncm_ep_pool,
178 		    DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 2,
179 		    MAX(CDC_NCM_SEND_NTB_MAX_SIZE, CDC_NCM_RECV_NTB_MAX_SIZE),
180 		    sizeof(struct udc_buf_info), NULL);
181 
182 /*
183  * Collection of descriptors used to assemble specific function descriptors.
184  * This structure is used by CDC NCM implementation to update and fetch
185  * properties at runtime. We currently support full and high speed.
186  */
187 struct usbd_cdc_ncm_desc {
188 	struct usb_association_descriptor iad;
189 
190 	struct usb_if_descriptor if0;
191 	struct cdc_header_descriptor if0_header;
192 	struct cdc_union_descriptor if0_union;
193 	struct cdc_ecm_descriptor if0_ecm;
194 	struct cdc_ncm_descriptor if0_ncm;
195 	struct usb_ep_descriptor if0_int_ep;
196 	struct usb_ep_descriptor if0_hs_int_ep;
197 
198 	struct usb_if_descriptor if1_0;
199 
200 	struct usb_if_descriptor if1_1;
201 	struct usb_ep_descriptor if1_1_in_ep;
202 	struct usb_ep_descriptor if1_1_out_ep;
203 	struct usb_ep_descriptor if1_1_hs_in_ep;
204 	struct usb_ep_descriptor if1_1_hs_out_ep;
205 
206 	struct usb_desc_header nil_desc;
207 };
208 
209 enum iface_state {
210 	IF_STATE_INIT,
211 	IF_STATE_CONNECTION_STATUS_SUBMITTED,
212 	IF_STATE_CONNECTION_STATUS_SENT,
213 	IF_STATE_SPEED_CHANGE_SUBMITTED,
214 	IF_STATE_SPEED_CHANGE_SENT,
215 	IF_STATE_DONE,
216 };
217 
218 struct cdc_ncm_eth_data {
219 	struct usbd_class_data *c_data;
220 	struct usbd_desc_node *const mac_desc_data;
221 	struct usbd_cdc_ncm_desc *const desc;
222 	const struct usb_desc_header **const fs_desc;
223 	const struct usb_desc_header **const hs_desc;
224 
225 	struct net_if *iface;
226 	uint8_t mac_addr[6];
227 
228 	atomic_t state;
229 	enum iface_state if_state;
230 	uint16_t tx_seq;
231 	uint16_t rx_seq;
232 
233 	struct k_sem sync_sem;
234 
235 	struct k_work_delayable notif_work;
236 };
237 
cdc_ncm_get_ctrl_if(struct cdc_ncm_eth_data * const data)238 static uint8_t cdc_ncm_get_ctrl_if(struct cdc_ncm_eth_data *const data)
239 {
240 	struct usbd_cdc_ncm_desc *desc = data->desc;
241 
242 	return desc->if0.bInterfaceNumber;
243 }
244 
cdc_ncm_get_int_in(struct usbd_class_data * const c_data)245 static uint8_t cdc_ncm_get_int_in(struct usbd_class_data *const c_data)
246 {
247 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
248 	const struct device *dev = usbd_class_get_private(c_data);
249 	struct cdc_ncm_eth_data *data = dev->data;
250 	struct usbd_cdc_ncm_desc *desc = data->desc;
251 
252 	if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
253 		return desc->if0_hs_int_ep.bEndpointAddress;
254 	}
255 
256 	return desc->if0_int_ep.bEndpointAddress;
257 }
258 
cdc_ncm_get_bulk_in(struct usbd_class_data * const c_data)259 static uint8_t cdc_ncm_get_bulk_in(struct usbd_class_data *const c_data)
260 {
261 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
262 	const struct device *dev = usbd_class_get_private(c_data);
263 	struct cdc_ncm_eth_data *data = dev->data;
264 	struct usbd_cdc_ncm_desc *desc = data->desc;
265 
266 	if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
267 		return desc->if1_1_hs_in_ep.bEndpointAddress;
268 	}
269 
270 	return desc->if1_1_in_ep.bEndpointAddress;
271 }
272 
cdc_ncm_get_bulk_in_mps(struct usbd_class_data * const c_data)273 static uint16_t cdc_ncm_get_bulk_in_mps(struct usbd_class_data *const c_data)
274 {
275 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
276 
277 	if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
278 		return 512U;
279 	}
280 
281 	return 64U;
282 }
283 
cdc_ncm_get_bulk_out(struct usbd_class_data * const c_data)284 static uint8_t cdc_ncm_get_bulk_out(struct usbd_class_data *const c_data)
285 {
286 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
287 	const struct device *dev = usbd_class_get_private(c_data);
288 	struct cdc_ncm_eth_data *data = dev->data;
289 	struct usbd_cdc_ncm_desc *desc = data->desc;
290 
291 	if (usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
292 		return desc->if1_1_hs_out_ep.bEndpointAddress;
293 	}
294 
295 	return desc->if1_1_out_ep.bEndpointAddress;
296 }
297 
cdc_ncm_buf_alloc(const uint8_t ep)298 static struct net_buf *cdc_ncm_buf_alloc(const uint8_t ep)
299 {
300 	struct net_buf *buf = NULL;
301 	struct udc_buf_info *bi;
302 
303 	buf = net_buf_alloc(&cdc_ncm_ep_pool, K_NO_WAIT);
304 	if (!buf) {
305 		return NULL;
306 	}
307 
308 	bi = udc_get_buf_info(buf);
309 	bi->ep = ep;
310 
311 	return buf;
312 }
313 
cdc_ncm_out_start(struct usbd_class_data * const c_data)314 static int cdc_ncm_out_start(struct usbd_class_data *const c_data)
315 {
316 	const struct device *dev = usbd_class_get_private(c_data);
317 	struct cdc_ncm_eth_data *data = dev->data;
318 	struct net_buf *buf;
319 	uint8_t ep;
320 	int ret;
321 
322 	if (atomic_test_and_set_bit(&data->state, CDC_NCM_OUT_ENGAGED)) {
323 		return -EBUSY;
324 	}
325 
326 	ep = cdc_ncm_get_bulk_out(c_data);
327 	buf = cdc_ncm_buf_alloc(ep);
328 	if (buf == NULL) {
329 		return -ENOMEM;
330 	}
331 
332 	ret = usbd_ep_enqueue(c_data, buf);
333 	if (ret) {
334 		LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
335 		net_buf_unref(buf);
336 	} else {
337 		LOG_DBG("enqueue out %u", buf->size);
338 	}
339 
340 	return  ret;
341 }
342 
verify_nth16(struct cdc_ncm_eth_data * const data,const union recv_ntb * const ntb,const uint16_t len)343 static int verify_nth16(struct cdc_ncm_eth_data *const data,
344 			const union recv_ntb *const ntb, const uint16_t len)
345 {
346 	const struct nth16 *nthdr16 = &ntb->nth;
347 	const struct ndp16 *ndphdr16;
348 
349 	if (len < sizeof(ntb->nth)) {
350 		LOG_DBG("DROP: %s len %d", "", len);
351 		return -EINVAL;
352 	}
353 
354 	if (sys_le16_to_cpu(nthdr16->wHeaderLength) != sizeof(struct nth16)) {
355 		LOG_DBG("DROP: %s len %d", "nth16",
356 			sys_le16_to_cpu(nthdr16->wHeaderLength));
357 		return -EINVAL;
358 	}
359 
360 	if (sys_le32_to_cpu(nthdr16->dwSignature) != NTH16_SIGNATURE) {
361 		LOG_DBG("DROP: %s signature 0x%04x", "nth16",
362 			(unsigned int)sys_le32_to_cpu(nthdr16->dwSignature));
363 		return -EINVAL;
364 	}
365 
366 	if (sys_le16_to_cpu(nthdr16->wSequence) != data->rx_seq) {
367 		LOG_WRN("OUT NTH wSequence %u mismatch expected %u",
368 			sys_le16_to_cpu(nthdr16->wSequence), data->rx_seq);
369 		data->rx_seq = sys_le16_to_cpu(nthdr16->wSequence);
370 	}
371 
372 	data->rx_seq++;
373 
374 	if (len < (sizeof(struct nth16) + sizeof(struct ndp16) +
375 		   2U * sizeof(struct ndp16_datagram))) {
376 		LOG_DBG("DROP: %s len %d", "min", len);
377 		return -EINVAL;
378 	}
379 
380 	if (sys_le16_to_cpu(nthdr16->wBlockLength) != len) {
381 		LOG_DBG("DROP: %s len %d", "block",
382 			sys_le16_to_cpu(nthdr16->wBlockLength));
383 		return -EINVAL;
384 	}
385 
386 	if (sys_le16_to_cpu(nthdr16->wBlockLength) > CDC_NCM_RECV_NTB_MAX_SIZE) {
387 		LOG_DBG("DROP: %s len %d", "block max",
388 			sys_le16_to_cpu(nthdr16->wBlockLength));
389 		return -EINVAL;
390 	}
391 
392 	if ((sys_le16_to_cpu(nthdr16->wNdpIndex) < sizeof(struct nth16)) ||
393 	    (sys_le16_to_cpu(nthdr16->wNdpIndex) >
394 	     (len - (sizeof(struct ndp16) + 2U * sizeof(struct ndp16_datagram))))) {
395 		LOG_DBG("DROP: ndp pos %d (%d)",
396 			sys_le16_to_cpu(nthdr16->wNdpIndex), len);
397 		return -EINVAL;
398 	}
399 
400 	ndphdr16 = (const struct ndp16 *)(ntb->data +
401 					   sys_le16_to_cpu(nthdr16->wNdpIndex));
402 
403 	if (sys_le16_to_cpu(ndphdr16->wLength) <
404 	    (sizeof(struct ndp16) + 2U * sizeof(struct ndp16_datagram))) {
405 		LOG_DBG("DROP: %s len %d", "ndp16",
406 			sys_le16_to_cpu(ndphdr16->wLength));
407 		return -EINVAL;
408 	}
409 
410 	if ((sys_le32_to_cpu(ndphdr16->dwSignature) != NDP16_SIGNATURE_NCM0) &&
411 	    (sys_le32_to_cpu(ndphdr16->dwSignature) != NDP16_SIGNATURE_NCM1)) {
412 		LOG_DBG("DROP: %s signature 0x%04x", "ndp16",
413 			(unsigned int)sys_le32_to_cpu(ndphdr16->dwSignature));
414 		return -EINVAL;
415 	}
416 
417 	if (sys_le16_to_cpu(ndphdr16->wNextNdpIndex) != 0) {
418 		LOG_DBG("DROP: wNextNdpIndex %d",
419 			sys_le16_to_cpu(ndphdr16->wNextNdpIndex));
420 		return -EINVAL;
421 	}
422 
423 	return 0;
424 }
425 
check_frame(struct cdc_ncm_eth_data * data,struct net_buf * const buf)426 static int check_frame(struct cdc_ncm_eth_data *data, struct net_buf *const buf)
427 {
428 	const union recv_ntb *ntb = (union recv_ntb *)buf->data;
429 	const struct nth16 *nthdr16 = &ntb->nth;
430 	uint16_t len = buf->len;
431 	int ndx = 0;
432 	const struct ndp16_datagram *ndp_datagram;
433 	const struct ndp16 *ndptr16;
434 	uint16_t max_ndx;
435 	int ret;
436 
437 	/* TODO: support nth32 */
438 	ret = verify_nth16(data, ntb, len);
439 	if (ret < 0) {
440 		LOG_ERR("Failed to verify NTH16");
441 		return ret;
442 	}
443 
444 	ndp_datagram = (const struct ndp16_datagram *)
445 		(ntb->data + sys_le16_to_cpu(nthdr16->wNdpIndex) +
446 		 sizeof(struct ndp16));
447 
448 	ndptr16 = (const struct ndp16 *)(ntb->data + sys_le16_to_cpu(nthdr16->wNdpIndex));
449 
450 	max_ndx = (uint16_t)((sys_le16_to_cpu(ndptr16->wLength) - sizeof(struct ndp16)) /
451 			     sizeof(struct ndp16_datagram));
452 
453 	if (max_ndx > (CDC_NCM_RECV_MAX_DATAGRAMS_PER_NTB + 1)) {
454 		LOG_DBG("DROP: dgram count %d (%d)", max_ndx - 1,
455 			sys_le16_to_cpu(ntb->nth.wBlockLength));
456 		return -EINVAL;
457 	}
458 
459 	if ((sys_le16_to_cpu(ndp_datagram[max_ndx-1].wDatagramIndex) != 0) ||
460 	    (sys_le16_to_cpu(ndp_datagram[max_ndx-1].wDatagramLength) != 0)) {
461 		LOG_DBG("DROP: max_ndx");
462 		return -EINVAL;
463 	}
464 
465 	while (sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex) != 0 &&
466 	       sys_le16_to_cpu(ndp_datagram[ndx].wDatagramLength) != 0) {
467 
468 		LOG_DBG("idx %d len %d",
469 			sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex),
470 			sys_le16_to_cpu(ndp_datagram[ndx].wDatagramLength));
471 
472 		if (sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex) > len) {
473 			LOG_DBG("DROP: %s datagram[%d] %d (%d)", "start",
474 				ndx,
475 				sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex),
476 				len);
477 			return -EINVAL;
478 		}
479 
480 		if (sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex) +
481 		    sys_le16_to_cpu(ndp_datagram[ndx].wDatagramLength) > len) {
482 			LOG_DBG("DROP: %s datagram[%d] %d (%d)", "stop",
483 				ndx,
484 				sys_le16_to_cpu(ndp_datagram[ndx].wDatagramIndex) +
485 				sys_le16_to_cpu(ndp_datagram[ndx].wDatagramLength),
486 				len);
487 			return -EINVAL;
488 		}
489 
490 		ndx++;
491 	}
492 
493 	if (DUMP_PKT) {
494 		LOG_HEXDUMP_DBG(ntb->data, len, "NTB");
495 	}
496 
497 	return 0;
498 }
499 
500 #define NET_PKT_ALLOC_TIMEOUT 100 /* ms */
501 
cdc_ncm_acl_out_cb(struct usbd_class_data * const c_data,struct net_buf * const buf,const int err)502 static int cdc_ncm_acl_out_cb(struct usbd_class_data *const c_data,
503 			      struct net_buf *const buf, const int err)
504 {
505 	const struct device *dev = usbd_class_get_private(c_data);
506 	const union recv_ntb *ntb = (union recv_ntb *)buf->data;
507 	struct cdc_ncm_eth_data *data = dev->data;
508 	const struct ndp16_datagram *ndp_datagram;
509 	const struct nth16 *nthdr16;
510 	const struct ndp16 *ndp;
511 	struct net_pkt *pkt, *src;
512 	uint16_t start, len;
513 	uint16_t count;
514 	int ret;
515 
516 	if (err || buf->len == 0) {
517 		if (err != -ECONNABORTED) {
518 			LOG_ERR("Bulk OUT transfer error (%d) or zero length", err);
519 		}
520 
521 		goto restart_out_transfer;
522 	}
523 
524 	ret = check_frame(data, buf);
525 	if (ret < 0) {
526 		LOG_ERR("check frame failed (%d)", ret);
527 		goto restart_out_transfer;
528 	}
529 
530 	/* Temporary source pkt we use to copy one Ethernet frame from
531 	 * the list of USB net_buf's.
532 	 */
533 	src = net_pkt_alloc(K_MSEC(NET_PKT_ALLOC_TIMEOUT));
534 	if (src == NULL) {
535 		LOG_ERR("src packet alloc fail");
536 		goto restart_out_transfer;
537 	}
538 
539 	net_pkt_append_buffer(src, buf);
540 	net_pkt_set_overwrite(src, true);
541 
542 	nthdr16 = &ntb->nth;
543 	LOG_DBG("NTH16: wSequence %u wBlockLength %u wNdpIndex %u",
544 		nthdr16->wSequence, nthdr16->wBlockLength, nthdr16->wNdpIndex);
545 
546 	/* NDP may be anywhere in the transfer buffer. Offsets, like wNdpIndex
547 	 * or wDatagramIndex are always of from byte zero of the NTB.
548 	 */
549 	ndp = (const struct ndp16 *)(ntb->data + sys_le16_to_cpu(nthdr16->wNdpIndex));
550 	LOG_DBG("NDP16: wLength %u", sys_le16_to_cpu(ndp->wLength));
551 
552 	ndp_datagram = (struct ndp16_datagram *)&ndp->datagram[0];
553 
554 	/* There is one (terminating zero) or more datagram pointer
555 	 * entries starting after 8 bytes of header information.
556 	 */
557 	count = (sys_le16_to_cpu(ndp->wLength) - 8U) / 4U;
558 	LOG_DBG("%u datagram%s received", count, count == 1 ? "" : "s");
559 
560 	for (int i = 0; i < count; i++) {
561 		start = sys_le16_to_cpu(ndp_datagram[i].wDatagramIndex);
562 		len = sys_le16_to_cpu(ndp_datagram[i].wDatagramLength);
563 
564 		LOG_DBG("[%d] start %u len %u", i, start, len);
565 		if (start == 0 || len == 0) {
566 			LOG_DBG("Terminating zero datagram %u", i);
567 			break;
568 		}
569 
570 		pkt = net_pkt_rx_alloc_with_buffer(data->iface, len, AF_UNSPEC, 0, K_FOREVER);
571 		if (!pkt) {
572 			LOG_ERR("No memory for net_pkt");
573 			goto unref_packet;
574 		}
575 
576 		net_pkt_cursor_init(src);
577 
578 		ret = net_pkt_skip(src, start);
579 		if (ret < 0) {
580 			LOG_ERR("Cannot advance pkt by %u bytes (%d)", start, ret);
581 			net_pkt_unref(pkt);
582 			goto unref_packet;
583 		}
584 
585 		ret = net_pkt_copy(pkt, src, len);
586 		if (ret < 0) {
587 			LOG_ERR("Cannot copy data (%d)", ret);
588 			net_pkt_unref(pkt);
589 			goto unref_packet;
590 		}
591 
592 		LOG_DBG("Received packet len %zu", net_pkt_get_len(pkt));
593 
594 		if (net_recv_data(data->iface, pkt) < 0) {
595 			LOG_ERR("Packet %p dropped by network stack", pkt);
596 			net_pkt_unref(pkt);
597 		}
598 	}
599 
600 unref_packet:
601 	src->buffer = NULL;
602 	net_pkt_unref(src);
603 
604 restart_out_transfer:
605 	net_buf_unref(buf);
606 
607 	atomic_clear_bit(&data->state, CDC_NCM_OUT_ENGAGED);
608 	if (atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED)) {
609 		return cdc_ncm_out_start(c_data);
610 	}
611 
612 	return 0;
613 }
614 
ncm_handle_notifications(const struct device * dev,const int err)615 static void ncm_handle_notifications(const struct device *dev, const int err)
616 {
617 	struct cdc_ncm_eth_data *data = dev->data;
618 
619 	if (err != 0) {
620 		LOG_WRN("Notification request %s",
621 			err == -ECONNABORTED ? "cancelled" : "failed");
622 		data->if_state = IF_STATE_INIT;
623 	}
624 
625 	if (data->if_state == IF_STATE_SPEED_CHANGE_SUBMITTED) {
626 		data->if_state = IF_STATE_SPEED_CHANGE_SENT;
627 		LOG_INF("Speed change sent");
628 		(void)k_work_reschedule(&data->notif_work, K_MSEC(1));
629 	}
630 
631 	if (data->if_state == IF_STATE_CONNECTION_STATUS_SUBMITTED) {
632 		data->if_state = IF_STATE_CONNECTION_STATUS_SENT;
633 		LOG_INF("Connection status sent");
634 	}
635 }
636 
usbd_cdc_ncm_request(struct usbd_class_data * const c_data,struct net_buf * buf,int err)637 static int usbd_cdc_ncm_request(struct usbd_class_data *const c_data,
638 				struct net_buf *buf, int err)
639 {
640 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
641 	const struct device *dev = usbd_class_get_private(c_data);
642 	struct cdc_ncm_eth_data *data = dev->data;
643 	struct udc_buf_info *bi;
644 
645 	bi = udc_get_buf_info(buf);
646 	LOG_DBG("finished %x len %u", bi->ep, buf->len);
647 
648 	if (bi->ep == cdc_ncm_get_bulk_out(c_data)) {
649 		return cdc_ncm_acl_out_cb(c_data, buf, err);
650 	}
651 
652 	if (bi->ep == cdc_ncm_get_bulk_in(c_data)) {
653 		k_sem_give(&data->sync_sem);
654 		return 0;
655 	}
656 
657 	if (bi->ep == cdc_ncm_get_int_in(c_data)) {
658 		ncm_handle_notifications(dev, err);
659 		net_buf_unref(buf);
660 		return 0;
661 	}
662 
663 	return usbd_ep_buf_free(uds_ctx, buf);
664 }
665 
cdc_ncm_send_notification(const struct device * dev,void * notification,size_t notification_size)666 static int cdc_ncm_send_notification(const struct device *dev,
667 				     void *notification, size_t notification_size)
668 {
669 	struct cdc_ncm_eth_data *data = dev->data;
670 	struct usbd_class_data *c_data = data->c_data;
671 	struct net_buf *buf;
672 	uint8_t ep;
673 	int ret;
674 
675 	if (!atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED)) {
676 		LOG_INF("USB configuration is not enabled");
677 		return -EBUSY;
678 	}
679 
680 	if (atomic_test_bit(&data->state, CDC_NCM_CLASS_SUSPENDED)) {
681 		LOG_INF("USB device is suspended (FIXME)");
682 		return -EBUSY;
683 	}
684 
685 	ep = cdc_ncm_get_int_in(c_data);
686 
687 	buf = usbd_ep_buf_alloc(c_data, ep, notification_size);
688 	if (buf == NULL) {
689 		return -ENOMEM;
690 	}
691 
692 	net_buf_add_mem(buf, notification, notification_size);
693 
694 	ret = usbd_ep_enqueue(c_data, buf);
695 	if (ret) {
696 		LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
697 		net_buf_unref(buf);
698 	}
699 
700 	return ret;
701 }
702 
cdc_ncm_send_connected(const struct device * dev,const bool connected)703 static int cdc_ncm_send_connected(const struct device *dev,
704 				  const bool connected)
705 {
706 	struct cdc_ncm_eth_data *data = dev->data;
707 	struct cdc_ncm_notification notify_connection = {
708 		.RequestType = {
709 			.direction = USB_REQTYPE_DIR_TO_HOST,
710 			.type = USB_REQTYPE_TYPE_CLASS,
711 			.recipient = USB_REQTYPE_RECIPIENT_INTERFACE,
712 		},
713 		.bNotificationType = USB_CDC_NETWORK_CONNECTION,
714 		.wValue = sys_cpu_to_le16((uint16_t)connected),
715 		.wIndex = sys_cpu_to_le16(cdc_ncm_get_ctrl_if(data)),
716 		.wLength = 0,
717 	};
718 	int ret;
719 
720 	ret = cdc_ncm_send_notification(dev, &notify_connection,
721 					sizeof(notify_connection));
722 	if (ret < 0) {
723 		LOG_DBG("Cannot send %s (%d)",
724 			connected ? "connected" : "disconnected", ret);
725 	}
726 
727 	return ret;
728 }
729 
cdc_ncm_send_speed_change(const struct device * dev)730 static int cdc_ncm_send_speed_change(const struct device *dev)
731 {
732 	struct cdc_ncm_eth_data *data = dev->data;
733 	struct usbd_class_data *c_data = data->c_data;
734 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
735 	uint32_t usb_speed = (usbd_bus_speed(uds_ctx) == USBD_SPEED_FS) ?
736 		NCM_USB_SPEED_FS : NCM_USB_SPEED_HS;
737 	struct ncm_notify_connection_speed_change notify_speed_change = {
738 		.header = {
739 			.RequestType = {
740 				.recipient = USB_REQTYPE_RECIPIENT_INTERFACE,
741 				.type      = USB_REQTYPE_TYPE_CLASS,
742 				.direction = USB_REQTYPE_DIR_TO_HOST
743 			},
744 			.bRequest = CONNECTION_SPEED_CHANGE,
745 			.wLength  = sys_cpu_to_le16(8),
746 			.wIndex = sys_cpu_to_le16(cdc_ncm_get_ctrl_if(data)),
747 		},
748 		.downlink = sys_cpu_to_le32(usb_speed),
749 		.uplink   = sys_cpu_to_le32(usb_speed),
750 	};
751 	int ret;
752 
753 	ret = cdc_ncm_send_notification(dev,
754 					&notify_speed_change,
755 					sizeof(notify_speed_change));
756 	if (ret < 0) {
757 		LOG_DBG("Cannot send %s (%d)", "speed change", ret);
758 		return ret;
759 	}
760 
761 	return ret;
762 }
763 
764 
ncm_send_notification_sequence(const struct device * dev)765 static int ncm_send_notification_sequence(const struct device *dev)
766 {
767 	struct cdc_ncm_eth_data *data = dev->data;
768 	int ret;
769 
770 	/* Speed change must be sent first, chapter 7.1 */
771 	if (data->if_state == IF_STATE_INIT) {
772 		ret = cdc_ncm_send_speed_change(dev);
773 		if (ret < 0) {
774 			LOG_INF("Cannot send %s (%d)", "speed change", ret);
775 			return ret;
776 		}
777 
778 		LOG_INF("Speed change submitted");
779 		data->if_state = IF_STATE_SPEED_CHANGE_SUBMITTED;
780 		return -EAGAIN;
781 	}
782 
783 	if (data->if_state == IF_STATE_SPEED_CHANGE_SENT) {
784 		ret = cdc_ncm_send_connected(dev, true);
785 		if (ret < 0) {
786 			LOG_INF("Cannot send %s (%d)", "connected status", ret);
787 			return ret;
788 		}
789 
790 		LOG_INF("Connected status submitted");
791 		data->if_state = IF_STATE_CONNECTION_STATUS_SUBMITTED;
792 		return -EAGAIN;
793 	}
794 
795 	if (data->if_state == IF_STATE_CONNECTION_STATUS_SENT) {
796 		LOG_INF("Connected status done");
797 		data->if_state = IF_STATE_DONE;
798 	}
799 
800 	return 0;
801 }
802 
send_notification_work(struct k_work * work)803 static void send_notification_work(struct k_work *work)
804 {
805 	struct k_work_delayable *notif_work = k_work_delayable_from_work(work);
806 	struct cdc_ncm_eth_data *data;
807 	struct device *dev;
808 	int ret;
809 
810 	data = CONTAINER_OF(notif_work, struct cdc_ncm_eth_data, notif_work);
811 	dev = usbd_class_get_private(data->c_data);
812 
813 	if (atomic_test_bit(&data->state, CDC_NCM_IFACE_UP)) {
814 		ret = ncm_send_notification_sequence(dev);
815 	} else {
816 		data->if_state = IF_STATE_INIT;
817 		ret = cdc_ncm_send_connected(dev, false);
818 	}
819 
820 	if (ret) {
821 		(void)k_work_reschedule(&data->notif_work, K_MSEC(100));
822 	}
823 }
824 
usbd_cdc_ncm_update(struct usbd_class_data * const c_data,const uint8_t iface,const uint8_t alternate)825 static void usbd_cdc_ncm_update(struct usbd_class_data *const c_data,
826 				const uint8_t iface, const uint8_t alternate)
827 {
828 	const struct device *dev = usbd_class_get_private(c_data);
829 	struct cdc_ncm_eth_data *data = dev->data;
830 	struct usbd_cdc_ncm_desc *desc = data->desc;
831 	uint8_t data_iface = desc->if1_1.bInterfaceNumber;
832 	int ret;
833 
834 	LOG_INF("New configuration, interface %u alternate %u",
835 		iface, alternate);
836 
837 	if (data_iface == iface && alternate == 0) {
838 		atomic_clear_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED);
839 		data->tx_seq = 0;
840 		data->rx_seq = 0;
841 	}
842 
843 	if (data_iface == iface && alternate == 1) {
844 		atomic_set_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED);
845 		data->if_state = IF_STATE_INIT;
846 		(void)k_work_reschedule(&data->notif_work, K_MSEC(100));
847 		ret = cdc_ncm_out_start(c_data);
848 		if (ret < 0) {
849 			LOG_ERR("Failed to start OUT transfer (%d)", ret);
850 		}
851 	}
852 }
853 
usbd_cdc_ncm_enable(struct usbd_class_data * const c_data)854 static void usbd_cdc_ncm_enable(struct usbd_class_data *const c_data)
855 {
856 	LOG_INF("Enabled %s", c_data->name);
857 }
858 
usbd_cdc_ncm_disable(struct usbd_class_data * const c_data)859 static void usbd_cdc_ncm_disable(struct usbd_class_data *const c_data)
860 {
861 	const struct device *dev = usbd_class_get_private(c_data);
862 	struct cdc_ncm_eth_data *data = dev->data;
863 
864 	atomic_clear_bit(&data->state, CDC_NCM_CLASS_SUSPENDED);
865 
866 	LOG_INF("Disabled %s", c_data->name);
867 }
868 
usbd_cdc_ncm_suspended(struct usbd_class_data * const c_data)869 static void usbd_cdc_ncm_suspended(struct usbd_class_data *const c_data)
870 {
871 	const struct device *dev = usbd_class_get_private(c_data);
872 	struct cdc_ncm_eth_data *data = dev->data;
873 
874 	atomic_set_bit(&data->state, CDC_NCM_CLASS_SUSPENDED);
875 }
876 
usbd_cdc_ncm_resumed(struct usbd_class_data * const c_data)877 static void usbd_cdc_ncm_resumed(struct usbd_class_data *const c_data)
878 {
879 	const struct device *dev = usbd_class_get_private(c_data);
880 	struct cdc_ncm_eth_data *data = dev->data;
881 
882 	atomic_clear_bit(&data->state, CDC_NCM_CLASS_SUSPENDED);
883 }
884 
usbd_cdc_ncm_ctd(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,const struct net_buf * const buf)885 static int usbd_cdc_ncm_ctd(struct usbd_class_data *const c_data,
886 			    const struct usb_setup_packet *const setup,
887 			    const struct net_buf *const buf)
888 {
889 	if (setup->RequestType.recipient == USB_REQTYPE_RECIPIENT_INTERFACE) {
890 		if (setup->bRequest == SET_ETHERNET_PACKET_FILTER) {
891 			LOG_DBG("bRequest 0x%02x (%s) not implemented",
892 				setup->bRequest, "SetPacketFilter");
893 			return 0;
894 		}
895 
896 		if (setup->bRequest == SET_NTB_INPUT_SIZE) {
897 			LOG_DBG("bRequest 0x%02x (%s) not implemented",
898 				setup->bRequest, "SetNtbInputSize");
899 			return 0;
900 		}
901 
902 		if (setup->bRequest == SET_NTB_FORMAT) {
903 			LOG_DBG("bRequest 0x%02x (%s) not implemented",
904 				setup->bRequest, "SetNtbFormat");
905 			return 0;
906 		}
907 	}
908 
909 	LOG_DBG("bmRequestType 0x%02x bRequest 0x%02x unsupported",
910 		setup->bmRequestType, setup->bRequest);
911 	errno = -ENOTSUP;
912 
913 	return 0;
914 }
915 
usbd_cdc_ncm_cth(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,struct net_buf * const buf)916 static int usbd_cdc_ncm_cth(struct usbd_class_data *const c_data,
917 			    const struct usb_setup_packet *const setup,
918 			    struct net_buf *const buf)
919 {
920 	LOG_DBG("%d: %d %d %d %d", setup->RequestType.type, setup->bRequest,
921 		setup->wLength, setup->wIndex, setup->wValue);
922 
923 	if (setup->RequestType.type != USB_REQTYPE_TYPE_CLASS) {
924 		errno = ENOTSUP;
925 		goto out;
926 	}
927 
928 	switch (setup->bRequest) {
929 	case GET_NTB_PARAMETERS: {
930 		struct ntb_parameters ntb_params = {
931 			.wLength = sys_cpu_to_le16(sizeof(struct ntb_parameters)),
932 			.bmNtbFormatsSupported = sys_cpu_to_le16(NTB_FORMAT_SUPPORTED),
933 			.dwNtbInMaxSize = sys_cpu_to_le32(CDC_NCM_SEND_NTB_MAX_SIZE),
934 			.wNdbInDivisor = sys_cpu_to_le16(4),
935 			.wNdbInPayloadRemainder = sys_cpu_to_le16(0),
936 			.wNdbInAlignment = sys_cpu_to_le16(CDC_NCM_ALIGNMENT),
937 			.wReserved = sys_cpu_to_le16(0),
938 			.dwNtbOutMaxSize = sys_cpu_to_le32(CDC_NCM_RECV_NTB_MAX_SIZE),
939 			.wNdbOutDivisor = sys_cpu_to_le16(4),
940 			.wNdbOutPayloadRemainder = sys_cpu_to_le16(0),
941 			.wNdbOutAlignment = sys_cpu_to_le16(CDC_NCM_ALIGNMENT),
942 			.wNtbOutMaxDatagrams = sys_cpu_to_le16(CDC_NCM_RECV_MAX_DATAGRAMS_PER_NTB),
943 		};
944 
945 		LOG_DBG("GET_NTB_PARAMETERS");
946 		net_buf_add_mem(buf, &ntb_params, sizeof(ntb_params));
947 		break;
948 	}
949 
950 	case GET_NTB_INPUT_SIZE: {
951 		struct ntb_input_size input_size = {
952 			.dwNtbInMaxSize = sys_cpu_to_le32(CDC_NCM_SEND_NTB_MAX_SIZE),
953 			.wNtbInMaxDatagrams = sys_cpu_to_le16(CDC_NCM_SEND_MAX_DATAGRAMS_PER_NTB),
954 			.wReserved = sys_cpu_to_le16(0),
955 		};
956 
957 		LOG_DBG("GET_NTB_INPUT_SIZE");
958 		net_buf_add_mem(buf, &input_size, sizeof(input_size));
959 		break;
960 	}
961 
962 	default:
963 		LOG_DBG("bRequest 0x%02x not supported", setup->bRequest);
964 		errno = ENOTSUP;
965 		break;
966 	}
967 
968 out:
969 	return 0;
970 }
971 
usbd_cdc_ncm_init(struct usbd_class_data * const c_data)972 static int usbd_cdc_ncm_init(struct usbd_class_data *const c_data)
973 {
974 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
975 	const struct device *dev = usbd_class_get_private(c_data);
976 	struct cdc_ncm_eth_data *const data = dev->data;
977 	struct usbd_cdc_ncm_desc *desc = data->desc;
978 	uint8_t if_num = desc->if0.bInterfaceNumber;
979 
980 	/* Update relevant b*Interface fields */
981 	desc->iad.bFirstInterface = if_num;
982 	desc->if0_union.bControlInterface = if_num;
983 	desc->if0_union.bSubordinateInterface0 = if_num + 1;
984 
985 	LOG_DBG("CDC NCM class initialized");
986 
987 	if (usbd_add_descriptor(uds_ctx, data->mac_desc_data)) {
988 		LOG_ERR("Failed to add iMACAddress string descriptor");
989 	} else {
990 		desc->if0_ecm.iMACAddress = usbd_str_desc_get_idx(data->mac_desc_data);
991 	}
992 
993 	return 0;
994 }
995 
usbd_cdc_ncm_shutdown(struct usbd_class_data * const c_data)996 static void usbd_cdc_ncm_shutdown(struct usbd_class_data *const c_data)
997 {
998 	const struct device *dev = usbd_class_get_private(c_data);
999 	struct cdc_ncm_eth_data *const data = dev->data;
1000 	struct usbd_cdc_ncm_desc *desc = data->desc;
1001 
1002 	desc->if0_ecm.iMACAddress = 0;
1003 	sys_dlist_remove(&data->mac_desc_data->node);
1004 }
1005 
usbd_cdc_ncm_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)1006 static void *usbd_cdc_ncm_get_desc(struct usbd_class_data *const c_data,
1007 				   const enum usbd_speed speed)
1008 {
1009 	const struct device *dev = usbd_class_get_private(c_data);
1010 	struct cdc_ncm_eth_data *const data = dev->data;
1011 
1012 	if (speed == USBD_SPEED_HS) {
1013 		return data->hs_desc;
1014 	}
1015 
1016 	return data->fs_desc;
1017 }
1018 
cdc_ncm_send(const struct device * dev,struct net_pkt * const pkt)1019 static int cdc_ncm_send(const struct device *dev, struct net_pkt *const pkt)
1020 {
1021 	struct cdc_ncm_eth_data *const data = dev->data;
1022 	struct usbd_class_data *c_data = data->c_data;
1023 	size_t len = net_pkt_get_len(pkt);
1024 	struct net_buf *buf;
1025 	union send_ntb *ntb;
1026 
1027 	if (len > NET_ETH_MAX_FRAME_SIZE) {
1028 		LOG_WRN("Trying to send too large packet, drop");
1029 		return -ENOMEM;
1030 	}
1031 
1032 	if (!atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED) ||
1033 	    !atomic_test_bit(&data->state, CDC_NCM_IFACE_UP)) {
1034 		LOG_DBG("Configuration is not enabled or interface not ready (%d / %d)",
1035 			atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED),
1036 			atomic_test_bit(&data->state, CDC_NCM_IFACE_UP));
1037 		return -EACCES;
1038 	}
1039 
1040 	buf = cdc_ncm_buf_alloc(cdc_ncm_get_bulk_in(c_data));
1041 	if (buf == NULL) {
1042 		LOG_ERR("Failed to allocate buffer");
1043 		return -ENOMEM;
1044 	}
1045 
1046 	ntb = (union send_ntb *)buf->data;
1047 
1048 	ntb->nth.dwSignature = sys_cpu_to_le32(NTH16_SIGNATURE);
1049 	ntb->nth.wHeaderLength = sys_cpu_to_le16(sizeof(struct nth16));
1050 	ntb->nth.wSequence = sys_cpu_to_le16(++data->tx_seq);
1051 	ntb->nth.wNdpIndex = sys_cpu_to_le16(sizeof(struct nth16));
1052 	ntb->ndp.dwSignature = sys_cpu_to_le32(NDP16_SIGNATURE_NCM0);
1053 	ntb->ndp.wLength = sys_cpu_to_le16(sizeof(struct ndp16) +
1054 					   (CDC_NCM_SEND_MAX_DATAGRAMS_PER_NTB + 1) *
1055 					   sizeof(struct ndp16_datagram));
1056 	ntb->ndp.wNextNdpIndex = 0;
1057 	ntb->ndp_datagram[0].wDatagramIndex =
1058 		sys_cpu_to_le16(sys_le16_to_cpu(ntb->nth.wHeaderLength) +
1059 				sys_le16_to_cpu(ntb->ndp.wLength));
1060 	ntb->ndp_datagram[0].wDatagramLength = sys_cpu_to_le16(len);
1061 	ntb->ndp_datagram[1].wDatagramIndex  = 0;
1062 	ntb->ndp_datagram[1].wDatagramLength = 0;
1063 	ntb->nth.wBlockLength = sys_cpu_to_le16(
1064 		sys_le16_to_cpu(ntb->ndp_datagram[0].wDatagramIndex) + len);
1065 
1066 	net_buf_add(buf, sys_le16_to_cpu(ntb->ndp_datagram[0].wDatagramIndex));
1067 
1068 	if (net_pkt_read(pkt, buf->data + buf->len, len)) {
1069 		LOG_ERR("Failed copy net_pkt");
1070 		net_buf_unref(buf);
1071 
1072 		return -ENOBUFS;
1073 	}
1074 
1075 	net_buf_add(buf, len);
1076 
1077 	if (sys_le16_to_cpu(ntb->nth.wBlockLength) % cdc_ncm_get_bulk_in_mps(c_data) == 0) {
1078 		udc_ep_buf_set_zlp(buf);
1079 	}
1080 
1081 	usbd_ep_enqueue(c_data, buf);
1082 	k_sem_take(&data->sync_sem, K_FOREVER);
1083 
1084 	net_buf_unref(buf);
1085 
1086 	return 0;
1087 }
1088 
cdc_ncm_set_config(const struct device * dev,const enum ethernet_config_type type,const struct ethernet_config * config)1089 static int cdc_ncm_set_config(const struct device *dev,
1090 			      const enum ethernet_config_type type,
1091 			      const struct ethernet_config *config)
1092 {
1093 	struct cdc_ncm_eth_data *data = dev->data;
1094 
1095 	if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
1096 		memcpy(data->mac_addr, config->mac_address.addr,
1097 		       sizeof(data->mac_addr));
1098 
1099 		return 0;
1100 	}
1101 
1102 	return -ENOTSUP;
1103 }
1104 
cdc_ncm_get_capabilities(const struct device * dev)1105 static enum ethernet_hw_caps cdc_ncm_get_capabilities(const struct device *dev)
1106 {
1107 	ARG_UNUSED(dev);
1108 
1109 	return ETHERNET_LINK_10BASE_T;
1110 }
1111 
cdc_ncm_iface_start(const struct device * dev)1112 static int cdc_ncm_iface_start(const struct device *dev)
1113 {
1114 	struct cdc_ncm_eth_data *data = dev->data;
1115 
1116 	LOG_DBG("Start interface %d", net_if_get_by_iface(data->iface));
1117 
1118 	atomic_set_bit(&data->state, CDC_NCM_IFACE_UP);
1119 	net_if_carrier_on(data->iface);
1120 
1121 	if (atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED)) {
1122 		(void)k_work_reschedule(&data->notif_work, K_MSEC(1));
1123 	}
1124 
1125 	return 0;
1126 }
1127 
cdc_ncm_iface_stop(const struct device * dev)1128 static int cdc_ncm_iface_stop(const struct device *dev)
1129 {
1130 	struct cdc_ncm_eth_data *data = dev->data;
1131 
1132 	LOG_DBG("Stop interface %d", net_if_get_by_iface(data->iface));
1133 
1134 	atomic_clear_bit(&data->state, CDC_NCM_IFACE_UP);
1135 
1136 	if (atomic_test_bit(&data->state, CDC_NCM_DATA_IFACE_ENABLED)) {
1137 		(void)k_work_reschedule(&data->notif_work, K_MSEC(1));
1138 	}
1139 
1140 	return 0;
1141 }
1142 
cdc_ncm_iface_init(struct net_if * const iface)1143 static void cdc_ncm_iface_init(struct net_if *const iface)
1144 {
1145 	const struct device *dev = net_if_get_device(iface);
1146 	struct cdc_ncm_eth_data *data = dev->data;
1147 
1148 	data->iface = iface;
1149 	ethernet_init(iface);
1150 	net_if_set_link_addr(iface, data->mac_addr,
1151 			     sizeof(data->mac_addr),
1152 			     NET_LINK_ETHERNET);
1153 
1154 	net_if_carrier_off(iface);
1155 
1156 	LOG_DBG("CDC NCM interface initialized");
1157 }
1158 
usbd_cdc_ncm_preinit(const struct device * dev)1159 static int usbd_cdc_ncm_preinit(const struct device *dev)
1160 {
1161 	struct cdc_ncm_eth_data *data = dev->data;
1162 
1163 	k_work_init_delayable(&data->notif_work, send_notification_work);
1164 
1165 	if (sys_get_le48(data->mac_addr) == sys_cpu_to_le48(0)) {
1166 		gen_random_mac(data->mac_addr, 0, 0, 0);
1167 	}
1168 
1169 	LOG_DBG("CDC NCM device initialized");
1170 
1171 	return 0;
1172 }
1173 
1174 static struct usbd_class_api usbd_cdc_ncm_api = {
1175 	.request = usbd_cdc_ncm_request,
1176 	.update = usbd_cdc_ncm_update,
1177 	.enable = usbd_cdc_ncm_enable,
1178 	.disable = usbd_cdc_ncm_disable,
1179 	.suspended = usbd_cdc_ncm_suspended,
1180 	.resumed = usbd_cdc_ncm_resumed,
1181 	.control_to_dev = usbd_cdc_ncm_ctd,
1182 	.control_to_host = usbd_cdc_ncm_cth,
1183 	.init = usbd_cdc_ncm_init,
1184 	.shutdown = usbd_cdc_ncm_shutdown,
1185 	.get_desc = usbd_cdc_ncm_get_desc,
1186 };
1187 
1188 static const struct ethernet_api cdc_ncm_eth_api = {
1189 	.iface_api.init = cdc_ncm_iface_init,
1190 	.set_config = cdc_ncm_set_config,
1191 	.get_capabilities = cdc_ncm_get_capabilities,
1192 	.send = cdc_ncm_send,
1193 	.start = cdc_ncm_iface_start,
1194 	.stop = cdc_ncm_iface_stop,
1195 };
1196 
1197 #define CDC_NCM_DEFINE_DESCRIPTOR(n)						\
1198 static struct usbd_cdc_ncm_desc cdc_ncm_desc_##n = {				\
1199 	.iad = {								\
1200 		.bLength = sizeof(struct usb_association_descriptor),		\
1201 		.bDescriptorType = USB_DESC_INTERFACE_ASSOC,			\
1202 		.bFirstInterface = 0,						\
1203 		.bInterfaceCount = 0x02,					\
1204 		.bFunctionClass = USB_BCC_CDC_CONTROL,				\
1205 		.bFunctionSubClass = NCM_SUBCLASS,				\
1206 		.bFunctionProtocol = 0,						\
1207 		.iFunction = 0,							\
1208 	},									\
1209 										\
1210 	.if0 = {								\
1211 		.bLength = sizeof(struct usb_if_descriptor),			\
1212 		.bDescriptorType = USB_DESC_INTERFACE,				\
1213 		.bInterfaceNumber = 0,						\
1214 		.bAlternateSetting = 0,						\
1215 		.bNumEndpoints = 1,						\
1216 		.bInterfaceClass = USB_BCC_CDC_CONTROL,				\
1217 		.bInterfaceSubClass = NCM_SUBCLASS,				\
1218 		.bInterfaceProtocol = 0,					\
1219 		.iInterface = 0,						\
1220 	},									\
1221 										\
1222 	.if0_header = {								\
1223 		.bFunctionLength = sizeof(struct cdc_header_descriptor),	\
1224 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
1225 		.bDescriptorSubtype = HEADER_FUNC_DESC,				\
1226 		.bcdCDC = sys_cpu_to_le16(USB_SRN_1_1),				\
1227 	},									\
1228 										\
1229 	.if0_union = {								\
1230 		.bFunctionLength = sizeof(struct cdc_union_descriptor),		\
1231 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
1232 		.bDescriptorSubtype = UNION_FUNC_DESC,				\
1233 		.bControlInterface = 0,						\
1234 		.bSubordinateInterface0 = 1,					\
1235 	},									\
1236 										\
1237 	.if0_ecm = {								\
1238 		.bFunctionLength = sizeof(struct cdc_ecm_descriptor),		\
1239 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
1240 		.bDescriptorSubtype = ETHERNET_FUNC_DESC,			\
1241 		.iMACAddress = 4,						\
1242 		.bmEthernetStatistics = sys_cpu_to_le32(0),			\
1243 		.wMaxSegmentSize = sys_cpu_to_le16(NET_ETH_MAX_FRAME_SIZE),	\
1244 		.wNumberMCFilters = sys_cpu_to_le16(0),				\
1245 		.bNumberPowerFilters = 0,					\
1246 	},									\
1247 										\
1248 	.if0_ncm = {								\
1249 		.bFunctionLength = sizeof(struct cdc_ncm_descriptor),		\
1250 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
1251 		.bDescriptorSubtype = ETHERNET_FUNC_DESC_NCM,			\
1252 		.bcdNcmVersion = sys_cpu_to_le16(0x100),			\
1253 		.bmNetworkCapabilities = 0,					\
1254 	},									\
1255 										\
1256 	.if0_int_ep = {								\
1257 		.bLength = sizeof(struct usb_ep_descriptor),			\
1258 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1259 		.bEndpointAddress = 0x81,					\
1260 		.bmAttributes = USB_EP_TYPE_INTERRUPT,				\
1261 		.wMaxPacketSize = sys_cpu_to_le16(CDC_NCM_EP_MPS_INT),		\
1262 		.bInterval = CDC_NCM_FS_INT_EP_INTERVAL,			\
1263 	},									\
1264 										\
1265 	.if0_hs_int_ep = {							\
1266 		.bLength = sizeof(struct usb_ep_descriptor),			\
1267 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1268 		.bEndpointAddress = 0x82,					\
1269 		.bmAttributes = USB_EP_TYPE_INTERRUPT,				\
1270 		.wMaxPacketSize = sys_cpu_to_le16(CDC_NCM_EP_MPS_INT),		\
1271 		.bInterval = CDC_NCM_HS_INT_EP_INTERVAL,			\
1272 	},									\
1273 										\
1274 	.if1_0 = {								\
1275 		.bLength = sizeof(struct usb_if_descriptor),			\
1276 		.bDescriptorType = USB_DESC_INTERFACE,				\
1277 		.bInterfaceNumber = 1,						\
1278 		.bAlternateSetting = 0,						\
1279 		.bNumEndpoints = 0,						\
1280 		.bInterfaceClass = USB_BCC_CDC_DATA,				\
1281 		.bInterfaceSubClass = 0,					\
1282 		.bInterfaceProtocol = NCM_DATA_PROTOCOL,			\
1283 		.iInterface = 0,						\
1284 	},									\
1285 										\
1286 	.if1_1 = {								\
1287 		.bLength = sizeof(struct usb_if_descriptor),			\
1288 		.bDescriptorType = USB_DESC_INTERFACE,				\
1289 		.bInterfaceNumber = 1,						\
1290 		.bAlternateSetting = 1,						\
1291 		.bNumEndpoints = 2,						\
1292 		.bInterfaceClass = USB_BCC_CDC_DATA,				\
1293 		.bInterfaceSubClass = 0,					\
1294 		.bInterfaceProtocol = NCM_DATA_PROTOCOL,			\
1295 		.iInterface = 0,						\
1296 	},									\
1297 										\
1298 	.if1_1_in_ep = {							\
1299 		.bLength = sizeof(struct usb_ep_descriptor),			\
1300 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1301 		.bEndpointAddress = 0x81,					\
1302 		.bmAttributes = USB_EP_TYPE_BULK,				\
1303 		.wMaxPacketSize = sys_cpu_to_le16(64U),				\
1304 		.bInterval = 0,							\
1305 	},									\
1306 										\
1307 	.if1_1_out_ep = {							\
1308 		.bLength = sizeof(struct usb_ep_descriptor),			\
1309 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1310 		.bEndpointAddress = 0x01,					\
1311 		.bmAttributes = USB_EP_TYPE_BULK,				\
1312 		.wMaxPacketSize = sys_cpu_to_le16(64U),				\
1313 		.bInterval = 0,							\
1314 	},									\
1315 										\
1316 	.if1_1_hs_in_ep = {							\
1317 		.bLength = sizeof(struct usb_ep_descriptor),			\
1318 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1319 		.bEndpointAddress = 0x82,					\
1320 		.bmAttributes = USB_EP_TYPE_BULK,				\
1321 		.wMaxPacketSize = sys_cpu_to_le16(512U),			\
1322 		.bInterval = 0,							\
1323 	},									\
1324 										\
1325 	.if1_1_hs_out_ep = {							\
1326 		.bLength = sizeof(struct usb_ep_descriptor),			\
1327 		.bDescriptorType = USB_DESC_ENDPOINT,				\
1328 		.bEndpointAddress = 0x02,					\
1329 		.bmAttributes = USB_EP_TYPE_BULK,				\
1330 		.wMaxPacketSize = sys_cpu_to_le16(512U),			\
1331 		.bInterval = 0,							\
1332 	},									\
1333 										\
1334 	.nil_desc = {								\
1335 		.bLength = 0,							\
1336 		.bDescriptorType = 0,						\
1337 	},									\
1338 };										\
1339 										\
1340 const static struct usb_desc_header *cdc_ncm_fs_desc_##n[] = {			\
1341 	(struct usb_desc_header *) &cdc_ncm_desc_##n.iad,			\
1342 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0,			\
1343 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_header,		\
1344 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_union,			\
1345 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_ecm,			\
1346 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_ncm,			\
1347 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_int_ep,		\
1348 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_0,			\
1349 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1,			\
1350 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1_in_ep,		\
1351 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1_out_ep,		\
1352 	(struct usb_desc_header *) &cdc_ncm_desc_##n.nil_desc,			\
1353 };										\
1354 										\
1355 const static struct usb_desc_header *cdc_ncm_hs_desc_##n[] = {			\
1356 	(struct usb_desc_header *) &cdc_ncm_desc_##n.iad,			\
1357 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0,			\
1358 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_header,		\
1359 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_union,			\
1360 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_ecm,			\
1361 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_ncm,			\
1362 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if0_hs_int_ep,		\
1363 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_0,			\
1364 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1,			\
1365 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1_hs_in_ep,		\
1366 	(struct usb_desc_header *) &cdc_ncm_desc_##n.if1_1_hs_out_ep,		\
1367 	(struct usb_desc_header *) &cdc_ncm_desc_##n.nil_desc,			\
1368 }
1369 
1370 #define USBD_CDC_NCM_DT_DEVICE_DEFINE(n)					\
1371 	CDC_NCM_DEFINE_DESCRIPTOR(n);						\
1372 	USBD_DESC_STRING_DEFINE(mac_desc_data_##n,				\
1373 				DT_INST_PROP(n, remote_mac_address),		\
1374 				USBD_DUT_STRING_INTERFACE);			\
1375 										\
1376 	USBD_DEFINE_CLASS(cdc_ncm_##n,						\
1377 			  &usbd_cdc_ncm_api,					\
1378 			  (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL);		\
1379 										\
1380 	static struct cdc_ncm_eth_data eth_data_##n = {				\
1381 		.c_data = &cdc_ncm_##n,						\
1382 		.mac_addr = DT_INST_PROP_OR(n, local_mac_address, {0}),		\
1383 		.sync_sem = Z_SEM_INITIALIZER(eth_data_##n.sync_sem, 0, 1),	\
1384 		.mac_desc_data = &mac_desc_data_##n,				\
1385 		.desc = &cdc_ncm_desc_##n,					\
1386 		.fs_desc = cdc_ncm_fs_desc_##n,					\
1387 		.hs_desc = cdc_ncm_hs_desc_##n,					\
1388 	};									\
1389 										\
1390 	ETH_NET_DEVICE_DT_INST_DEFINE(n, usbd_cdc_ncm_preinit, NULL,		\
1391 		&eth_data_##n, NULL,						\
1392 		CONFIG_ETH_INIT_PRIORITY,					\
1393 		&cdc_ncm_eth_api,						\
1394 		NET_ETH_MTU);
1395 
1396 DT_INST_FOREACH_STATUS_OKAY(USBD_CDC_NCM_DT_DEVICE_DEFINE);
1397