Skip to content

Commit

Permalink
Merge pull request #165 from tessel/winusb
Browse files Browse the repository at this point in the history
Make Windows auto-install WinUSB driver.
  • Loading branch information
johnnyman727 committed May 11, 2016
2 parents 9dd0ef3 + de4f613 commit 2230c76
Showing 1 changed file with 78 additions and 9 deletions.
87 changes: 78 additions & 9 deletions firmware/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ __attribute__((__aligned__(4))) const USB_DeviceDescriptor device_descriptor = {
.bMaxPacketSize0 = 64,
.idVendor = 0x1209,
.idProduct = 0x7551,
.bcdDevice = 0x0110,
.bcdDevice = 0x0111,

.iManufacturer = 0x01,
.iProduct = 0x02,
Expand Down Expand Up @@ -206,29 +206,76 @@ __attribute__((__aligned__(4))) const USB_StringDescriptor language_string = {
.bString = {USB_LANGUAGE_EN_US},
};

#define MSFT_ID 0xEE
#define MSFT_ID_STR u"\xEE"

__attribute__((__aligned__(4))) const USB_StringDescriptor msft_os = {
.bLength = 18,
.bDescriptorType = USB_DTYPE_String,
.bString = u"MSFT100\xee"
.bString = u"MSFT100" MSFT_ID_STR
};

__attribute__((__aligned__(4))) const USB_MicrosoftCompatibleDescriptor msft_compatible = {
.dwLength = sizeof(USB_MicrosoftCompatibleDescriptor) + sizeof(USB_MicrosoftCompatibleDescriptor_Interface),
__attribute__((__aligned__(4))) uint8_t ep0_buffer[146];

// TODO: this doesn't need to be in RAM if it is copied into usb_ep0_out one packet at a time
const USB_MicrosoftCompatibleDescriptor msft_compatible = {
.dwLength = sizeof(USB_MicrosoftCompatibleDescriptor) + (3 * sizeof(USB_MicrosoftCompatibleDescriptor_Interface)),
.bcdVersion = 0x0100,
.wIndex = 0x0004,
.bCount = 1,
.bCount = 3,
.reserved = {0, 0, 0, 0, 0, 0, 0},
.interfaces = {
{
.bFirstInterfaceNumber = 0,
.reserved1 = 0,
.reserved1 = 0x01,
.compatibleID = "WINUSB\0\0",
.subCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0},
.reserved2 = {0, 0, 0, 0, 0, 0},
}
},
{
.bFirstInterfaceNumber = 1,
.reserved1 = 0x01,
.compatibleID = "WINUSB\0\0",
.subCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0},
.reserved2 = {0, 0, 0, 0, 0, 0},
},
{
.bFirstInterfaceNumber = 2,
.reserved1 = 0x01,
.compatibleID = "WINUSB\0\0",
.subCompatibleID = {0, 0, 0, 0, 0, 0, 0, 0},
.reserved2 = {0, 0, 0, 0, 0, 0},
},
}
};

typedef struct {
uint32_t dwLength;
uint16_t bcdVersion;
uint16_t wIndex;
uint16_t wCount;
uint32_t dwPropLength;
uint32_t dwType;
uint16_t wNameLength;
uint16_t name[21];
uint32_t dwDataLength;
uint16_t data[40];
uint8_t _padding[2];
} __attribute__((packed)) USB_MicrosoftExtendedPropertiesDescriptor;

const USB_MicrosoftExtendedPropertiesDescriptor msft_extended = {
.dwLength = 146,
.bcdVersion = 0x0100,
.wIndex = 0x05,
.wCount = 0x01,
.dwPropLength = 136,
.dwType = 7,
.wNameLength = 42,
.name = u"DeviceInterfaceGUIDs\0",
.dwDataLength = 80,
.data = u"{3c33bbfd-71f9-4815-8b8f-7cd1ef928b3d}\0\0",
};

uint16_t usb_cb_get_descriptor(uint8_t type, uint8_t index, const uint8_t** ptr) {
const void* address = NULL;
uint16_t size = 0;
Expand Down Expand Up @@ -366,17 +413,39 @@ void req_boot_status() {
return usb_ep0_in(len);
}

// TODO: Use the version in the USB library after making it handle descriptors larger than 64 bytes
static inline void handle_msft_compatible(const USB_MicrosoftCompatibleDescriptor* msft_compatible, const USB_MicrosoftExtendedPropertiesDescriptor* msft_extended) {
uint16_t len;
if (usb_setup.wIndex == 0x0005) {
len = msft_extended->dwLength;
memcpy(ep0_buffer, msft_extended, len);
} else if (usb_setup.wIndex == 0x0004) {
len = msft_compatible->dwLength;
memcpy(ep0_buffer, msft_compatible, len);
} else {
return usb_ep0_stall();
}
if (len > usb_setup.wLength) {
len = usb_setup.wLength;
}
usb_ep_start_in(0x80, ep0_buffer, len, true);
usb_ep0_out();
}

void usb_cb_control_setup(void) {
uint8_t recipient = usb_setup.bmRequestType & USB_REQTYPE_RECIPIENT_MASK;
if (recipient == USB_RECIPIENT_DEVICE) {
switch(usb_setup.bRequest) {
case 0xee: return usb_handle_msft_compatible(&msft_compatible);
case MSFT_ID: return handle_msft_compatible(&msft_compatible, &msft_extended);
case REQ_PWR: return req_gpio(usb_setup.wIndex, usb_setup.wValue);
case REQ_INFO: return req_info(usb_setup.wIndex);
case REQ_BOOT: return req_boot();
case REQ_OPENWRT_BOOT_STATUS: return req_boot_status();
}
} else if (recipient == USB_RECIPIENT_INTERFACE) {
switch(usb_setup.bRequest) {
case MSFT_ID: return handle_msft_compatible(&msft_compatible, &msft_extended);
}
}
return usb_ep0_stall();
}
Expand Down Expand Up @@ -451,4 +520,4 @@ bool usb_cb_set_interface(uint16_t interface, uint16_t new_altsetting) {
return true;
}
return false;
}
}

0 comments on commit 2230c76

Please sign in to comment.