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