Last active
November 5, 2021 01:30
-
-
Save kuro68k/22f1e9c691e8d1ef46d3 to your computer and use it in GitHub Desktop.
Add Microsoft WCID descriptors to Atmel's ASF USB stack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
To add MS USB extended descriptors to an ASF project: | |
0. Optionally disable disabling peripheral clocks in common/services/clock/xmega/sysclk.c -> sysclk_init() | |
1. Configure clocks and oscillators in config/conf_board.h: | |
// required for the ASF clock module | |
#define BOARD_XOSC_HZ F_CPU | |
#define BOARD_XOSC_STARTUP_US 1024 | |
#define BOARD_XOSC_TYPE XOSC_TYPE_XTAL | |
and config/conf_clock. | |
2. Optionally disable sleep manager in config/conf_sleepmgr.h | |
3. Optionally set up a custom serial number in config/conf_usb.h: | |
#define USB_DEVICE_SERIAL_NAME | |
#define USB_DEVICE_GET_SERIAL_NAME_POINTER USB_serial_number | |
#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 25 | |
extern uint8_t USB_serial_number[]; | |
4. Add functions to get extra strings to config/conf_usb.h: | |
#define UDC_GET_EXTRA_STRING() usb_msft_string() | |
#define USB_DEVICE_SPECIFIC_REQUEST() usb_other_requests() | |
5. Add usb.h: | |
#ifndef USB_H_ | |
#define USB_H_ | |
/// Microsoft WCID descriptor | |
typedef struct USB_MicrosoftCompatibleDescriptor_Interface { | |
uint8_t bFirstInterfaceNumber; | |
uint8_t reserved1; | |
uint8_t compatibleID[8]; | |
uint8_t subCompatibleID[8]; | |
uint8_t reserved2[6]; | |
} __attribute__((packed)) USB_MicrosoftCompatibleDescriptor_Interface; | |
typedef struct USB_MicrosoftCompatibleDescriptor { | |
uint32_t dwLength; | |
uint16_t bcdVersion; | |
uint16_t wIndex; | |
uint8_t bCount; | |
uint8_t reserved[7]; | |
USB_MicrosoftCompatibleDescriptor_Interface interfaces[]; | |
} __attribute__((packed)) USB_MicrosoftCompatibleDescriptor; | |
typedef struct USB_MicrosoftExtendedPropertiesDescriptor { | |
uint32_t dwLength; | |
uint16_t bcdVersion; | |
uint16_t wIndex; | |
uint16_t bCount; | |
uint32_t dwPropertySize; | |
uint32_t dwPropertyDataType; | |
uint16_t wPropertyNameLength; | |
wchar_t PropertyName[21]; | |
uint32_t dwPropertyDataLength; | |
wchar_t PropertyData[40]; | |
} __attribute__((packed)) USB_MicrosoftExtendedPropertiesDescriptor; | |
extern bool usb_msft_string(void); | |
extern bool usb_other_requests(void); | |
#endif /* USB_H_ */ | |
6. Add usb.c: | |
#include <avr/io.h> | |
#include <stdbool.h> | |
#include "asf.h" | |
#include "usb.h" | |
/// Based on: https://github.com/cjameshuff/m1k-fw/blob/master/src/main.c | |
static USB_MicrosoftCompatibleDescriptor microsoft_compatible_id_descriptor = { | |
.dwLength = sizeof(USB_MicrosoftCompatibleDescriptor) + | |
1*sizeof(USB_MicrosoftCompatibleDescriptor_Interface), | |
.bcdVersion = 0x0100, | |
.wIndex = 0x0004, | |
.bCount = 1, | |
.reserved = {0, 0, 0, 0, 0, 0, 0}, | |
.interfaces = { | |
{ | |
.bFirstInterfaceNumber = 1, | |
.reserved1 = 1, | |
.compatibleID = "WINUSB\0\0", | |
.subCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0}, | |
.reserved2 = {0, 0, 0, 0, 0, 0}, | |
} | |
} | |
}; | |
static USB_MicrosoftExtendedPropertiesDescriptor microsoft_extended_properties_descriptor = { | |
.dwLength = sizeof(USB_MicrosoftExtendedPropertiesDescriptor), | |
.bcdVersion = 0x0100, | |
.wIndex = 0x0005, | |
.bCount = 2, | |
.dwPropertySize = 136, | |
.dwPropertyDataType = 7, | |
.wPropertyNameLength = 21*2, | |
.PropertyName = L"DeviceInterfaceGUIDs", | |
.dwPropertyDataLength = 40*2, | |
.PropertyData = L"{00000000-0000-0000-0000-000000000000}\0", | |
}; | |
/************************************************************************************************** | |
** WCID configuration information | |
** Hooked into UDC via UDC_GET_EXTRA_STRING #define. | |
*/ | |
bool usb_msft_string(void) | |
{ | |
uint8_t udi_msft_magic[] = "MSFT100"; | |
/* | |
struct extra_strings_desc_t{ | |
usb_str_desc_t header; | |
le16_t string[sizeof(udi_msft_magic)]; | |
}; | |
*/ | |
struct extra_strings_desc_t{ | |
usb_str_desc_t header; | |
le16_t string[7]; | |
uint8_t vendor_code; | |
uint8_t padding; | |
}; | |
static UDC_DESC_STORAGE struct extra_strings_desc_t extra_strings_desc = { | |
.header.bDescriptorType = USB_DT_STRING, | |
}; | |
uint8_t i; | |
uint8_t *str; | |
uint8_t str_lgt=0; | |
if ((udd_g_ctrlreq.req.wValue & 0xff) == 0xEE) { | |
str_lgt = sizeof(udi_msft_magic)-1; | |
str = udi_msft_magic; | |
} | |
else { | |
return false; | |
} | |
if (str_lgt!=0) { | |
for( i=0; i<str_lgt; i++) { | |
extra_strings_desc.string[i] = cpu_to_le16((le16_t)str[i]); | |
} | |
extra_strings_desc.vendor_code = 0x22; | |
extra_strings_desc.padding = 0; | |
//extra_strings_desc.header.bLength = 2+ (str_lgt)*2; | |
extra_strings_desc.header.bLength = 18; | |
udd_g_ctrlreq.payload_size = extra_strings_desc.header.bLength; | |
udd_g_ctrlreq.payload = (uint8_t *) &extra_strings_desc; | |
} | |
// if the string is larger than request length, then cut it | |
if (udd_g_ctrlreq.payload_size > udd_g_ctrlreq.req.wLength) { | |
udd_g_ctrlreq.payload_size = udd_g_ctrlreq.req.wLength; | |
} | |
return true; | |
} | |
/************************************************************************************************** | |
** Handle device requests that the ASF stack doesn't | |
*/ | |
bool usb_other_requests(void) | |
{ | |
uint8_t* ptr = 0; | |
uint16_t size = 0; | |
if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) | |
{ | |
//if (udd_g_ctrlreq.req.bRequest == 0x30) | |
if (1) | |
{ | |
if (udd_g_ctrlreq.req.wIndex == 0x04) | |
{ | |
ptr = (uint8_t*)µsoft_compatible_id_descriptor; | |
size = (udd_g_ctrlreq.req.wLength); | |
if (size > microsoft_compatible_id_descriptor.dwLength) | |
size = microsoft_compatible_id_descriptor.dwLength; | |
} | |
else if (udd_g_ctrlreq.req.wIndex == 0x05) | |
{ | |
ptr = (uint8_t*)µsoft_extended_properties_descriptor; | |
size = (udd_g_ctrlreq.req.wLength); | |
if (size > microsoft_extended_properties_descriptor.dwLength) | |
size = microsoft_extended_properties_descriptor.dwLength; | |
} | |
else | |
return false; | |
} | |
} | |
udd_g_ctrlreq.payload_size = size; | |
if ( size == 0 ) | |
{ | |
udd_g_ctrlreq.callback = 0; | |
udd_g_ctrlreq.over_under_run = 0; | |
} | |
else | |
udd_g_ctrlreq.payload = ptr; | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment