1 /*
2  * Copyright (c) 2017 Intel Corporation
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT zephyr_cdc_ecm_ethernet
9 
10 #include <zephyr/net/net_pkt.h>
11 #include <zephyr/net/ethernet.h>
12 
13 #include <eth.h>
14 
15 #include <zephyr/usb/usbd.h>
16 #include <zephyr/usb/usb_ch9.h>
17 #include <zephyr/usb/class/usb_cdc.h>
18 #include <zephyr/drivers/usb/udc.h>
19 
20 #include <zephyr/logging/log.h>
21 LOG_MODULE_REGISTER(cdc_ecm, CONFIG_USBD_CDC_ECM_LOG_LEVEL);
22 
23 #define CDC_ECM_EP_MPS_INT		16
24 #define CDC_ECM_INTERVAL_DEFAULT	10000UL
25 #define CDC_ECM_FS_INT_EP_INTERVAL	USB_FS_INT_EP_INTERVAL(10000U)
26 #define CDC_ECM_HS_INT_EP_INTERVAL	USB_HS_INT_EP_INTERVAL(10000U)
27 
28 enum {
29 	CDC_ECM_IFACE_UP,
30 	CDC_ECM_DATA_IFACE_ENABLED,
31 	CDC_ECM_CLASS_SUSPENDED,
32 	CDC_ECM_OUT_ENGAGED,
33 };
34 
35 /*
36  * Transfers through two endpoints proceed in a synchronous manner,
37  * with maximum block of NET_ETH_MAX_FRAME_SIZE.
38  */
39 UDC_BUF_POOL_DEFINE(cdc_ecm_ep_pool,
40 		    DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 2,
41 		    NET_ETH_MAX_FRAME_SIZE,
42 		    sizeof(struct udc_buf_info), NULL);
43 
44 struct cdc_ecm_notification {
45 	union {
46 		uint8_t bmRequestType;
47 		struct usb_req_type_field RequestType;
48 	};
49 	uint8_t bNotificationType;
50 	uint16_t wValue;
51 	uint16_t wIndex;
52 	uint16_t wLength;
53 } __packed;
54 
55 /*
56  * Collection of descriptors used to assemble specific function descriptors.
57  * This structure is used by CDC ECM implementation to update and fetch
58  * properties at runtime. We currently support full and high speed.
59  */
60 struct usbd_cdc_ecm_desc {
61 	struct usb_association_descriptor iad;
62 
63 	struct usb_if_descriptor if0;
64 	struct cdc_header_descriptor if0_header;
65 	struct cdc_union_descriptor if0_union;
66 	struct cdc_ecm_descriptor if0_ecm;
67 	struct usb_ep_descriptor if0_int_ep;
68 	struct usb_ep_descriptor if0_hs_int_ep;
69 
70 	struct usb_if_descriptor if1_0;
71 
72 	struct usb_if_descriptor if1_1;
73 	struct usb_ep_descriptor if1_1_in_ep;
74 	struct usb_ep_descriptor if1_1_out_ep;
75 	struct usb_ep_descriptor if1_1_hs_in_ep;
76 	struct usb_ep_descriptor if1_1_hs_out_ep;
77 
78 	struct usb_desc_header nil_desc;
79 };
80 
81 struct cdc_ecm_eth_data {
82 	struct usbd_class_data *c_data;
83 	struct usbd_desc_node *const mac_desc_data;
84 	struct usbd_cdc_ecm_desc *const desc;
85 	const struct usb_desc_header **const fs_desc;
86 	const struct usb_desc_header **const hs_desc;
87 
88 	struct net_if *iface;
89 	uint8_t mac_addr[6];
90 
91 	struct k_sem sync_sem;
92 	atomic_t state;
93 };
94 
cdc_ecm_get_ctrl_if(struct cdc_ecm_eth_data * const data)95 static uint8_t cdc_ecm_get_ctrl_if(struct cdc_ecm_eth_data *const data)
96 {
97 	struct usbd_cdc_ecm_desc *desc = data->desc;
98 
99 	return desc->if0.bInterfaceNumber;
100 }
101 
cdc_ecm_get_int_in(struct usbd_class_data * const c_data)102 static uint8_t cdc_ecm_get_int_in(struct usbd_class_data *const c_data)
103 {
104 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
105 	const struct device *dev = usbd_class_get_private(c_data);
106 	struct cdc_ecm_eth_data *data = dev->data;
107 	struct usbd_cdc_ecm_desc *desc = data->desc;
108 
109 	if (USBD_SUPPORTS_HIGH_SPEED &&
110 	    usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
111 		return desc->if0_hs_int_ep.bEndpointAddress;
112 	}
113 
114 	return desc->if0_int_ep.bEndpointAddress;
115 }
116 
cdc_ecm_get_bulk_in(struct usbd_class_data * const c_data)117 static uint8_t cdc_ecm_get_bulk_in(struct usbd_class_data *const c_data)
118 {
119 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
120 	const struct device *dev = usbd_class_get_private(c_data);
121 	struct cdc_ecm_eth_data *data = dev->data;
122 	struct usbd_cdc_ecm_desc *desc = data->desc;
123 
124 	if (USBD_SUPPORTS_HIGH_SPEED &&
125 	    usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
126 		return desc->if1_1_hs_in_ep.bEndpointAddress;
127 	}
128 
129 	return desc->if1_1_in_ep.bEndpointAddress;
130 }
131 
cdc_ecm_get_bulk_in_mps(struct usbd_class_data * const c_data)132 static uint16_t cdc_ecm_get_bulk_in_mps(struct usbd_class_data *const c_data)
133 {
134 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
135 
136 	if (USBD_SUPPORTS_HIGH_SPEED &&
137 	    usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
138 		return 512U;
139 	}
140 
141 	return 64U;
142 }
143 
cdc_ecm_get_bulk_out(struct usbd_class_data * const c_data)144 static uint8_t cdc_ecm_get_bulk_out(struct usbd_class_data *const c_data)
145 {
146 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
147 	const struct device *dev = usbd_class_get_private(c_data);
148 	struct cdc_ecm_eth_data *data = dev->data;
149 	struct usbd_cdc_ecm_desc *desc = data->desc;
150 
151 	if (USBD_SUPPORTS_HIGH_SPEED &&
152 	    usbd_bus_speed(uds_ctx) == USBD_SPEED_HS) {
153 		return desc->if1_1_hs_out_ep.bEndpointAddress;
154 	}
155 
156 	return desc->if1_1_out_ep.bEndpointAddress;
157 }
158 
cdc_ecm_buf_alloc(const uint8_t ep)159 static struct net_buf *cdc_ecm_buf_alloc(const uint8_t ep)
160 {
161 	struct net_buf *buf = NULL;
162 	struct udc_buf_info *bi;
163 
164 	buf = net_buf_alloc(&cdc_ecm_ep_pool, K_NO_WAIT);
165 	if (!buf) {
166 		return NULL;
167 	}
168 
169 	bi = udc_get_buf_info(buf);
170 	bi->ep = ep;
171 
172 	return buf;
173 }
174 
175 /* Retrieve expected pkt size from ethernet/ip header */
ecm_eth_size(void * const ecm_pkt,const size_t len)176 static size_t ecm_eth_size(void *const ecm_pkt, const size_t len)
177 {
178 	uint8_t *ip_data = (uint8_t *)ecm_pkt + sizeof(struct net_eth_hdr);
179 	struct net_eth_hdr *hdr = (void *)ecm_pkt;
180 	uint16_t ip_len;
181 
182 	if (len < NET_IPV6H_LEN + sizeof(struct net_eth_hdr)) {
183 		/* Too short */
184 		return 0;
185 	}
186 
187 	switch (ntohs(hdr->type)) {
188 	case NET_ETH_PTYPE_IP:
189 		__fallthrough;
190 	case NET_ETH_PTYPE_ARP:
191 		ip_len = ntohs(((struct net_ipv4_hdr *)ip_data)->len);
192 		break;
193 	case NET_ETH_PTYPE_IPV6:
194 		ip_len = ntohs(((struct net_ipv6_hdr *)ip_data)->len);
195 		break;
196 	default:
197 		LOG_DBG("Unknown hdr type 0x%04x", hdr->type);
198 		return 0;
199 	}
200 
201 	return sizeof(struct net_eth_hdr) + ip_len;
202 }
203 
cdc_ecm_out_start(struct usbd_class_data * const c_data)204 static int cdc_ecm_out_start(struct usbd_class_data *const c_data)
205 {
206 	const struct device *dev = usbd_class_get_private(c_data);
207 	struct cdc_ecm_eth_data *data = dev->data;
208 	struct net_buf *buf;
209 	uint8_t ep;
210 	int ret;
211 
212 	if (atomic_test_and_set_bit(&data->state, CDC_ECM_OUT_ENGAGED)) {
213 		return -EBUSY;
214 	}
215 
216 	ep = cdc_ecm_get_bulk_out(c_data);
217 	buf = cdc_ecm_buf_alloc(ep);
218 	if (buf == NULL) {
219 		return -ENOMEM;
220 	}
221 
222 	ret = usbd_ep_enqueue(c_data, buf);
223 	if (ret) {
224 		LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
225 		net_buf_unref(buf);
226 	}
227 
228 	return  ret;
229 }
230 
cdc_ecm_acl_out_cb(struct usbd_class_data * const c_data,struct net_buf * const buf,const int err)231 static int cdc_ecm_acl_out_cb(struct usbd_class_data *const c_data,
232 			      struct net_buf *const buf, const int err)
233 {
234 	const struct device *dev = usbd_class_get_private(c_data);
235 	struct cdc_ecm_eth_data *data = dev->data;
236 	struct net_pkt *pkt;
237 
238 	if (err || buf->len == 0) {
239 		if (err != -ECONNABORTED) {
240 			LOG_ERR("Bulk OUT transfer error (%d) or zero length", err);
241 		}
242 
243 		goto restart_out_transfer;
244 	}
245 
246 	/* Linux considers by default that network usb device controllers are
247 	 * not able to handle Zero Length Packet (ZLP) and then generates
248 	 * a short packet containing a null byte. Handle by checking the IP
249 	 * header length and dropping the extra byte.
250 	 */
251 	if (buf->data[buf->len - 1] == 0U) {
252 		/* Last byte is null */
253 		if (ecm_eth_size(buf->data, buf->len) == (buf->len - 1)) {
254 			/* last byte has been appended as delimiter, drop it */
255 			net_buf_remove_u8(buf);
256 		}
257 	}
258 
259 	pkt = net_pkt_rx_alloc_with_buffer(data->iface, buf->len,
260 					   AF_UNSPEC, 0, K_FOREVER);
261 	if (!pkt) {
262 		LOG_ERR("No memory for net_pkt");
263 		goto restart_out_transfer;
264 	}
265 
266 	if (net_pkt_write(pkt, buf->data, buf->len)) {
267 		LOG_ERR("Unable to write into pkt");
268 		net_pkt_unref(pkt);
269 		goto restart_out_transfer;
270 	}
271 
272 	LOG_DBG("Received packet len %zu", net_pkt_get_len(pkt));
273 	if (net_recv_data(data->iface, pkt) < 0) {
274 		LOG_ERR("Packet %p dropped by network stack", pkt);
275 		net_pkt_unref(pkt);
276 	}
277 
278 restart_out_transfer:
279 	net_buf_unref(buf);
280 	atomic_clear_bit(&data->state, CDC_ECM_OUT_ENGAGED);
281 
282 	if (atomic_test_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED)) {
283 		return cdc_ecm_out_start(c_data);
284 	}
285 
286 	return 0;
287 }
288 
usbd_cdc_ecm_request(struct usbd_class_data * const c_data,struct net_buf * buf,int err)289 static int usbd_cdc_ecm_request(struct usbd_class_data *const c_data,
290 				struct net_buf *buf, int err)
291 {
292 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
293 	const struct device *dev = usbd_class_get_private(c_data);
294 	struct cdc_ecm_eth_data *data = dev->data;
295 	struct udc_buf_info *bi;
296 
297 	bi = udc_get_buf_info(buf);
298 
299 	if (bi->ep == cdc_ecm_get_bulk_out(c_data)) {
300 		return cdc_ecm_acl_out_cb(c_data, buf, err);
301 	}
302 
303 	if (bi->ep == cdc_ecm_get_bulk_in(c_data)) {
304 		k_sem_give(&data->sync_sem);
305 
306 		return 0;
307 	}
308 
309 	if (bi->ep == cdc_ecm_get_int_in(c_data)) {
310 		LOG_INF("Notification %s", err ? "cancelled or failed" : "sent");
311 	}
312 
313 	return usbd_ep_buf_free(uds_ctx, buf);
314 }
315 
cdc_ecm_send_notification(const struct device * dev,const bool connected)316 static int cdc_ecm_send_notification(const struct device *dev,
317 				     const bool connected)
318 {
319 	struct cdc_ecm_eth_data *data = dev->data;
320 	struct usbd_class_data *c_data = data->c_data;
321 	struct cdc_ecm_notification notification = {
322 		.RequestType = {
323 			.direction = USB_REQTYPE_DIR_TO_HOST,
324 			.type = USB_REQTYPE_TYPE_CLASS,
325 			.recipient = USB_REQTYPE_RECIPIENT_INTERFACE,
326 		},
327 		.bNotificationType = USB_CDC_NETWORK_CONNECTION,
328 		.wValue = sys_cpu_to_le16((uint16_t)connected),
329 		.wIndex = sys_cpu_to_le16(cdc_ecm_get_ctrl_if(data)),
330 		.wLength = 0,
331 	};
332 	struct net_buf *buf;
333 	uint8_t ep;
334 	int ret;
335 
336 	if (!atomic_test_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED)) {
337 		LOG_INF("USB configuration is not enabled");
338 		return 0;
339 	}
340 
341 	if (atomic_test_bit(&data->state, CDC_ECM_CLASS_SUSPENDED)) {
342 		LOG_INF("USB device is suspended (FIXME)");
343 		return 0;
344 	}
345 
346 	ep = cdc_ecm_get_int_in(c_data);
347 	buf = usbd_ep_buf_alloc(c_data, ep, sizeof(struct cdc_ecm_notification));
348 	if (buf == NULL) {
349 		return -ENOMEM;
350 	}
351 
352 	net_buf_add_mem(buf, &notification, sizeof(struct cdc_ecm_notification));
353 	ret = usbd_ep_enqueue(c_data, buf);
354 	if (ret) {
355 		LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
356 		net_buf_unref(buf);
357 		return ret;
358 	}
359 
360 	return 0;
361 }
362 
usbd_cdc_ecm_update(struct usbd_class_data * const c_data,const uint8_t iface,const uint8_t alternate)363 static void usbd_cdc_ecm_update(struct usbd_class_data *const c_data,
364 				const uint8_t iface, const uint8_t alternate)
365 {
366 	const struct device *dev = usbd_class_get_private(c_data);
367 	struct cdc_ecm_eth_data *data = dev->data;
368 	struct usbd_cdc_ecm_desc *desc = data->desc;
369 	const uint8_t data_iface = desc->if1_1.bInterfaceNumber;
370 
371 	LOG_INF("New configuration, interface %u alternate %u",
372 		iface, alternate);
373 
374 	if (data_iface == iface && alternate == 0) {
375 		atomic_clear_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED);
376 		net_if_carrier_off(data->iface);
377 	}
378 
379 	if (data_iface == iface && alternate == 1) {
380 		atomic_set_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED);
381 
382 		if (atomic_test_bit(&data->state, CDC_ECM_IFACE_UP)) {
383 			net_if_carrier_on(data->iface);
384 			if (cdc_ecm_send_notification(dev, true)) {
385 				LOG_ERR("Failed to send connected notification");
386 			}
387 		}
388 
389 		if (cdc_ecm_out_start(c_data)) {
390 			LOG_ERR("Failed to start OUT transfer");
391 		}
392 	}
393 }
394 
usbd_cdc_ecm_enable(struct usbd_class_data * const c_data)395 static void usbd_cdc_ecm_enable(struct usbd_class_data *const c_data)
396 {
397 	LOG_INF("Enabled %s", c_data->name);
398 }
399 
usbd_cdc_ecm_disable(struct usbd_class_data * const c_data)400 static void usbd_cdc_ecm_disable(struct usbd_class_data *const c_data)
401 {
402 	const struct device *dev = usbd_class_get_private(c_data);
403 	struct cdc_ecm_eth_data *data = dev->data;
404 
405 	atomic_clear_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED);
406 	atomic_clear_bit(&data->state, CDC_ECM_CLASS_SUSPENDED);
407 	LOG_INF("Disabled %s", c_data->name);
408 }
409 
usbd_cdc_ecm_suspended(struct usbd_class_data * const c_data)410 static void usbd_cdc_ecm_suspended(struct usbd_class_data *const c_data)
411 {
412 	const struct device *dev = usbd_class_get_private(c_data);
413 	struct cdc_ecm_eth_data *data = dev->data;
414 
415 	atomic_set_bit(&data->state, CDC_ECM_CLASS_SUSPENDED);
416 }
417 
usbd_cdc_ecm_resumed(struct usbd_class_data * const c_data)418 static void usbd_cdc_ecm_resumed(struct usbd_class_data *const c_data)
419 {
420 	const struct device *dev = usbd_class_get_private(c_data);
421 	struct cdc_ecm_eth_data *data = dev->data;
422 
423 	atomic_clear_bit(&data->state, CDC_ECM_CLASS_SUSPENDED);
424 }
425 
usbd_cdc_ecm_ctd(struct usbd_class_data * const c_data,const struct usb_setup_packet * const setup,const struct net_buf * const buf)426 static int usbd_cdc_ecm_ctd(struct usbd_class_data *const c_data,
427 			    const struct usb_setup_packet *const setup,
428 			    const struct net_buf *const buf)
429 {
430 	if (setup->RequestType.recipient == USB_REQTYPE_RECIPIENT_INTERFACE &&
431 	    setup->bRequest == SET_ETHERNET_PACKET_FILTER) {
432 		LOG_INF("bRequest 0x%02x (SetPacketFilter) not implemented",
433 			setup->bRequest);
434 
435 		return 0;
436 	}
437 
438 	LOG_DBG("bmRequestType 0x%02x bRequest 0x%02x unsupported",
439 		setup->bmRequestType, setup->bRequest);
440 	errno = -ENOTSUP;
441 
442 	return 0;
443 }
444 
usbd_cdc_ecm_init(struct usbd_class_data * const c_data)445 static int usbd_cdc_ecm_init(struct usbd_class_data *const c_data)
446 {
447 	struct usbd_context *uds_ctx = usbd_class_get_ctx(c_data);
448 	const struct device *dev = usbd_class_get_private(c_data);
449 	struct cdc_ecm_eth_data *const data = dev->data;
450 	struct usbd_cdc_ecm_desc *desc = data->desc;
451 	const uint8_t if_num = desc->if0.bInterfaceNumber;
452 
453 	/* Update relevant b*Interface fields */
454 	desc->if0_union.bControlInterface = if_num;
455 	desc->if0_union.bSubordinateInterface0 = if_num + 1;
456 	LOG_DBG("CDC ECM class initialized");
457 
458 	if (usbd_add_descriptor(uds_ctx, data->mac_desc_data)) {
459 		LOG_ERR("Failed to add iMACAddress string descriptor");
460 	} else {
461 		desc->if0_ecm.iMACAddress = usbd_str_desc_get_idx(data->mac_desc_data);
462 	}
463 
464 	return 0;
465 }
466 
usbd_cdc_ecm_shutdown(struct usbd_class_data * const c_data)467 static void usbd_cdc_ecm_shutdown(struct usbd_class_data *const c_data)
468 {
469 	const struct device *dev = usbd_class_get_private(c_data);
470 	struct cdc_ecm_eth_data *const data = dev->data;
471 	struct usbd_cdc_ecm_desc *desc = data->desc;
472 
473 	desc->if0_ecm.iMACAddress = 0;
474 	sys_dlist_remove(&data->mac_desc_data->node);
475 }
476 
usbd_cdc_ecm_get_desc(struct usbd_class_data * const c_data,const enum usbd_speed speed)477 static void *usbd_cdc_ecm_get_desc(struct usbd_class_data *const c_data,
478 				   const enum usbd_speed speed)
479 {
480 	const struct device *dev = usbd_class_get_private(c_data);
481 	struct cdc_ecm_eth_data *const data = dev->data;
482 
483 	if (USBD_SUPPORTS_HIGH_SPEED && speed == USBD_SPEED_HS) {
484 		return data->hs_desc;
485 	}
486 
487 	return data->fs_desc;
488 }
489 
cdc_ecm_send(const struct device * dev,struct net_pkt * const pkt)490 static int cdc_ecm_send(const struct device *dev, struct net_pkt *const pkt)
491 {
492 	struct cdc_ecm_eth_data *const data = dev->data;
493 	struct usbd_class_data *c_data = data->c_data;
494 	size_t len = net_pkt_get_len(pkt);
495 	struct net_buf *buf;
496 	uint8_t ep;
497 	int ret;
498 
499 	if (len > NET_ETH_MAX_FRAME_SIZE) {
500 		LOG_WRN("Trying to send too large packet, drop");
501 		return -ENOMEM;
502 	}
503 
504 	if (!atomic_test_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED) ||
505 	    !atomic_test_bit(&data->state, CDC_ECM_IFACE_UP)) {
506 		LOG_INF("Configuration is not enabled or interface not ready");
507 		return -EACCES;
508 	}
509 
510 	ep = cdc_ecm_get_bulk_in(c_data);
511 	buf = cdc_ecm_buf_alloc(ep);
512 	if (buf == NULL) {
513 		LOG_ERR("Failed to allocate buffer");
514 		return -ENOMEM;
515 	}
516 
517 	if (net_pkt_read(pkt, buf->data, len)) {
518 		LOG_ERR("Failed copy net_pkt");
519 		net_buf_unref(buf);
520 
521 		return -ENOBUFS;
522 	}
523 
524 	net_buf_add(buf, len);
525 
526 	if (!(buf->len % cdc_ecm_get_bulk_in_mps(c_data))) {
527 		udc_ep_buf_set_zlp(buf);
528 	}
529 
530 	ret = usbd_ep_enqueue(c_data, buf);
531 	if (ret) {
532 		LOG_ERR("Failed to enqueue net_buf for 0x%02x", ep);
533 		net_buf_unref(buf);
534 		return ret;
535 	}
536 
537 	k_sem_take(&data->sync_sem, K_FOREVER);
538 	net_buf_unref(buf);
539 
540 	return 0;
541 }
542 
cdc_ecm_set_config(const struct device * dev,const enum ethernet_config_type type,const struct ethernet_config * config)543 static int cdc_ecm_set_config(const struct device *dev,
544 			      const enum ethernet_config_type type,
545 			      const struct ethernet_config *config)
546 {
547 	struct cdc_ecm_eth_data *data = dev->data;
548 
549 	if (type == ETHERNET_CONFIG_TYPE_MAC_ADDRESS) {
550 		memcpy(data->mac_addr, config->mac_address.addr,
551 		       sizeof(data->mac_addr));
552 
553 		return 0;
554 	}
555 
556 	return -ENOTSUP;
557 }
558 
cdc_ecm_get_capabilities(const struct device * dev)559 static enum ethernet_hw_caps cdc_ecm_get_capabilities(const struct device *dev)
560 {
561 	ARG_UNUSED(dev);
562 
563 	return ETHERNET_LINK_10BASE;
564 }
565 
cdc_ecm_iface_start(const struct device * dev)566 static int cdc_ecm_iface_start(const struct device *dev)
567 {
568 	struct cdc_ecm_eth_data *data = dev->data;
569 
570 	LOG_DBG("Start interface %p", data->iface);
571 
572 	atomic_set_bit(&data->state, CDC_ECM_IFACE_UP);
573 
574 	if (atomic_test_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED)) {
575 		net_if_carrier_on(data->iface);
576 		if (cdc_ecm_send_notification(dev, true)) {
577 			LOG_ERR("Failed to send connected notification");
578 		}
579 	}
580 
581 	return 0;
582 }
583 
cdc_ecm_iface_stop(const struct device * dev)584 static int cdc_ecm_iface_stop(const struct device *dev)
585 {
586 	struct cdc_ecm_eth_data *data = dev->data;
587 
588 	LOG_DBG("Stop interface %p", data->iface);
589 
590 	atomic_clear_bit(&data->state, CDC_ECM_IFACE_UP);
591 
592 	if (atomic_test_bit(&data->state, CDC_ECM_DATA_IFACE_ENABLED)) {
593 		if (cdc_ecm_send_notification(dev, false)) {
594 			LOG_ERR("Failed to send disconnected notification");
595 		}
596 	}
597 
598 	return 0;
599 }
600 
cdc_ecm_iface_init(struct net_if * const iface)601 static void cdc_ecm_iface_init(struct net_if *const iface)
602 {
603 	const struct device *dev = net_if_get_device(iface);
604 	struct cdc_ecm_eth_data *data = dev->data;
605 
606 	data->iface = iface;
607 	ethernet_init(iface);
608 	net_if_set_link_addr(iface, data->mac_addr,
609 			     sizeof(data->mac_addr),
610 			     NET_LINK_ETHERNET);
611 
612 	net_if_carrier_off(iface);
613 
614 	LOG_DBG("CDC ECM interface initialized");
615 }
616 
usbd_cdc_ecm_preinit(const struct device * dev)617 static int usbd_cdc_ecm_preinit(const struct device *dev)
618 {
619 	struct cdc_ecm_eth_data *data = dev->data;
620 
621 	if (sys_get_le48(data->mac_addr) == sys_cpu_to_le48(0)) {
622 		gen_random_mac(data->mac_addr, 0, 0, 0);
623 	}
624 
625 	LOG_DBG("CDC ECM device initialized");
626 
627 	return 0;
628 }
629 
630 static struct usbd_class_api usbd_cdc_ecm_api = {
631 	.request = usbd_cdc_ecm_request,
632 	.update = usbd_cdc_ecm_update,
633 	.enable = usbd_cdc_ecm_enable,
634 	.disable = usbd_cdc_ecm_disable,
635 	.suspended = usbd_cdc_ecm_suspended,
636 	.resumed = usbd_cdc_ecm_resumed,
637 	.control_to_dev = usbd_cdc_ecm_ctd,
638 	.init = usbd_cdc_ecm_init,
639 	.shutdown = usbd_cdc_ecm_shutdown,
640 	.get_desc = usbd_cdc_ecm_get_desc,
641 };
642 
643 static const struct ethernet_api cdc_ecm_eth_api = {
644 	.iface_api.init = cdc_ecm_iface_init,
645 	.set_config = cdc_ecm_set_config,
646 	.get_capabilities = cdc_ecm_get_capabilities,
647 	.send = cdc_ecm_send,
648 	.start = cdc_ecm_iface_start,
649 	.stop = cdc_ecm_iface_stop,
650 };
651 
652 #define CDC_ECM_DEFINE_DESCRIPTOR(n)						\
653 static struct usbd_cdc_ecm_desc cdc_ecm_desc_##n = {				\
654 	.iad = {								\
655 		.bLength = sizeof(struct usb_association_descriptor),		\
656 		.bDescriptorType = USB_DESC_INTERFACE_ASSOC,			\
657 		.bFirstInterface = 0,						\
658 		.bInterfaceCount = 0x02,					\
659 		.bFunctionClass = USB_BCC_CDC_CONTROL,				\
660 		.bFunctionSubClass = ECM_SUBCLASS,				\
661 		.bFunctionProtocol = 0,						\
662 		.iFunction = 0,							\
663 	},									\
664 										\
665 	.if0 = {								\
666 		.bLength = sizeof(struct usb_if_descriptor),			\
667 		.bDescriptorType = USB_DESC_INTERFACE,				\
668 		.bInterfaceNumber = 0,						\
669 		.bAlternateSetting = 0,						\
670 		.bNumEndpoints = 1,						\
671 		.bInterfaceClass = USB_BCC_CDC_CONTROL,				\
672 		.bInterfaceSubClass = ECM_SUBCLASS,				\
673 		.bInterfaceProtocol = 0,					\
674 		.iInterface = 0,						\
675 	},									\
676 										\
677 	.if0_header = {								\
678 		.bFunctionLength = sizeof(struct cdc_header_descriptor),	\
679 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
680 		.bDescriptorSubtype = HEADER_FUNC_DESC,				\
681 		.bcdCDC = sys_cpu_to_le16(USB_SRN_1_1),				\
682 	},									\
683 										\
684 	.if0_union = {								\
685 		.bFunctionLength = sizeof(struct cdc_union_descriptor),		\
686 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
687 		.bDescriptorSubtype = UNION_FUNC_DESC,				\
688 		.bControlInterface = 0,						\
689 		.bSubordinateInterface0 = 1,					\
690 	},									\
691 										\
692 	.if0_ecm = {								\
693 		.bFunctionLength = sizeof(struct cdc_ecm_descriptor),		\
694 		.bDescriptorType = USB_DESC_CS_INTERFACE,			\
695 		.bDescriptorSubtype = ETHERNET_FUNC_DESC,			\
696 		.iMACAddress = 0,						\
697 		.bmEthernetStatistics = sys_cpu_to_le32(0),			\
698 		.wMaxSegmentSize = sys_cpu_to_le16(NET_ETH_MAX_FRAME_SIZE),	\
699 		.wNumberMCFilters = sys_cpu_to_le16(0),				\
700 		.bNumberPowerFilters = 0,					\
701 	},									\
702 										\
703 	.if0_int_ep = {								\
704 		.bLength = sizeof(struct usb_ep_descriptor),			\
705 		.bDescriptorType = USB_DESC_ENDPOINT,				\
706 		.bEndpointAddress = 0x81,					\
707 		.bmAttributes = USB_EP_TYPE_INTERRUPT,				\
708 		.wMaxPacketSize = sys_cpu_to_le16(CDC_ECM_EP_MPS_INT),		\
709 		.bInterval = CDC_ECM_FS_INT_EP_INTERVAL,			\
710 	},									\
711 										\
712 	.if0_hs_int_ep = {							\
713 		.bLength = sizeof(struct usb_ep_descriptor),			\
714 		.bDescriptorType = USB_DESC_ENDPOINT,				\
715 		.bEndpointAddress = 0x81,					\
716 		.bmAttributes = USB_EP_TYPE_INTERRUPT,				\
717 		.wMaxPacketSize = sys_cpu_to_le16(CDC_ECM_EP_MPS_INT),		\
718 		.bInterval = CDC_ECM_HS_INT_EP_INTERVAL,			\
719 	},									\
720 										\
721 	.if1_0 = {								\
722 		.bLength = sizeof(struct usb_if_descriptor),			\
723 		.bDescriptorType = USB_DESC_INTERFACE,				\
724 		.bInterfaceNumber = 1,						\
725 		.bAlternateSetting = 0,						\
726 		.bNumEndpoints = 0,						\
727 		.bInterfaceClass = USB_BCC_CDC_DATA,				\
728 		.bInterfaceSubClass = 0,					\
729 		.bInterfaceProtocol = 0,					\
730 		.iInterface = 0,						\
731 	},									\
732 										\
733 	.if1_1 = {								\
734 		.bLength = sizeof(struct usb_if_descriptor),			\
735 		.bDescriptorType = USB_DESC_INTERFACE,				\
736 		.bInterfaceNumber = 1,						\
737 		.bAlternateSetting = 1,						\
738 		.bNumEndpoints = 2,						\
739 		.bInterfaceClass = USB_BCC_CDC_DATA,				\
740 		.bInterfaceSubClass = ECM_SUBCLASS,				\
741 		.bInterfaceProtocol = 0,					\
742 		.iInterface = 0,						\
743 	},									\
744 										\
745 	.if1_1_in_ep = {							\
746 		.bLength = sizeof(struct usb_ep_descriptor),			\
747 		.bDescriptorType = USB_DESC_ENDPOINT,				\
748 		.bEndpointAddress = 0x82,					\
749 		.bmAttributes = USB_EP_TYPE_BULK,				\
750 		.wMaxPacketSize = sys_cpu_to_le16(64U),				\
751 		.bInterval = 0,							\
752 	},									\
753 										\
754 	.if1_1_out_ep = {							\
755 		.bLength = sizeof(struct usb_ep_descriptor),			\
756 		.bDescriptorType = USB_DESC_ENDPOINT,				\
757 		.bEndpointAddress = 0x01,					\
758 		.bmAttributes = USB_EP_TYPE_BULK,				\
759 		.wMaxPacketSize = sys_cpu_to_le16(64U),				\
760 		.bInterval = 0,							\
761 	},									\
762 										\
763 	.if1_1_hs_in_ep = {							\
764 		.bLength = sizeof(struct usb_ep_descriptor),			\
765 		.bDescriptorType = USB_DESC_ENDPOINT,				\
766 		.bEndpointAddress = 0x82,					\
767 		.bmAttributes = USB_EP_TYPE_BULK,				\
768 		.wMaxPacketSize = sys_cpu_to_le16(512U),			\
769 		.bInterval = 0,							\
770 	},									\
771 										\
772 	.if1_1_hs_out_ep = {							\
773 		.bLength = sizeof(struct usb_ep_descriptor),			\
774 		.bDescriptorType = USB_DESC_ENDPOINT,				\
775 		.bEndpointAddress = 0x01,					\
776 		.bmAttributes = USB_EP_TYPE_BULK,				\
777 		.wMaxPacketSize = sys_cpu_to_le16(512U),			\
778 		.bInterval = 0,							\
779 	},									\
780 										\
781 	.nil_desc = {								\
782 		.bLength = 0,							\
783 		.bDescriptorType = 0,						\
784 	},									\
785 };										\
786 										\
787 	const static struct usb_desc_header *cdc_ecm_fs_desc_##n[] = {		\
788 		(struct usb_desc_header *) &cdc_ecm_desc_##n.iad,		\
789 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0,		\
790 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_header,	\
791 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_union,		\
792 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_ecm,		\
793 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_int_ep,	\
794 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_0,		\
795 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1,		\
796 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1_in_ep,	\
797 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1_out_ep,	\
798 		(struct usb_desc_header *) &cdc_ecm_desc_##n.nil_desc,		\
799 	};									\
800 										\
801 	const static struct usb_desc_header *cdc_ecm_hs_desc_##n[] = {		\
802 		(struct usb_desc_header *) &cdc_ecm_desc_##n.iad,		\
803 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0,		\
804 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_header,	\
805 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_union,		\
806 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_ecm,		\
807 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if0_hs_int_ep,	\
808 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_0,		\
809 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1,		\
810 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1_hs_in_ep,	\
811 		(struct usb_desc_header *) &cdc_ecm_desc_##n.if1_1_hs_out_ep,	\
812 		(struct usb_desc_header *) &cdc_ecm_desc_##n.nil_desc,		\
813 	}
814 
815 #define USBD_CDC_ECM_DT_DEVICE_DEFINE(n)					\
816 	CDC_ECM_DEFINE_DESCRIPTOR(n);						\
817 	USBD_DESC_STRING_DEFINE(mac_desc_data_##n,				\
818 				DT_INST_PROP(n, remote_mac_address),		\
819 				USBD_DUT_STRING_INTERFACE);			\
820 										\
821 	USBD_DEFINE_CLASS(cdc_ecm_##n,						\
822 			  &usbd_cdc_ecm_api,					\
823 			  (void *)DEVICE_DT_GET(DT_DRV_INST(n)), NULL);		\
824 										\
825 	static struct cdc_ecm_eth_data eth_data_##n = {				\
826 		.c_data = &cdc_ecm_##n,						\
827 		.mac_addr = DT_INST_PROP_OR(n, local_mac_address, {0}),		\
828 		.sync_sem = Z_SEM_INITIALIZER(eth_data_##n.sync_sem, 0, 1),	\
829 		.mac_desc_data = &mac_desc_data_##n,				\
830 		.desc = &cdc_ecm_desc_##n,					\
831 		.fs_desc = cdc_ecm_fs_desc_##n,					\
832 		.hs_desc = cdc_ecm_hs_desc_##n,					\
833 	};									\
834 										\
835 	ETH_NET_DEVICE_DT_INST_DEFINE(n, usbd_cdc_ecm_preinit, NULL,		\
836 		&eth_data_##n, NULL,						\
837 		CONFIG_ETH_INIT_PRIORITY,					\
838 		&cdc_ecm_eth_api,						\
839 		NET_ETH_MTU);
840 
841 DT_INST_FOREACH_STATUS_OKAY(USBD_CDC_ECM_DT_DEVICE_DEFINE);
842