This is an automated email from the ASF dual-hosted git repository.

kasjer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit 0fd0ce44e3d6179be47adb6e9c732dcbec1f16ac
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Tue Oct 13 12:46:48 2026 +0200

    tinyusb/std_descriptors: Add MS OS 2.0 descriptors for NCM
    
    Windows 10+ has an inbox CDC-NCM driver but loads it automatically
    only when the device reports WINNCM compatible ID.  When USBD_NET is
    NCM add BOS descriptor with Microsoft OS 2.0 platform capability and
    serve descriptor set with WINNCM compatible ID for the NCM function.
    bcdUSB is 0x0201 in that case as required for BOS.
    
    Controlled by USBD_NET_MS_OS20 (default 1).  It can not be combined
    with USBD_WINDOWS_COMP_ID because Windows ignores MS OS 1.0
    descriptors once 2.0 are present.
    
    Assisted-by: Claude:claude-opus-5-5
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 .../tinyusb/std_descriptors/src/std_descriptors.c  | 75 ++++++++++++++++++++++
 hw/usb/tinyusb/std_descriptors/syscfg.yml          |  8 +++
 2 files changed, 83 insertions(+)

diff --git a/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c 
b/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
index 793d57cef..67002940c 100755
--- a/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
+++ b/hw/usb/tinyusb/std_descriptors/src/std_descriptors.c
@@ -187,7 +187,14 @@ tud_hid_set_report_cb(uint8_t itf, uint8_t report_id, 
hid_report_type_t report_t
 }
 #endif /* CFG_TUD_HID */
 
+/* Microsoft OS 2.0 descriptors for NCM, they need BOS (USB 2.01) */
+#define USBD_MS_OS20    (CFG_TUD_NCM && MYNEWT_VAL(USBD_NET_MS_OS20))
+
+#if USBD_MS_OS20
+#define USB_BCD     tu_htole16(0x201)
+#else
 #define USB_BCD     tu_htole16(0x200)
+#endif
 
 const tusb_desc_device_t desc_device = {
     .bLength            = sizeof(tusb_desc_device_t),
@@ -484,6 +491,74 @@ const char *string_desc_arr[] = {
 
 static uint16_t desc_string[MYNEWT_VAL(USBD_STRING_DESCRIPTOR_MAX_LENGTH) + 1];
 
+#if USBD_MS_OS20
+
+#if MYNEWT_VAL(USBD_WINDOWS_COMP_ID)
+#error "USBD_NET_MS_OS20 can not be used with USBD_WINDOWS_COMP_ID"
+#endif
+
+#define MS_OS_20_VENDOR_CODE    0x01
+/* wIndex of GET_MS_OS_20_DESCRIPTOR vendor request */
+#define MS_OS_20_DESCRIPTOR_INDEX   0x07
+#define MS_OS_20_DESC_LEN       (0x0A + 0x08 + 0x08 + 0x14)
+#define BOS_TOTAL_LEN           (TUD_BOS_DESC_LEN + \
+                                 TUD_BOS_MICROSOFT_OS_DESC_LEN)
+
+static const uint8_t desc_bos[] = {
+    TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1),
+    TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, MS_OS_20_VENDOR_CODE),
+};
+
+/*
+ * Microsoft OS 2.0 descriptor set: NCM function gets WINNCM compatible ID
+ * so Windows binds its inbox NCM driver (UsbNcm) automatically.
+ */
+static const uint8_t desc_ms_os_20[] = {
+    /* Set header: length, type, Windows version (8.1+), total length */
+    U16_TO_U8S_LE(0x000A), U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR),
+    U32_TO_U8S_LE(0x06030000), U16_TO_U8S_LE(MS_OS_20_DESC_LEN),
+    /* Configuration subset: length, type, config index, reserved, length */
+    U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION),
+    0, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A),
+    /* Function subset: length, type, first interface, reserved, length */
+    U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION),
+    ITF_NUM_NET, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN - 0x0A - 0x08),
+    /* Compatible ID: length, type, compatible ID, sub-compatible ID */
+    U16_TO_U8S_LE(0x0014), U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID),
+    'W', 'I', 'N', 'N', 'C', 'M', 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN,
+                 "MS OS 2.0 descriptor length mismatch");
+
+/*
+ * Invoked when received GET BOS DESCRIPTOR request
+ */
+const uint8_t *
+tud_descriptor_bos_cb(void)
+{
+    return desc_bos;
+}
+
+bool
+tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage,
+                           const tusb_control_request_t *request)
+{
+    if (request->bmRequestType_bit.type != TUSB_REQ_TYPE_VENDOR ||
+        request->bRequest != MS_OS_20_VENDOR_CODE ||
+        request->wIndex != MS_OS_20_DESCRIPTOR_INDEX) {
+        return false;
+    }
+    if (stage != CONTROL_STAGE_SETUP) {
+        return true;
+    }
+
+    return tud_control_xfer(rhport, request, (void *)(uintptr_t)desc_ms_os_20,
+                            sizeof(desc_ms_os_20));
+}
+#endif /* USBD_MS_OS20 */
+
 #if MYNEWT_VAL(USBD_WINDOWS_COMP_ID)
 
 #define MICROSOFT_OS_STRING_DESCRIPTOR  0xEE
diff --git a/hw/usb/tinyusb/std_descriptors/syscfg.yml 
b/hw/usb/tinyusb/std_descriptors/syscfg.yml
index 0ad95a3fa..78b6115c6 100644
--- a/hw/usb/tinyusb/std_descriptors/syscfg.yml
+++ b/hw/usb/tinyusb/std_descriptors/syscfg.yml
@@ -386,6 +386,13 @@ syscfg.defs:
             Number of NCM transfer block buffers in each direction.  On full
             speed 2 can improve throughput at the cost of RAM.
         value: 1
+    USBD_NET_MS_OS20:
+        description: >
+            Add BOS and Microsoft OS 2.0 descriptors with WINNCM compatible
+            ID for NCM function, so Windows loads its NCM driver without
+            manual installation.  Can not be used with USBD_WINDOWS_COMP_ID
+            (Windows ignores MS OS 1.0 descriptors when 2.0 are present).
+        value: 1
 
     USBD_WINDOWS_COMP_ID:
         description: >
@@ -411,6 +418,7 @@ syscfg.restrictions:
     - '(CFG_TUSB_DEBUG == 0) || (USBD_STACK_SIZE >= 400)'
     - '((USBD_NET != "NCM") && (USBD_NET != "ECM") && (USBD_NET != "RNDIS")) ||
        USBD_COMPOSITE_DEVICE'
+    - '(USBD_NET != "NCM") || !USBD_NET_MS_OS20 || !USBD_WINDOWS_COMP_ID'
 
 syscfg.vals.USBD_COMPOSITE_DEVICE:
     USBD_DEVICE_CLASS: TUSB_CLASS_MISC

Reply via email to