summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/class/net/net_device.c345
-rw-r--r--src/class/net/net_device.h84
-rw-r--r--src/device/usbd.c18
-rw-r--r--src/device/usbd.h84
-rw-r--r--src/tusb.h4
-rw-r--r--src/tusb_option.h12
6 files changed, 547 insertions, 0 deletions
diff --git a/src/class/net/net_device.c b/src/class/net/net_device.c
new file mode 100644
index 000000000..422d435c6
--- /dev/null
+++ b/src/class/net/net_device.c
@@ -0,0 +1,345 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Peter Lawrence
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+#if ( TUSB_OPT_DEVICE_ENABLED && (CFG_TUD_NET != OPT_NET_NONE) )
+
+#include "net_device.h"
+#include "device/usbd_pvt.h"
+#include "rndis_protocol.h"
+
+void rndis_class_set_handler(uint8_t *data, int size); /* found in ./misc/networking/rndis_reports.c */
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+typedef struct
+{
+ uint8_t itf_num;
+ uint8_t ep_notif;
+ uint8_t ep_in;
+ uint8_t ep_out;
+} netd_interface_t;
+
+#if CFG_TUD_NET == OPT_NET_ECM
+ #define CFG_TUD_NET_PACKET_PREFIX_LEN 0
+ #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
+ #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL
+#elif CFG_TUD_NET == OPT_NET_RNDIS
+ #define CFG_TUD_NET_PACKET_PREFIX_LEN sizeof(rndis_data_packet_t)
+ #define CFG_TUD_NET_PACKET_SUFFIX_LEN 0
+ #define CFG_TUD_NET_INTERFACESUBCLASS TUD_RNDIS_ITF_SUBCLASS
+#elif CFG_TUD_NET == OPT_NET_EEM
+ #define CFG_TUD_NET_PACKET_PREFIX_LEN 2
+ #define CFG_TUD_NET_PACKET_SUFFIX_LEN 4
+ #define CFG_TUD_NET_INTERFACESUBCLASS CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL
+#endif
+
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t received[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t transmitted[CFG_TUD_NET_PACKET_PREFIX_LEN + CFG_TUD_NET_MTU + CFG_TUD_NET_PACKET_PREFIX_LEN];
+
+#if CFG_TUD_NET == OPT_NET_RNDIS
+ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t rndis_buf[128];
+#endif
+
+//--------------------------------------------------------------------+
+// INTERNAL OBJECT & FUNCTION DECLARATION
+//--------------------------------------------------------------------+
+CFG_TUSB_MEM_SECTION static netd_interface_t _netd_itf;
+
+static bool can_xmit;
+
+void network_recv_renew(void)
+{
+ usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_out, received, sizeof(received));
+}
+
+static void do_in_xfer(uint8_t *buf, uint16_t len)
+{
+ can_xmit = false;
+ usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_in, buf, len);
+}
+
+void netd_report(uint8_t *buf, uint16_t len)
+{
+ usbd_edpt_xfer(TUD_OPT_RHPORT, _netd_itf.ep_notif, buf, len);
+}
+
+//--------------------------------------------------------------------+
+// USBD Driver API
+//--------------------------------------------------------------------+
+void netd_init(void)
+{
+ tu_memclr(&_netd_itf, sizeof(_netd_itf));
+}
+
+void netd_reset(uint8_t rhport)
+{
+ (void) rhport;
+
+ netd_init();
+}
+
+bool netd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length)
+{
+ // sanity check the descriptor
+ TU_ASSERT (CFG_TUD_NET_INTERFACESUBCLASS == itf_desc->bInterfaceSubClass);
+
+ // confirm interface hasn't already been allocated
+ TU_ASSERT(0 == _netd_itf.ep_in);
+
+ //------------- first Interface -------------//
+ _netd_itf.itf_num = itf_desc->bInterfaceNumber;
+
+ uint8_t const * p_desc = tu_desc_next( itf_desc );
+ (*p_length) = sizeof(tusb_desc_interface_t);
+
+#if CFG_TUD_NET != OPT_NET_EEM
+ // Communication Functional Descriptors
+ while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
+ {
+ (*p_length) += tu_desc_len(p_desc);
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ // notification endpoint (if any)
+ if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
+ {
+ TU_ASSERT( dcd_edpt_open(rhport, (tusb_desc_endpoint_t const *) p_desc) );
+
+ _netd_itf.ep_notif = ((tusb_desc_endpoint_t const *) p_desc)->bEndpointAddress;
+
+ (*p_length) += p_desc[DESC_OFFSET_LEN];
+ p_desc = tu_desc_next(p_desc);
+ }
+
+ //------------- second Interface -------------//
+ if ( (TUSB_DESC_INTERFACE == p_desc[DESC_OFFSET_TYPE]) &&
+ (TUSB_CLASS_CDC_DATA == ((tusb_desc_interface_t const *) p_desc)->bInterfaceClass) )
+ {
+ // next to endpoint descriptor
+ p_desc = tu_desc_next(p_desc);
+ (*p_length) += sizeof(tusb_desc_interface_t);
+ }
+#endif
+
+ if (TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
+ {
+ // Open endpoint pair
+ TU_ASSERT( usbd_open_edpt_pair(rhport, p_desc, 2, TUSB_XFER_BULK, &_netd_itf.ep_out, &_netd_itf.ep_in) );
+
+ (*p_length) += 2*sizeof(tusb_desc_endpoint_t);
+ }
+
+ network_init_callback();
+
+ // we are ready to transmit a packet
+ can_xmit = true;
+
+ // prepare for incoming packets
+ network_recv_renew();
+
+ return true;
+}
+
+// Invoked when class request DATA stage is finished.
+// return false to stall control endpoint (e.g Host send nonsense DATA)
+bool netd_control_complete(uint8_t rhport, tusb_control_request_t const * request)
+{
+ (void) rhport;
+
+ // Handle class request only
+ TU_VERIFY (request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+
+ TU_VERIFY (_netd_itf.itf_num == request->wIndex);
+
+#if CFG_TUD_NET == OPT_NET_RNDIS
+ if (request->bmRequestType_bit.direction == TUSB_DIR_OUT)
+ {
+ rndis_class_set_handler(rndis_buf, request->wLength);
+ }
+#endif
+
+ return true;
+}
+
+// Handle class control request
+// return false to stall control endpoint (e.g unsupported request)
+bool netd_control_request(uint8_t rhport, tusb_control_request_t const * request)
+{
+ // Handle class request only
+ TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS);
+
+ TU_VERIFY (_netd_itf.itf_num == request->wIndex);
+
+#if CFG_TUD_NET == OPT_NET_RNDIS
+ tud_control_xfer(rhport, request, rndis_buf, sizeof(rndis_buf));
+#else
+ (void)rhport;
+#endif
+
+ return true;
+}
+
+struct cdc_eem_packet_header
+{
+ uint16_t length:14;
+ uint16_t bmCRC:1;
+ uint16_t bmType:1;
+};
+
+static void handle_incoming_packet(uint32_t len)
+{
+ uint8_t *pnt = received;
+ uint32_t size = 0;
+
+#if CFG_TUD_NET == OPT_NET_ECM
+ size = len;
+#elif CFG_TUD_NET == OPT_NET_RNDIS
+ rndis_data_packet_t *r = (rndis_data_packet_t *)pnt;
+ if (len >= sizeof(rndis_data_packet_t))
+ if ( (r->MessageType == REMOTE_NDIS_PACKET_MSG) && (r->MessageLength <= len))
+ if ( (r->DataOffset + offsetof(rndis_data_packet_t, DataOffset) + r->DataLength) <= len)
+ {
+ pnt = &received[r->DataOffset + offsetof(rndis_data_packet_t, DataOffset)];
+ size = r->DataLength;
+ }
+#elif CFG_TUD_NET == OPT_NET_EEM
+ struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)pnt;
+
+ (void)len;
+
+ if (hdr->bmType)
+ {
+ /* EEM Control Packet: discard it */
+ network_recv_renew();
+ }
+ else
+ {
+ /* EEM Data Packet */
+ pnt += CFG_TUD_NET_PACKET_PREFIX_LEN;
+ size = hdr->length - 4; /* discard the unused CRC-32 */
+ }
+#endif
+
+ if (size)
+ {
+ struct pbuf *p = pbuf_alloc(PBUF_RAW, size, PBUF_POOL);
+ bool accepted = true;
+
+ if (p)
+ {
+ memcpy(p->payload, pnt, size);
+ p->len = size;
+ accepted = network_recv_callback(p);
+ }
+
+ if (!p || !accepted)
+ {
+ /* if a buffer couldn't be allocated or accepted by the callback, we must discard this packet */
+ network_recv_renew();
+ }
+ }
+}
+
+bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes)
+{
+ (void) rhport;
+ (void) result;
+
+ /* new packet received */
+ if ( ep_addr == _netd_itf.ep_out )
+ {
+ handle_incoming_packet(xferred_bytes);
+ }
+
+ /* data transmission finished */
+ if ( ep_addr == _netd_itf.ep_in )
+ {
+ /* TinyUSB requires the class driver to implement ZLP (since ZLP usage is class-specific) */
+
+ if ( xferred_bytes && (0 == (xferred_bytes % CFG_TUD_NET_ENDPOINT_SIZE)) )
+ {
+ do_in_xfer(NULL, 0); /* a ZLP is needed */
+ }
+ else
+ {
+ /* we're finally finished */
+ can_xmit = true;
+ }
+ }
+
+ return true;
+}
+
+bool network_can_xmit(void)
+{
+ return can_xmit;
+}
+
+void network_xmit(struct pbuf *p)
+{
+ struct pbuf *q;
+ uint8_t *data;
+ uint16_t len;
+
+ if (!can_xmit)
+ return;
+
+ len = CFG_TUD_NET_PACKET_PREFIX_LEN;
+ data = transmitted + len;
+
+ for(q = p; q != NULL; q = q->next)
+ {
+ memcpy(data, (char *)q->payload, q->len);
+ data += q->len;
+ len += q->len;
+ }
+
+#if CFG_TUD_NET == OPT_NET_RNDIS
+ rndis_data_packet_t *hdr = (rndis_data_packet_t *)transmitted;
+ memset(hdr, 0, sizeof(rndis_data_packet_t));
+ hdr->MessageType = REMOTE_NDIS_PACKET_MSG;
+ hdr->MessageLength = len;
+ hdr->DataOffset = sizeof(rndis_data_packet_t) - offsetof(rndis_data_packet_t, DataOffset);
+ hdr->DataLength = len - sizeof(rndis_data_packet_t);
+#elif CFG_TUD_NET == OPT_NET_EEM
+ struct cdc_eem_packet_header *hdr = (struct cdc_eem_packet_header *)transmitted;
+ /* append a fake CRC-32; the standard allows 0xDEADBEEF, which takes less CPU time */
+ data[0] = 0xDE; data[1] = 0xAD; data[2] = 0xBE; data[3] = 0xEF;
+ /* adjust length to reflect added fake CRC-32 */
+ len += 4;
+ hdr->bmType = 0; /* EEM Data Packet */
+ hdr->length = len - sizeof(struct cdc_eem_packet_header);
+ hdr->bmCRC = 0; /* Ethernet Frame CRC-32 set to 0xDEADBEEF */
+#endif
+
+ do_in_xfer(transmitted, len);
+}
+
+#endif
diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h
new file mode 100644
index 000000000..c61efc86c
--- /dev/null
+++ b/src/class/net/net_device.h
@@ -0,0 +1,84 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Peter Lawrence
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef _TUSB_NET_DEVICE_H_
+#define _TUSB_NET_DEVICE_H_
+
+#include "common/tusb_common.h"
+#include "device/usbd.h"
+#include "class/cdc/cdc.h"
+#include "lwip/pbuf.h"
+#include "netif/ethernet.h"
+
+/* declared here, NOT in usb_descriptors.c, so that the driver can intelligently ZLP as needed */
+#define CFG_TUD_NET_ENDPOINT_SIZE ((CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64)
+
+/* Maximum Tranmission Unit (in bytes) of the network, including Ethernet header */
+#define CFG_TUD_NET_MTU (1500 + SIZEOF_ETH_HDR)
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
+
+// client must provide this: initialize any network state back to the beginning
+void network_init_callback(void);
+
+// client must provide this: return false if the packet buffer was not accepted
+bool network_recv_callback(struct pbuf *p);
+
+// client must provide this: 48-bit MAC address
+extern const uint8_t network_mac_address[6];
+
+// indicate to network driver that client has finished with the packet provided to network_recv_callback()
+void network_recv_renew(void);
+
+// poll network driver for its ability to accept another packet to transmit
+bool network_can_xmit(void);
+
+// if network_can_xmit() returns true, network_xmit() can be called once
+void network_xmit(struct pbuf *p);
+
+//--------------------------------------------------------------------+
+// INTERNAL USBD-CLASS DRIVER API
+//--------------------------------------------------------------------+
+void netd_init (void);
+void netd_reset (uint8_t rhport);
+bool netd_open (uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length);
+bool netd_control_request (uint8_t rhport, tusb_control_request_t const * request);
+bool netd_control_complete (uint8_t rhport, tusb_control_request_t const * request);
+bool netd_xfer_cb (uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+void netd_report (uint8_t *buf, uint16_t len);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_NET_DEVICE_H_ */
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 68c5c5160..32a89889e 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -181,6 +181,24 @@ static usbd_class_driver_t const _usbd_driver[] =
.sof = NULL
},
#endif
+
+ #if CFG_TUD_NET
+ {
+ .class_code =
+#if CFG_TUD_NET == OPT_NET_RNDIS
+ TUD_RNDIS_ITF_CLASS,
+#else
+ TUSB_CLASS_CDC,
+#endif
+ .init = netd_init,
+ .reset = netd_reset,
+ .open = netd_open,
+ .control_request = netd_control_request,
+ .control_complete = netd_control_complete,
+ .xfer_cb = netd_xfer_cb,
+ .sof = NULL
+ },
+ #endif
};
enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(_usbd_driver) };
diff --git a/src/device/usbd.h b/src/device/usbd.h
index d80abf17c..07163a013 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -326,6 +326,90 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re
9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101)
+//------------- CDC-ECM -------------//
+
+// Length of template descriptor: 62 bytes
+#define TUD_CDC_ECM_DESC_LEN (9+5+5+13+7+9+7+7)
+
+// CDC-ECM Descriptor Template
+// Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size.
+#define TUD_CDC_ECM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize) \
+ /* CDC Control Interface */\
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0, _desc_stridx,\
+ /* CDC-ECM Header */\
+ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
+ /* CDC-ECM Union */\
+ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\
+ /* CDC-ECM Functional Descriptor */\
+ 13, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ETHERNET_NETWORKING, _mac_stridx, 0, 0, 0, 0, U16_TO_U8S_LE(_maxsegmentsize), U16_TO_U8S_LE(0), 0,\
+ /* Endpoint Notification */\
+ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\
+ /* CDC Data Interface */\
+ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
+ /* Endpoint In */\
+ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
+ /* Endpoint Out */\
+ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
+
+
+//------------- RNDIS -------------//
+
+#if 0
+ /* Windows XP */
+ #define TUD_RNDIS_ITF_CLASS TUSB_CLASS_CDC
+ #define TUD_RNDIS_ITF_SUBCLASS CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
+ #define TUD_RNDIS_ITF_PROTOCOL CDC_COMM_PROTOCOL_MICROSOFT_RNDIS
+#else
+ /* Windows 7+ */
+ #define TUD_RNDIS_ITF_CLASS 0xE0
+ #define TUD_RNDIS_ITF_SUBCLASS 0x01
+ #define TUD_RNDIS_ITF_PROTOCOL 0x03
+#endif
+
+// Length of template descriptor: 66 bytes
+#define TUD_RNDIS_DESC_LEN (8+9+5+5+4+5+7+9+7+7)
+
+// RNDIS Descriptor Template
+// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+#define TUD_RNDIS_DESCRIPTOR(_itfnum, _stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize) \
+ /* Interface Association */\
+ 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, 0,\
+ /* CDC Control Interface */\
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUD_RNDIS_ITF_CLASS, TUD_RNDIS_ITF_SUBCLASS, TUD_RNDIS_ITF_PROTOCOL, _stridx,\
+ /* CDC-ACM Header */\
+ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\
+ /* CDC Call Management */\
+ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (uint8_t)((_itfnum) + 1),\
+ /* ACM */\
+ 4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 0,\
+ /* CDC Union */\
+ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\
+ /* Endpoint Notification */\
+ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 1,\
+ /* CDC Data Interface */\
+ 9, TUSB_DESC_INTERFACE, (uint8_t)((_itfnum)+1), 0, 2, TUSB_CLASS_CDC_DATA, 0, 0, 0,\
+ /* Endpoint In */\
+ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
+ /* Endpoint Out */\
+ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
+
+
+//------------- CDC-EEM -------------//
+
+// Length of template descriptor: 23 bytes
+#define TUD_CDC_EEM_DESC_LEN (9+7+7)
+
+// CDC-EEM Descriptor Template
+// Interface number, description string index, EP data address (out, in) and size.
+#define TUD_CDC_EEM_DESCRIPTOR(_itfnum, _stridx, _epout, _epin, _epsize) \
+ /* EEM Interface */\
+ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ETHERNET_EMULATION_MODEL, CDC_COMM_PROTOCOL_ETHERNET_EMULATION_MODEL, _stridx,\
+ /* Endpoint In */\
+ 7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
+ /* Endpoint Out */\
+ 7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0
+
+
#ifdef __cplusplus
}
#endif
diff --git a/src/tusb.h b/src/tusb.h
index 7dcddf645..55c105121 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -91,6 +91,10 @@
#if CFG_TUD_DFU_RT
#include "class/dfu/dfu_rt_device.h"
#endif
+
+ #if CFG_TUD_NET
+ #include "class/net/net_device.h"
+ #endif
#endif
diff --git a/src/tusb_option.h b/src/tusb_option.h
index 97f14532f..00d4a39dc 100644
--- a/src/tusb_option.h
+++ b/src/tusb_option.h
@@ -117,6 +117,15 @@
#define OPT_MODE_HIGH_SPEED 0x10 ///< High speed
/** @} */
+/** \defgroup group_supported_netif Supported Network Interface
+ * \ref CFG_TUD_NET must be defined to one of these
+ * @{ */
+#define OPT_NET_NONE 0 ///< No network interface
+#define OPT_NET_ECM 1 ///< CDC-ECM
+#define OPT_NET_RNDIS 2 ///< RNDIS
+#define OPT_NET_EEM 3 ///< CDC-EEM
+/** @} */
+
#ifndef CFG_TUSB_RHPORT0_MODE
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_NONE
#endif
@@ -204,6 +213,9 @@
#define CFG_TUD_DFU_RT 0
#endif
+#ifndef CFG_TUD_NET
+ #define CFG_TUD_NET 0
+#endif
//--------------------------------------------------------------------
// HOST OPTIONS