From 0649b18b2e8b2e76b38f6280796ba48a51882eac Mon Sep 17 00:00:00 2001 From: nminaylov Date: Fri, 24 Apr 2026 22:39:02 +0300 Subject: NCM packet filter support --- src/class/net/ncm_device.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/class') diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 405e4467b..a1ad9b205 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -997,6 +997,11 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t tud_control_xfer(rhport, request, (void *) (uintptr_t) &ntb_parameters, sizeof(ntb_parameters)); } break; + case NCM_SET_ETHERNET_PACKET_FILTER: { + tud_control_xfer(rhport, request, NULL, 0); + } break; + + // unsupported request default: return false; -- cgit v1.3.1 From 2cdd98104ece869f3a5eda3dd9c2b02f5b4c318d Mon Sep 17 00:00:00 2001 From: nminaylov Date: Mon, 27 Apr 2026 14:40:18 +0300 Subject: NCM caps enum --- src/class/net/ncm_device.c | 3 +-- src/class/net/net_device.h | 10 ++++++++++ src/device/usbd.h | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) (limited to 'src/class') diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index a1ad9b205..83e8bffab 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -999,8 +999,7 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t case NCM_SET_ETHERNET_PACKET_FILTER: { tud_control_xfer(rhport, request, NULL, 0); - } break; - + } break; // unsupported request default: diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 96c03fd61..61ff6b2d6 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -50,6 +50,16 @@ typedef enum NCM_DATA_PROTOCOL_NETWORK_TRANSFER_BLOCK = 0x01 } ncm_data_interface_protocol_code_t; +// Table 5.2 bmNetworkCapabilities bits +typedef enum { + NCM_NETWORK_CAPS_NONE = 0x00, + NCM_NETWORK_CAPS_ETH_FILTER = (1 << 0), + NCM_NETWORK_CAPS_NET_ADDRESS = (1 << 1), + NCM_NETWORK_CAPS_ENCAP_COMMAND = (1 << 2), + NCM_NETWORK_CAPS_MAX_DATAGRAM_SIZE = (1 << 3), + NCM_NETWORK_CAPS_CRC_MODE = (1 << 4), + NCM_NETWORK_CAPS_NTB_INPUT_SIZE = (1 << 5) +} ncm_network_capabilities_t; #ifdef __cplusplus extern "C" { diff --git a/src/device/usbd.h b/src/device/usbd.h index 45beb7c4c..96144350e 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -1023,6 +1023,9 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // CDC-NCM Descriptor Templates //--------------------------------------------------------------------+ +// NCM Capabilities, bitmap of NCM_NETWORK_CAPS_* bits. +#define TUD_CDC_NCM_CAPS (NCM_NETWORK_CAPS_ETH_FILTER) + // Length of template descriptor #define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) @@ -1040,7 +1043,7 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ /* CDC-NCM 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, \ /* CDC-NCM Functional Descriptor */\ - 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), 0x01, \ + 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), TUD_CDC_NCM_CAPS, \ /* Endpoint Notification */\ 7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 50,\ /* CDC Data Interface (default inactive) */\ -- cgit v1.3.1 From 7cfa0d1b970b6e276e0eca3eee2de43aa3b7c443 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 30 Apr 2026 14:56:13 +0200 Subject: add packet filter callback Co-authored-by: Copilot Signed-off-by: Zixun LI --- src/class/net/ecm_rndis_device.c | 8 ++++++++ src/class/net/ncm_device.c | 8 ++++++++ src/class/net/net_device.h | 3 +++ 3 files changed, 19 insertions(+) (limited to 'src/class') diff --git a/src/class/net/ecm_rndis_device.c b/src/class/net/ecm_rndis_device.c index eaa82c187..5464fe25d 100644 --- a/src/class/net/ecm_rndis_device.c +++ b/src/class/net/ecm_rndis_device.c @@ -81,6 +81,13 @@ CFG_TUD_MEM_SECTION static netd_epbuf_t _netd_epbuf; static bool can_xmit; static bool ecm_link_is_up = true; // Store link state for ECM mode +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_network_set_packet_filter_cb(uint16_t packet_filter) { + (void) packet_filter; +} + void tud_network_recv_renew(void) { usbd_edpt_xfer(0, _netd_itf.ep_out, _netd_epbuf.rx, NETD_PACKET_SIZE, false); } @@ -285,6 +292,7 @@ bool netd_control_xfer_cb (uint8_t rhport, uint8_t stage, tusb_control_request_t if (_netd_itf.ecm_mode) { /* the only required CDC-ECM Management Element Request is SetEthernetPacketFilter */ if (0x43 /* SET_ETHERNET_PACKET_FILTER */ == request->bRequest) { + tud_network_set_packet_filter_cb(request->wValue); tud_control_xfer(rhport, request, NULL, 0); // Only send connection notification if link is up if (ecm_link_is_up) { diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 83e8bffab..85895361f 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -138,6 +138,13 @@ typedef struct { static ncm_interface_t ncm_interface; CFG_TUD_MEM_SECTION static ncm_epbuf_t ncm_epbuf; +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tud_network_set_packet_filter_cb(uint16_t packet_filter) { + (void) packet_filter; +} + /** * This is the NTB parameter structure * @@ -998,6 +1005,7 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t } break; case NCM_SET_ETHERNET_PACKET_FILTER: { + tud_network_set_packet_filter_cb(request->wValue); tud_control_xfer(rhport, request, NULL, 0); } break; diff --git a/src/class/net/net_device.h b/src/class/net/net_device.h index 61ff6b2d6..e0d235ebe 100644 --- a/src/class/net/net_device.h +++ b/src/class/net/net_device.h @@ -106,6 +106,9 @@ extern uint8_t tud_network_mac_address[6]; //------------- NCM -------------// +// Optional callback: informs the application about host requested packet filter bits +void tud_network_set_packet_filter_cb(uint16_t packet_filter); + // Set the network link state (up/down) and notify the host void tud_network_link_state(uint8_t rhport, bool is_up); -- cgit v1.3.1 From ddb81076a4f7c38b0958a97d76aa072180902b6f Mon Sep 17 00:00:00 2001 From: Elwin Huang Date: Wed, 29 Apr 2026 11:07:44 +0800 Subject: ncm: Implement SetNtbInputSize request According to NCM standard 7.2.7, the device should tell the host its maximum size of NTB. Implement SetNtbInputSize according to it. Without this commit, some OS may failed to enumerate the NCM device (e.g., IOS 26). Signed-off-by: Elwin Huang --- src/class/net/ncm_device.c | 82 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 8 deletions(-) (limited to 'src/class') diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 85895361f..7240c50aa 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -118,6 +118,16 @@ typedef struct { bool notification_xmit_is_running; // notification is currently transmitted bool link_is_up; // current link state + // host-configured transmit limits + uint32_t xmit_max_ntb_size; // maximum NTB size device may send + uint16_t xmit_max_datagrams; // maximum datagrams per NTB device may send + uint8_t ntb_input_size_len; // last SET_NTB_INPUT_SIZE wLength + struct { + uint32_t dwNtbInMaxSize; + uint16_t wNtbInMaxDatagrams; + uint16_t wReserved; + } ntb_input_size; + // misc bool tud_network_recv_renew_active; // tud_network_recv_renew() is active (avoid recursive invocations) bool tud_network_recv_renew_process_again; // tud_network_recv_renew() should process again @@ -415,10 +425,14 @@ static bool xmit_requested_datagram_fits_into_current_ntb(uint16_t datagram_size if (ncm_interface.xmit_glue_ntb == NULL) { return false; } - if (ncm_interface.xmit_glue_ntb_datagram_ndx >= CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB) { + uint16_t max_datagrams = ncm_interface.xmit_max_datagrams; + if (max_datagrams == 0) { + max_datagrams = CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB; + } + if (ncm_interface.xmit_glue_ntb_datagram_ndx >= max_datagrams) { return false; } - if (ncm_interface.xmit_glue_ntb->nth.wBlockLength + datagram_size + XMIT_ALIGN_OFFSET(datagram_size) > CFG_TUD_NCM_IN_NTB_MAX_SIZE) { + if (ncm_interface.xmit_glue_ntb->nth.wBlockLength + datagram_size + XMIT_ALIGN_OFFSET(datagram_size) > ncm_interface.xmit_max_ntb_size) { return false; } return true; @@ -715,7 +729,7 @@ static void recv_transfer_datagram_to_glue_logic(void) { bool tud_network_can_xmit(uint16_t size) { TU_LOG_DRV("tud_network_can_xmit(%d)\n", size); - TU_ASSERT(size <= CFG_TUD_NCM_IN_NTB_MAX_SIZE - (sizeof(nth16_t) + sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)), false); + TU_ASSERT(size <= ncm_interface.xmit_max_ntb_size - (sizeof(nth16_t) + sizeof(ndp16_t) + 2 * sizeof(ndp16_datagram_t)), false); if (xmit_requested_datagram_fits_into_current_ntb(size) || xmit_setup_next_glue_ntb()) { // -> everything is fine @@ -835,6 +849,9 @@ void netd_init(void) { memset(&ncm_interface, 0, sizeof(ncm_interface)); + ncm_interface.xmit_max_ntb_size = CFG_TUD_NCM_IN_NTB_MAX_SIZE; + ncm_interface.xmit_max_datagrams = CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB; + for (int i = 0; i < XMIT_NTB_N; ++i) { ncm_interface.xmit_free_ntb[i] = &ncm_epbuf.xmit[i].ntb; } @@ -961,12 +978,12 @@ bool netd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_ * At startup transmission of notification packets are done here. */ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { - if (stage != CONTROL_STAGE_SETUP) { - return true; - } switch (request->bmRequestType_bit.type) { case TUSB_REQ_TYPE_STANDARD: + if (stage != CONTROL_STAGE_SETUP) { + return true; + } switch (request->bRequest) { case TUSB_REQ_GET_INTERFACE: { @@ -1000,21 +1017,70 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t TU_VERIFY(ncm_interface.itf_num == request->wIndex, false); switch (request->bRequest) { case NCM_GET_NTB_PARAMETERS: { + if (stage != CONTROL_STAGE_SETUP) { + return true; + } // transfer NTB parameters to host. tud_control_xfer(rhport, request, (void *) (uintptr_t) &ntb_parameters, sizeof(ntb_parameters)); } break; case NCM_SET_ETHERNET_PACKET_FILTER: { + if (stage != CONTROL_STAGE_SETUP) { + return true; + } tud_network_set_packet_filter_cb(request->wValue); tud_control_xfer(rhport, request, NULL, 0); } break; - // unsupported request + case NCM_SET_NTB_INPUT_SIZE: { + if (stage == CONTROL_STAGE_SETUP) { + if (request->wLength != 4 && request->wLength != 8) { + return false; + } + + ncm_interface.ntb_input_size_len = (uint8_t) request->wLength; + memset(&ncm_interface.ntb_input_size, 0, sizeof(ncm_interface.ntb_input_size)); + + // wLength == 8 -> the NTB Input Size Structure + // wLength == 4 -> dwNtbInMaxSize field of the NTB Input Size Structure. + if (request->wLength == 4) { + tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size.dwNtbInMaxSize, 4); + } else { + tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size, 8); + } + } else if (stage == CONTROL_STAGE_ACK) { + uint32_t requested_size = ncm_interface.ntb_input_size.dwNtbInMaxSize; + uint16_t requested_datagrams = 0; + uint32_t min_ntb_size = 2048u; + uint32_t new_ntb_size = 0; + uint16_t new_datagrams = 0; + + if (requested_size < min_ntb_size || requested_size > CFG_TUD_NCM_IN_NTB_MAX_SIZE) { + return false; + } + new_ntb_size = requested_size; + + if (ncm_interface.ntb_input_size_len == 8) { + requested_datagrams = ncm_interface.ntb_input_size.wNtbInMaxDatagrams; + } + + if (requested_datagrams > CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB) { + return false; + } + new_datagrams = requested_datagrams; + + ncm_interface.xmit_max_ntb_size = new_ntb_size; + ncm_interface.xmit_max_datagrams = new_datagrams; + } + } break; + + // unsupported request default: return false; } break; - // unsupported request + + // unsupported request default: return false; } -- cgit v1.3.1 From 8db6084acac03acc1b98721f78d22587968ed5b2 Mon Sep 17 00:00:00 2001 From: Zixun LI Date: Thu, 30 Apr 2026 15:56:23 +0200 Subject: ncm: implement GetNtbInputSize request Signed-off-by: HiFiPHile --- .../net_lwip_webserver/src/usb_descriptors.c | 2 +- src/class/net/ncm.h | 14 ++++ src/class/net/ncm_device.c | 87 +++++++++++----------- src/device/usbd.h | 8 +- 4 files changed, 62 insertions(+), 49 deletions(-) (limited to 'src/class') diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c index b194b9c5a..0c6c11611 100644 --- a/examples/device/net_lwip_webserver/src/usb_descriptors.c +++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c @@ -164,7 +164,7 @@ static uint8_t const ncm_configuration[] = { // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_CDC, STRID_INTERFACE, STRID_MAC, EPNUM_NET_NOTIF, 64, EPNUM_NET_OUT, EPNUM_NET_IN, CFG_TUD_NET_ENDPOINT_SIZE, - CFG_TUD_NET_MTU, NCM_NETWORK_CAPS_ETH_FILTER), + CFG_TUD_NET_MTU, (uint8_t)((uint8_t)NCM_NETWORK_CAPS_ETH_FILTER | (uint8_t)NCM_NETWORK_CAPS_NTB_INPUT_SIZE)), }; #endif diff --git a/src/class/net/ncm.h b/src/class/net/ncm.h index 8989fe0b4..27ff89b72 100644 --- a/src/class/net/ncm.h +++ b/src/class/net/ncm.h @@ -161,4 +161,18 @@ typedef struct { uint32_t uplink; } ncm_notify_t; +typedef struct TU_ATTR_PACKED { + uint8_t bFunctionLength; + uint8_t bDescriptorType; + uint8_t bDescriptorSubType; + uint16_t bcdNcmVersion; + uint8_t bmCapabilities; +} tusb_desc_cdc_ncm_func_t; + +typedef struct TU_ATTR_PACKED { + uint32_t dwNtbInMaxSize; + uint16_t wNtbInMaxDatagrams; + uint16_t wReserved; +} ncm_ntb_input_size_t; + #endif diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 7240c50aa..e16b0523f 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -119,14 +119,10 @@ typedef struct { bool link_is_up; // current link state // host-configured transmit limits - uint32_t xmit_max_ntb_size; // maximum NTB size device may send + uint8_t bm_capabilities; + uint16_t xmit_max_ntb_size; // maximum NTB size device may send uint16_t xmit_max_datagrams; // maximum datagrams per NTB device may send - uint8_t ntb_input_size_len; // last SET_NTB_INPUT_SIZE wLength - struct { - uint32_t dwNtbInMaxSize; - uint16_t wNtbInMaxDatagrams; - uint16_t wReserved; - } ntb_input_size; + ncm_ntb_input_size_t ntb_input_size; // misc bool tud_network_recv_renew_active; // tud_network_recv_renew() is active (avoid recursive invocations) @@ -425,14 +421,10 @@ static bool xmit_requested_datagram_fits_into_current_ntb(uint16_t datagram_size if (ncm_interface.xmit_glue_ntb == NULL) { return false; } - uint16_t max_datagrams = ncm_interface.xmit_max_datagrams; - if (max_datagrams == 0) { - max_datagrams = CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB; - } - if (ncm_interface.xmit_glue_ntb_datagram_ndx >= max_datagrams) { + if (ncm_interface.xmit_glue_ntb_datagram_ndx >= ncm_interface.xmit_max_datagrams) { return false; } - if (ncm_interface.xmit_glue_ntb->nth.wBlockLength + datagram_size + XMIT_ALIGN_OFFSET(datagram_size) > ncm_interface.xmit_max_ntb_size) { + if (ncm_interface.xmit_glue_ntb->nth.wBlockLength + datagram_size + (uint32_t)XMIT_ALIGN_OFFSET(datagram_size) > (uint32_t)ncm_interface.xmit_max_ntb_size) { return false; } return true; @@ -902,10 +894,14 @@ uint16_t netd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16 ncm_interface.itf_num = itf_desc->bInterfaceNumber;// management interface - // skip the two first entries and the following TUSB_DESC_CS_INTERFACE entries uint16_t drv_len = sizeof(tusb_desc_interface_t); uint8_t const *p_desc = tu_desc_next(itf_desc); while (tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && drv_len <= max_len) { + if (tu_desc_subtype(p_desc) == CDC_FUNC_DESC_NCM) { + TU_ASSERT(tu_desc_len(p_desc) >= sizeof(tusb_desc_cdc_ncm_func_t), 0); + tusb_desc_cdc_ncm_func_t const *ncm_func = (tusb_desc_cdc_ncm_func_t const *) p_desc; + ncm_interface.bm_capabilities = ncm_func->bmCapabilities; + } drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } @@ -1028,49 +1024,52 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t if (stage != CONTROL_STAGE_SETUP) { return true; } + + TU_VERIFY(ncm_interface.bm_capabilities & NCM_NETWORK_CAPS_ETH_FILTER, false); tud_network_set_packet_filter_cb(request->wValue); tud_control_xfer(rhport, request, NULL, 0); } break; - case NCM_SET_NTB_INPUT_SIZE: { - if (stage == CONTROL_STAGE_SETUP) { - if (request->wLength != 4 && request->wLength != 8) { - return false; - } + case NCM_GET_NTB_INPUT_SIZE: { + if (stage != CONTROL_STAGE_SETUP) { + return true; + } - ncm_interface.ntb_input_size_len = (uint8_t) request->wLength; - memset(&ncm_interface.ntb_input_size, 0, sizeof(ncm_interface.ntb_input_size)); + TU_VERIFY(request->wLength >=4, false); - // wLength == 8 -> the NTB Input Size Structure - // wLength == 4 -> dwNtbInMaxSize field of the NTB Input Size Structure. - if (request->wLength == 4) { - tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size.dwNtbInMaxSize, 4); - } else { - tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size, 8); - } - } else if (stage == CONTROL_STAGE_ACK) { - uint32_t requested_size = ncm_interface.ntb_input_size.dwNtbInMaxSize; - uint16_t requested_datagrams = 0; - uint32_t min_ntb_size = 2048u; - uint32_t new_ntb_size = 0; - uint16_t new_datagrams = 0; + uint8_t resp_len = (request->wLength >= 8 && (ncm_interface.bm_capabilities & NCM_NETWORK_CAPS_NTB_INPUT_SIZE)) ? 8 : 4; - if (requested_size < min_ntb_size || requested_size > CFG_TUD_NCM_IN_NTB_MAX_SIZE) { - return false; - } - new_ntb_size = requested_size; + ncm_ntb_input_size_t ntb_input_size = { + .dwNtbInMaxSize = ncm_interface.xmit_max_ntb_size, + .wNtbInMaxDatagrams = ncm_interface.xmit_max_datagrams + }; + tud_control_xfer(rhport, request, &ntb_input_size, resp_len); + } break; - if (ncm_interface.ntb_input_size_len == 8) { - requested_datagrams = ncm_interface.ntb_input_size.wNtbInMaxDatagrams; + case NCM_SET_NTB_INPUT_SIZE: { + if (stage == CONTROL_STAGE_SETUP) { + /* wLength == 8 -> the NTB Input Size Structure (if NCM_NETWORK_CAPS_NTB_INPUT_SIZE is set) + wLength == 4 -> dwNtbInMaxSize field of the NTB Input Size Structure. */ + TU_VERIFY(request->wLength == 4 || request->wLength == 8, false); + if (request->wLength == 8) { + TU_VERIFY(ncm_interface.bm_capabilities & NCM_NETWORK_CAPS_NTB_INPUT_SIZE, false); } - if (requested_datagrams > CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB) { + tu_memclr(&ncm_interface.ntb_input_size, sizeof(ncm_interface.ntb_input_size)); + tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size, request->wLength); + } else if (stage == CONTROL_STAGE_ACK) { + /* CDC-NCM 1.0 Table 6-4, up to NTB16 size */ + const uint32_t requested_size = ncm_interface.ntb_input_size.dwNtbInMaxSize; + if (requested_size < 2048u || requested_size > 65535u) { return false; } - new_datagrams = requested_datagrams; + ncm_interface.xmit_max_ntb_size = tu_min16(requested_size, CFG_TUD_NCM_IN_NTB_MAX_SIZE); - ncm_interface.xmit_max_ntb_size = new_ntb_size; - ncm_interface.xmit_max_datagrams = new_datagrams; + if (ncm_interface.ntb_input_size.wNtbInMaxDatagrams == 0 || ncm_interface.ntb_input_size.wNtbInMaxDatagrams > CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB) { + ncm_interface.xmit_max_datagrams = CFG_TUD_NCM_IN_MAX_DATAGRAMS_PER_NTB; + } else { + ncm_interface.xmit_max_datagrams = ncm_interface.ntb_input_size.wNtbInMaxDatagrams; + } } } break; diff --git a/src/device/usbd.h b/src/device/usbd.h index a960e2c79..5a21c7039 100644 --- a/src/device/usbd.h +++ b/src/device/usbd.h @@ -1026,18 +1026,18 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ // Length of template descriptor #define TUD_CDC_NCM_DESC_LEN (8+9+5+5+13+6+7+9+9+7+7) -// CDC-ECM Descriptor Template +// CDC-NCM 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, capability. #define TUD_CDC_NCM_DESCRIPTOR(_itfnum, _desc_stridx, _mac_stridx, _ep_notif, _ep_notif_size, _epout, _epin, _epsize, _maxsegmentsize, _capability) \ /* Interface Association */\ 8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, 0,\ /* CDC Control Interface */\ 9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_NETWORK_CONTROL_MODEL, 0, _desc_stridx,\ - /* CDC-NCM Header */\ + /* CDC Header */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0110),\ - /* CDC-NCM Union */\ + /* CDC Union */\ 5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (uint8_t)((_itfnum) + 1),\ - /* CDC-NCM Functional Descriptor */\ + /* CDC Ethernet Networking 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, \ /* CDC-NCM Functional Descriptor */\ 6, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_NCM, U16_TO_U8S_LE(0x0100), _capability, \ -- cgit v1.3.1 From 2471cbc28618971974fcbbb019a37cf5892253e2 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Fri, 8 May 2026 13:53:09 +0200 Subject: fixup Signed-off-by: HiFiPhile --- src/class/net/ncm_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/class') diff --git a/src/class/net/ncm_device.c b/src/class/net/ncm_device.c index 336d8ad3e..a78e472c2 100644 --- a/src/class/net/ncm_device.c +++ b/src/class/net/ncm_device.c @@ -1028,7 +1028,9 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t return true; } - TU_VERIFY(ncm_interface.bm_capabilities & NCM_NETWORK_CAPS_ETH_FILTER, false); + // Some hosts issue this request even if ETH_FILTER is not advertised, + // see https://bugzilla.kernel.org/show_bug.cgi?id=217290 + tud_network_set_packet_filter_cb(request->wValue); tud_control_xfer(rhport, request, NULL, 0); } break; @@ -1060,7 +1062,7 @@ bool netd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t tu_memclr(&ncm_interface.ntb_input_size, sizeof(ncm_interface.ntb_input_size)); tud_control_xfer(rhport, request, &ncm_interface.ntb_input_size, request->wLength); - } else if (stage == CONTROL_STAGE_ACK) { + } else if (stage == CONTROL_STAGE_DATA) { /* CDC-NCM 1.0 Table 6-4, up to NTB16 size */ const uint32_t requested_size = ncm_interface.ntb_input_size.dwNtbInMaxSize; if (requested_size < 2048u || requested_size > 65535u) { -- cgit v1.3.1