Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Add Microsoft WCID descriptors to Atmel's ASF USB stack
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*)&microsoft_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*)&microsoft_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
You can’t perform that action at this time.