/*
LUFA Library
- Copyright (C) Dean Camera, 2013.
+ Copyright (C) Dean Camera, 2018.
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2018 Dean Camera (dean [at] fourwalledcubicle [dot] com)
Permission to use, copy, modify, distribute, and sell this
software and its documentation for any purpose is hereby granted
{
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
- .USBSpecification = VERSION_BCD(01.10),
+ .USBSpecification = VERSION_BCD(2,0,0),
.Class = USB_CSCP_IADDeviceClass,
.SubClass = USB_CSCP_IADDeviceSubclass,
.Protocol = USB_CSCP_IADDeviceProtocol,
.VendorID = 0x03EB,
.ProductID = 0x2069,
- .ReleaseNumber = VERSION_BCD(00.01),
+ .ReleaseNumber = VERSION_BCD(0,0,2),
- .ManufacturerStrIndex = 0x01,
- .ProductStrIndex = 0x02,
+ .ManufacturerStrIndex = STRING_ID_Manufacturer,
+ .ProductStrIndex = STRING_ID_Product,
.SerialNumStrIndex = USE_INTERNAL_SERIAL,
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_Association_t), .Type = DTYPE_InterfaceAssociation},
- .FirstInterfaceIndex = 0,
+ .FirstInterfaceIndex = INTERFACE_ID_CDC_CCI,
.TotalInterfaces = 2,
.Class = CDC_CSCP_CDCClass,
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
- .InterfaceNumber = 0,
+ .InterfaceNumber = INTERFACE_ID_CDC_CCI,
.AlternateSetting = 0,
.TotalEndpoints = 1,
.CDC_Functional_Header =
{
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = CDC_DTYPE_CSInterface},
.Subtype = CDC_DSUBTYPE_CSInterface_Header,
- .CDCSpecification = VERSION_BCD(01.10),
+ .CDCSpecification = VERSION_BCD(1,1,0),
},
.CDC_Functional_ACM =
{
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = CDC_DTYPE_CSInterface},
.Subtype = CDC_DSUBTYPE_CSInterface_ACM,
.Capabilities = 0x00,
.CDC_Functional_Union =
{
- .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
+ .Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = CDC_DTYPE_CSInterface},
.Subtype = CDC_DSUBTYPE_CSInterface_Union,
- .MasterInterfaceNumber = 0,
- .SlaveInterfaceNumber = 1,
+ .MasterInterfaceNumber = INTERFACE_ID_CDC_CCI,
+ .SlaveInterfaceNumber = INTERFACE_ID_CDC_DCI,
},
.CDC_NotificationEndpoint =
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
- .InterfaceNumber = 1,
+ .InterfaceNumber = INTERFACE_ID_CDC_DCI,
.AlternateSetting = 0,
.TotalEndpoints = 2,
{
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
- .InterfaceNumber = 2,
+ .InterfaceNumber = INTERFACE_ID_MassStorage,
.AlternateSetting = 0,
.TotalEndpoints = 2,
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
*/
-const USB_Descriptor_String_t PROGMEM LanguageString =
-{
- .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
-
- .UnicodeString = {LANGUAGE_ID_ENG}
-};
+const USB_Descriptor_String_t PROGMEM LanguageString = USB_STRING_DESCRIPTOR_ARRAY(LANGUAGE_ID_ENG);
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
-const USB_Descriptor_String_t PROGMEM ManufacturerString =
-{
- .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
-
- .UnicodeString = L"Dean Camera"
-};
+const USB_Descriptor_String_t PROGMEM ManufacturerString = USB_STRING_DESCRIPTOR(L"LUFA Library");
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
* Descriptor.
*/
-const USB_Descriptor_String_t PROGMEM ProductString =
-{
- .Header = {.Size = USB_STRING_LEN(14), .Type = DTYPE_String},
+const USB_Descriptor_String_t PROGMEM ProductString = USB_STRING_DESCRIPTOR(L"LUFA Webserver");
- .UnicodeString = L"LUFA Webserver"
-};
+/** 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
* USB host.
*/
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
- const uint8_t wIndex,
+ const uint16_t wIndex,
const void** const DescriptorAddress)
{
const uint8_t DescriptorType = (wValue >> 8);
case DTYPE_String:
switch (DescriptorNumber)
{
- case 0x00:
+ case STRING_ID_Language:
Address = &LanguageString;
Size = pgm_read_byte(&LanguageString.Header.Size);
break;
- case 0x01:
+ case STRING_ID_Manufacturer:
Address = &ManufacturerString;
Size = pgm_read_byte(&ManufacturerString.Header.Size);
break;
- case 0x02:
+ case STRING_ID_Product:
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;
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();
+ }
+ }
+}