aboutsummaryrefslogtreecommitdiffstats
path: root/Demos/Device
diff options
context:
space:
mode:
authorDean Camera <dean@fourwalledcubicle.com>2018-04-22 16:08:12 +1000
committerDean Camera <dean@fourwalledcubicle.com>2018-04-22 16:08:12 +1000
commite9d9fcde04411001ba8dff07b512fdc46ce13e47 (patch)
tree41d1c6919e49dd49c6fb1426d7ff6a6aa708643b /Demos/Device
parent086975bd9442e86693fce2d16f003c4ad170cdac (diff)
downloadlufa-e9d9fcde04411001ba8dff07b512fdc46ce13e47.tar.gz
lufa-e9d9fcde04411001ba8dff07b512fdc46ce13e47.tar.bz2
lufa-e9d9fcde04411001ba8dff07b512fdc46ce13e47.zip
Add MS OS Compatibility descriptors to RNDIS demos for driverless install on Windows.
Diffstat (limited to 'Demos/Device')
-rw-r--r--Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c51
-rw-r--r--Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h22
-rw-r--r--Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c3
-rw-r--r--Demos/Device/LowLevel/RNDISEthernet/Descriptors.c51
-rw-r--r--Demos/Device/LowLevel/RNDISEthernet/Descriptors.h22
-rw-r--r--Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c3
6 files changed, 148 insertions, 4 deletions
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c b/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c
index 494150349..8e709cee9 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c
+++ b/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.c
@@ -46,7 +46,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
- .USBSpecification = VERSION_BCD(1,1,0),
+ .USBSpecification = VERSION_BCD(2,0,0),
.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_NoSpecificSubclass,
.Protocol = CDC_CSCP_NoSpecificProtocol,
@@ -55,7 +55,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.VendorID = 0x03EB,
.ProductID = 0x204C,
- .ReleaseNumber = VERSION_BCD(0,0,1),
+ .ReleaseNumber = VERSION_BCD(0,0,2),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
@@ -192,6 +192,32 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR
*/
const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"LUFA RNDIS CDC Demo");
+/** Microsoft OS Compatibility string descriptor. This is a special string descriptor that Microsoft based OS hosts
+ * will query at string descriptor ID 0xEE on initial enumeration, to test if the device supports the Microsoft OS
+ * Compatibility descriptor extensions (used to give the host additional information on the device's general class
+ * compatibility for driver-less installation).
+ */
+const USB_Descriptor_String_t PROGMEM MSConpatibilityString = USB_STRING_DESCRIPTOR_ARRAY('M','S','F','T','1','0','0', VENDOR_REQUEST_ID_MS_COMPAT);
+
+/** Microsoft OS Compatibility 1.0 descriptor. This is a special descriptor returned by the device on vendor request
+ * from the host, giving the OS additional compatibility information. This allows the host to automatically install
+ * the appropriate driver for various devices which share a common USB class (in this case RNDIS, which uses the
+ * CDC-ACM class usually used by virtual to serial adapters).
+ */
+const USB_Descriptor_MSCompatibility_t PROGMEM MSCompatibilityDescriptor =
+ {
+ .dwLength = sizeof(USB_Descriptor_MSCompatibility_t),
+ .bcdVersion = VERSION_BCD(1,0,0),
+ .wIndex = 4,
+ .bCount = 1,
+ .bReserved = { 0 },
+ .bFirstInterfaceNumber = INTERFACE_ID_CDC_CCI,
+ .bReserved2 = 1, // Must always be 1 according to spec
+ .compatibleID = "RNDIS",
+ .subCompatibleID = "5162001",
+ .bReserved3 = { 0 },
+ };
+
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
@@ -233,6 +259,10 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
Address = &ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
+ case STRING_ID_MS_Compat:
+ Address = &MSConpatibilityString;
+ Size = pgm_read_byte(&MSConpatibilityString.Header.Size);
+ break;
}
break;
@@ -242,3 +272,20 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
return Size;
}
+/** Sends the special Microsoft OS Compatibility Descriptor to the host PC, if
+ * the host is requesting it.
+ */
+void CheckIfMSCompatibilityDescriptorRequest(void)
+{
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE))
+ {
+ if (USB_ControlRequest.bRequest == VENDOR_REQUEST_ID_MS_COMPAT)
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the OS compatibility descriptor to the control endpoint */
+ Endpoint_Write_Control_PStream_LE(&MSCompatibilityDescriptor, sizeof(MSCompatibilityDescriptor));
+ Endpoint_ClearOUT();
+ }
+ }
+}
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h b/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h
index 082f44afc..56a3acd23 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h
+++ b/Demos/Device/ClassDriver/RNDISEthernet/Descriptors.h
@@ -59,6 +59,10 @@
/** Size in bytes of the CDC data IN and OUT endpoints. */
#define CDC_TXRX_EPSIZE 64
+ /** Vendor request (0-255) the host should issue to retrieve the
+ * Microsoft OS Compatibility Descriptors. */
+ #define VENDOR_REQUEST_ID_MS_COMPAT 0x01
+
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
@@ -81,6 +85,21 @@
USB_Descriptor_Endpoint_t RNDIS_DataInEndpoint;
} USB_Descriptor_Configuration_t;
+ /** Type define for a Microsoft OS Compatibility 1.0 descriptor. */
+ typedef struct
+ {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+ uint8_t bReserved[7];
+ uint8_t bFirstInterfaceNumber;
+ uint8_t bReserved2;
+ char compatibleID[8];
+ char subCompatibleID[8];
+ uint8_t bReserved3[6];
+ } USB_Descriptor_MSCompatibility_t;
+
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
@@ -100,6 +119,7 @@
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
+ STRING_ID_MS_Compat = 0xEE, /**< MS OS Compatibility string descriptor ID (magic value set by Microsoft) */
};
/* Function Prototypes: */
@@ -108,5 +128,7 @@
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+ void CheckIfMSCompatibilityDescriptorRequest(void);
+
#endif
diff --git a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
index f963d48e1..cfe90ccd7 100644
--- a/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
+++ b/Demos/Device/ClassDriver/RNDISEthernet/RNDISEthernet.c
@@ -174,6 +174,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(void)
{
+ /* Send MS OS Compatibility descriptor if requested by the host. */
+ CheckIfMSCompatibilityDescriptorRequest();
+
RNDIS_Device_ProcessControlRequest(&Ethernet_RNDIS_Interface);
}
diff --git a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c
index 494150349..8e709cee9 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c
+++ b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.c
@@ -46,7 +46,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
- .USBSpecification = VERSION_BCD(1,1,0),
+ .USBSpecification = VERSION_BCD(2,0,0),
.Class = CDC_CSCP_CDCClass,
.SubClass = CDC_CSCP_NoSpecificSubclass,
.Protocol = CDC_CSCP_NoSpecificProtocol,
@@ -55,7 +55,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
.VendorID = 0x03EB,
.ProductID = 0x204C,
- .ReleaseNumber = VERSION_BCD(0,0,1),
+ .ReleaseNumber = VERSION_BCD(0,0,2),
.ManufacturerStrIndex = STRING_ID_Manufacturer,
.ProductStrIndex = STRING_ID_Product,
@@ -192,6 +192,32 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR
*/
const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"LUFA RNDIS CDC Demo");
+/** Microsoft OS Compatibility string descriptor. This is a special string descriptor that Microsoft based OS hosts
+ * will query at string descriptor ID 0xEE on initial enumeration, to test if the device supports the Microsoft OS
+ * Compatibility descriptor extensions (used to give the host additional information on the device's general class
+ * compatibility for driver-less installation).
+ */
+const USB_Descriptor_String_t PROGMEM MSConpatibilityString = USB_STRING_DESCRIPTOR_ARRAY('M','S','F','T','1','0','0', VENDOR_REQUEST_ID_MS_COMPAT);
+
+/** Microsoft OS Compatibility 1.0 descriptor. This is a special descriptor returned by the device on vendor request
+ * from the host, giving the OS additional compatibility information. This allows the host to automatically install
+ * the appropriate driver for various devices which share a common USB class (in this case RNDIS, which uses the
+ * CDC-ACM class usually used by virtual to serial adapters).
+ */
+const USB_Descriptor_MSCompatibility_t PROGMEM MSCompatibilityDescriptor =
+ {
+ .dwLength = sizeof(USB_Descriptor_MSCompatibility_t),
+ .bcdVersion = VERSION_BCD(1,0,0),
+ .wIndex = 4,
+ .bCount = 1,
+ .bReserved = { 0 },
+ .bFirstInterfaceNumber = INTERFACE_ID_CDC_CCI,
+ .bReserved2 = 1, // Must always be 1 according to spec
+ .compatibleID = "RNDIS",
+ .subCompatibleID = "5162001",
+ .bReserved3 = { 0 },
+ };
+
/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors"
* documentation) by the application code so that the address and size of a requested descriptor can be given
* to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function
@@ -233,6 +259,10 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
Address = &ProductString;
Size = pgm_read_byte(&ProductString.Header.Size);
break;
+ case STRING_ID_MS_Compat:
+ Address = &MSConpatibilityString;
+ Size = pgm_read_byte(&MSConpatibilityString.Header.Size);
+ break;
}
break;
@@ -242,3 +272,20 @@ uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
return Size;
}
+/** Sends the special Microsoft OS Compatibility Descriptor to the host PC, if
+ * the host is requesting it.
+ */
+void CheckIfMSCompatibilityDescriptorRequest(void)
+{
+ if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE))
+ {
+ if (USB_ControlRequest.bRequest == VENDOR_REQUEST_ID_MS_COMPAT)
+ {
+ Endpoint_ClearSETUP();
+
+ /* Write the OS compatibility descriptor to the control endpoint */
+ Endpoint_Write_Control_PStream_LE(&MSCompatibilityDescriptor, sizeof(MSCompatibilityDescriptor));
+ Endpoint_ClearOUT();
+ }
+ }
+}
diff --git a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h
index 31c56a00b..8f407fc14 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h
+++ b/Demos/Device/LowLevel/RNDISEthernet/Descriptors.h
@@ -59,6 +59,10 @@
/** Size in bytes of the CDC device-to-host notification IN endpoint. */
#define CDC_NOTIFICATION_EPSIZE 8
+ /** Vendor request (0-255) the host should issue to retrieve the
+ * Microsoft OS Compatibility Descriptors. */
+ #define VENDOR_REQUEST_ID_MS_COMPAT 0x01
+
/* Type Defines: */
/** Type define for the device configuration descriptor structure. This must be defined in the
* application code, as the configuration descriptor contains several sub-descriptors which
@@ -81,6 +85,21 @@
USB_Descriptor_Endpoint_t RNDIS_DataInEndpoint;
} USB_Descriptor_Configuration_t;
+ /** Type define for a Microsoft OS Compatibility 1.0 descriptor. */
+ typedef struct
+ {
+ uint32_t dwLength;
+ uint16_t bcdVersion;
+ uint16_t wIndex;
+ uint8_t bCount;
+ uint8_t bReserved[7];
+ uint8_t bFirstInterfaceNumber;
+ uint8_t bReserved2;
+ char compatibleID[8];
+ char subCompatibleID[8];
+ uint8_t bReserved3[6];
+ } USB_Descriptor_MSCompatibility_t;
+
/** Enum for the device interface descriptor IDs within the device. Each interface descriptor
* should have a unique ID index associated with it, which can be used to refer to the
* interface from other descriptors.
@@ -100,6 +119,7 @@
STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */
STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */
STRING_ID_Product = 2, /**< Product string ID */
+ STRING_ID_MS_Compat = 0xEE, /**< MS OS Compatibility string descriptor ID (magic value set by Microsoft) */
};
/* Function Prototypes: */
@@ -108,5 +128,7 @@
const void** const DescriptorAddress)
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
+ void CheckIfMSCompatibilityDescriptorRequest(void);
+
#endif
diff --git a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
index 80cde672c..247458f39 100644
--- a/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
+++ b/Demos/Device/LowLevel/RNDISEthernet/RNDISEthernet.c
@@ -130,6 +130,9 @@ void EVENT_USB_Device_ConfigurationChanged(void)
*/
void EVENT_USB_Device_ControlRequest(void)
{
+ /* Send MS OS Compatibility descriptor if requested by the host. */
+ CheckIfMSCompatibilityDescriptorRequest();
+
/* Process RNDIS class commands */
switch (USB_ControlRequest.bRequest)
{