summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorZixun LI <[email protected]>2026-04-30 15:56:23 +0200
committerHiFiPHile <[email protected]>2026-05-01 13:54:22 +0200
commit8db6084acac03acc1b98721f78d22587968ed5b2 (patch)
tree5acc28431bf95f7d0d64c9f7b7ee216936d01c48 /src
parentddb81076a4f7c38b0958a97d76aa072180902b6f (diff)
ncm: implement GetNtbInputSize request
Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/class/net/ncm.h14
-rw-r--r--src/class/net/ncm_device.c87
-rw-r--r--src/device/usbd.h8
3 files changed, 61 insertions, 48 deletions
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, \