summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2024-11-28 16:23:41 +0700
committerGitHub <[email protected]>2024-11-28 16:23:41 +0700
commit6b36df3e396c2eaec5d741ca00b1cdf3d19baffb (patch)
tree3c0fdd0bc55c3b53fc19ee31921419e9bb3398ea /examples
parentc6dccffa2d81f692ca3f9729978ee37f7ed6281d (diff)
parent79373afaafffe64dd2bb33d725b88137c3d4ee6f (diff)
Merge pull request #2829 from HiFiPhile/lwip_fix
net_lwip_webserver example fix and improvement
Diffstat (limited to 'examples')
-rw-r--r--examples/device/net_lwip_webserver/src/main.c9
-rw-r--r--examples/device/net_lwip_webserver/src/usb_descriptors.c109
2 files changed, 115 insertions, 3 deletions
diff --git a/examples/device/net_lwip_webserver/src/main.c b/examples/device/net_lwip_webserver/src/main.c
index 8af7a9de6..36f402332 100644
--- a/examples/device/net_lwip_webserver/src/main.c
+++ b/examples/device/net_lwip_webserver/src/main.c
@@ -194,8 +194,13 @@ uint16_t tud_network_xmit_cb(uint8_t *dst, void *ref, uint16_t arg) {
static void service_traffic(void) {
/* handle any packet received by tud_network_recv_cb() */
if (received_frame) {
- ethernet_input(received_frame, &netif_data);
- pbuf_free(received_frame);
+ // Surrender ownership of our pbuf unless there was an error
+ // Only call pbuf_free if not Ok else it will panic with "pbuf_free: p->ref > 0"
+ // or steal it from whatever took ownership of it with undefined consequences.
+ // See: https://savannah.nongnu.org/patch/index.php?10121
+ if (ethernet_input(received_frame, &netif_data)!=ERR_OK) {
+ pbuf_free(received_frame);
+ }
received_frame = NULL;
tud_network_recv_renew();
}
diff --git a/examples/device/net_lwip_webserver/src/usb_descriptors.c b/examples/device/net_lwip_webserver/src/usb_descriptors.c
index d061f5076..cd800f521 100644
--- a/examples/device/net_lwip_webserver/src/usb_descriptors.c
+++ b/examples/device/net_lwip_webserver/src/usb_descriptors.c
@@ -72,8 +72,11 @@ tusb_desc_device_t const desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
+#if CFG_TUD_NCM
+ .bcdUSB = 0x0201,
+#else
.bcdUSB = 0x0200,
-
+#endif
// Use Interface Association Descriptor (IAD) device class
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
@@ -188,6 +191,110 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
return (index < CONFIG_ID_COUNT) ? configuration_arr[index] : NULL;
}
+#if CFG_TUD_NCM
+//--------------------------------------------------------------------+
+// BOS Descriptor
+//--------------------------------------------------------------------+
+
+/* Used to automatically load the NCM driver on Windows 10, otherwise manual driver install is needed.
+ Associate NCM interface with WINNCM driver. */
+
+/* Microsoft OS 2.0 registry property descriptor
+Per MS requirements https://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
+device should create DeviceInterfaceGUIDs. It can be done by driver and
+in case of real PnP solution device should expose MS "Microsoft OS 2.0
+registry property descriptor". Such descriptor can insert any record
+into Windows registry per device/configuration/interface. In our case it
+will insert "DeviceInterfaceGUIDs" multistring property.
+
+GUID is freshly generated and should be OK to use.
+
+https://developers.google.com/web/fundamentals/native-hardware/build-for-webusb/
+(Section Microsoft OS compatibility descriptors)
+*/
+
+#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN)
+
+#define MS_OS_20_DESC_LEN 0xB2
+
+// BOS Descriptor is required for webUSB
+uint8_t const desc_bos[] =
+{
+ // total length, number of device caps
+ TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 1),
+
+ // Microsoft OS 2.0 descriptor
+ TUD_BOS_MS_OS_20_DESCRIPTOR(MS_OS_20_DESC_LEN, 1)
+};
+
+uint8_t const * tud_descriptor_bos_cb(void)
+{
+ return desc_bos;
+}
+
+uint8_t const desc_ms_os_20[] =
+{
+ // Set header: length, type, windows version, 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 header: length, type, configuration index, reserved, configuration total 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 header: length, type, first interface, reserved, subset length
+ U16_TO_U8S_LE(0x0008), U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), ITF_NUM_CDC, 0, U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08),
+
+ // MS OS 2.0 Compatible ID descriptor: 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', 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
+
+ // MS OS 2.0 Registry property descriptor: length, type
+ U16_TO_U8S_LE(MS_OS_20_DESC_LEN-0x0A-0x08-0x08-0x14), U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY),
+ U16_TO_U8S_LE(0x0007), U16_TO_U8S_LE(0x002A), // wPropertyDataType, wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
+ 'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
+ 'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
+ U16_TO_U8S_LE(0x0050), // wPropertyDataLength
+ //bPropertyData: {12345678-0D08-43FD-8B3E-127CA8AFFF9D}
+ '{', 0x00, '1', 0x00, '2', 0x00, '3', 0x00, '4', 0x00, '5', 0x00, '6', 0x00, '7', 0x00, '8', 0x00, '-', 0x00,
+ '0', 0x00, 'D', 0x00, '0', 0x00, '8', 0x00, '-', 0x00, '4', 0x00, '3', 0x00, 'F', 0x00, 'D', 0x00, '-', 0x00,
+ '8', 0x00, 'B', 0x00, '3', 0x00, 'E', 0x00, '-', 0x00, '1', 0x00, '2', 0x00, '7', 0x00, 'C', 0x00, 'A', 0x00,
+ '8', 0x00, 'A', 0x00, 'F', 0x00, 'F', 0x00, 'F', 0x00, '9', 0x00, 'D', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+TU_VERIFY_STATIC(sizeof(desc_ms_os_20) == MS_OS_20_DESC_LEN, "Incorrect size");
+
+// Invoked when a control transfer occurred on an interface of this class
+// Driver response accordingly to the request and the transfer stage (setup/data/ack)
+// return false to stall control endpoint (e.g unsupported request)
+bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
+ // nothing to with DATA & ACK stage
+ if (stage != CONTROL_STAGE_SETUP) return true;
+
+ switch (request->bmRequestType_bit.type) {
+ case TUSB_REQ_TYPE_VENDOR:
+ switch (request->bRequest) {
+ case 1:
+ if (request->wIndex == 7) {
+ // Get Microsoft OS 2.0 compatible descriptor
+ uint16_t total_len;
+ memcpy(&total_len, desc_ms_os_20 + 8, 2);
+
+ return tud_control_xfer(rhport, request, (void*)(uintptr_t)desc_ms_os_20, total_len);
+ } else {
+ return false;
+ }
+
+ default: break;
+ }
+ break;
+
+ default: break;
+ }
+
+ // stall unknown request
+ return false;
+}
+
+#endif
//--------------------------------------------------------------------+
// String Descriptors
//--------------------------------------------------------------------+