mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-25 15:58:08 +00:00
re-enable WebUSB
This reverts commit "Revert WinUSB feature"
b20336e82d
This commit is contained in:
parent
c2fa3d8fca
commit
4da73df57d
4
Makefile
4
Makefile
@ -20,6 +20,10 @@ ifneq ($(EMULATOR),1)
|
|||||||
OBJS += timer.o
|
OBJS += timer.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
OBJS += usb21_standard.o
|
||||||
|
OBJS += webusb.o
|
||||||
|
OBJS += winusb.o
|
||||||
|
|
||||||
OBJS += gen/bitmaps.o
|
OBJS += gen/bitmaps.o
|
||||||
OBJS += gen/fonts.o
|
OBJS += gen/fonts.o
|
||||||
|
|
||||||
|
124
bootloader/usb.c
124
bootloader/usb.c
@ -18,7 +18,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <libopencm3/usb/usbd.h>
|
#include <libopencm3/usb/usbd.h>
|
||||||
#include <libopencm3/usb/hid.h>
|
|
||||||
#include <libopencm3/stm32/flash.h>
|
#include <libopencm3/stm32/flash.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -37,8 +36,14 @@
|
|||||||
#include "secp256k1.h"
|
#include "secp256k1.h"
|
||||||
#include "memzero.h"
|
#include "memzero.h"
|
||||||
|
|
||||||
|
#include "usb21_standard.h"
|
||||||
|
#include "webusb.h"
|
||||||
|
#include "winusb.h"
|
||||||
|
|
||||||
#define FIRMWARE_MAGIC "TRZR"
|
#define FIRMWARE_MAGIC "TRZR"
|
||||||
|
|
||||||
|
#define USB_INTERFACE_INDEX_MAIN 0
|
||||||
|
|
||||||
#define ENDPOINT_ADDRESS_IN (0x81)
|
#define ENDPOINT_ADDRESS_IN (0x81)
|
||||||
#define ENDPOINT_ADDRESS_OUT (0x01)
|
#define ENDPOINT_ADDRESS_OUT (0x01)
|
||||||
|
|
||||||
@ -48,60 +53,21 @@ static bool old_was_unsigned;
|
|||||||
static const struct usb_device_descriptor dev_descr = {
|
static const struct usb_device_descriptor dev_descr = {
|
||||||
.bLength = USB_DT_DEVICE_SIZE,
|
.bLength = USB_DT_DEVICE_SIZE,
|
||||||
.bDescriptorType = USB_DT_DEVICE,
|
.bDescriptorType = USB_DT_DEVICE,
|
||||||
.bcdUSB = 0x0200,
|
.bcdUSB = 0x0210,
|
||||||
.bDeviceClass = 0,
|
.bDeviceClass = 0,
|
||||||
.bDeviceSubClass = 0,
|
.bDeviceSubClass = 0,
|
||||||
.bDeviceProtocol = 0,
|
.bDeviceProtocol = 0,
|
||||||
.bMaxPacketSize0 = 64,
|
.bMaxPacketSize0 = 64,
|
||||||
.idVendor = 0x534c,
|
.idVendor = 0x534c,
|
||||||
.idProduct = 0x0001,
|
.idProduct = 0x0001,
|
||||||
.bcdDevice = 0x0100,
|
.bcdDevice = 0x0300,
|
||||||
.iManufacturer = 1,
|
.iManufacturer = 1,
|
||||||
.iProduct = 2,
|
.iProduct = 2,
|
||||||
.iSerialNumber = 3,
|
.iSerialNumber = 3,
|
||||||
.bNumConfigurations = 1,
|
.bNumConfigurations = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t hid_report_descriptor[] = {
|
static const struct usb_endpoint_descriptor endpoints[2] = {{
|
||||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined)
|
|
||||||
0x09, 0x01, // USAGE (1)
|
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
|
||||||
0x09, 0x20, // USAGE (Input Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
||||||
0x09, 0x21, // USAGE (Output Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
|
||||||
0xc0 // END_COLLECTION
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
struct usb_hid_descriptor hid_descriptor;
|
|
||||||
struct {
|
|
||||||
uint8_t bReportDescriptorType;
|
|
||||||
uint16_t wDescriptorLength;
|
|
||||||
} __attribute__((packed)) hid_report;
|
|
||||||
} __attribute__((packed)) hid_function = {
|
|
||||||
.hid_descriptor = {
|
|
||||||
.bLength = sizeof(hid_function),
|
|
||||||
.bDescriptorType = USB_DT_HID,
|
|
||||||
.bcdHID = 0x0111,
|
|
||||||
.bCountryCode = 0,
|
|
||||||
.bNumDescriptors = 1,
|
|
||||||
},
|
|
||||||
.hid_report = {
|
|
||||||
.bReportDescriptorType = USB_DT_REPORT,
|
|
||||||
.wDescriptorLength = sizeof(hid_report_descriptor),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct usb_endpoint_descriptor hid_endpoints[2] = {{
|
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_IN,
|
.bEndpointAddress = ENDPOINT_ADDRESS_IN,
|
||||||
@ -117,24 +83,24 @@ static const struct usb_endpoint_descriptor hid_endpoints[2] = {{
|
|||||||
.bInterval = 1,
|
.bInterval = 1,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_interface_descriptor hid_iface[] = {{
|
static const struct usb_interface_descriptor iface[] = {{
|
||||||
.bLength = USB_DT_INTERFACE_SIZE,
|
.bLength = USB_DT_INTERFACE_SIZE,
|
||||||
.bDescriptorType = USB_DT_INTERFACE,
|
.bDescriptorType = USB_DT_INTERFACE,
|
||||||
.bInterfaceNumber = 0,
|
.bInterfaceNumber = USB_INTERFACE_INDEX_MAIN,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 2,
|
.bNumEndpoints = 2,
|
||||||
.bInterfaceClass = USB_CLASS_HID,
|
.bInterfaceClass = USB_CLASS_VENDOR,
|
||||||
.bInterfaceSubClass = 0,
|
.bInterfaceSubClass = 0,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = 0,
|
.iInterface = 0,
|
||||||
.endpoint = hid_endpoints,
|
.endpoint = endpoints,
|
||||||
.extra = &hid_function,
|
.extra = NULL,
|
||||||
.extralen = sizeof(hid_function),
|
.extralen = 0,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_interface ifaces[] = {{
|
static const struct usb_interface ifaces[] = {{
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
.altsetting = hid_iface,
|
.altsetting = iface,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_config_descriptor config = {
|
static const struct usb_config_descriptor config = {
|
||||||
@ -155,23 +121,6 @@ static const char *usb_strings[] = {
|
|||||||
"", // empty serial
|
"", // empty serial
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hid_control_request(usbd_device *dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, usbd_control_complete_callback *complete)
|
|
||||||
{
|
|
||||||
(void)complete;
|
|
||||||
(void)dev;
|
|
||||||
|
|
||||||
if ((req->bmRequestType != 0x81) ||
|
|
||||||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
|
|
||||||
(req->wValue != 0x2200))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Handle the HID report descriptor. */
|
|
||||||
*buf = (uint8_t *)hid_report_descriptor;
|
|
||||||
*len = sizeof(hid_report_descriptor);
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STATE_READY,
|
STATE_READY,
|
||||||
STATE_OPEN,
|
STATE_OPEN,
|
||||||
@ -315,7 +264,7 @@ static void restore_metadata(const uint8_t *backup)
|
|||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
static void rx_callback(usbd_device *dev, uint8_t ep)
|
||||||
{
|
{
|
||||||
(void)ep;
|
(void)ep;
|
||||||
static uint8_t buf[64] __attribute__((aligned(4)));
|
static uint8_t buf[64] __attribute__((aligned(4)));
|
||||||
@ -665,23 +614,37 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_set_config(usbd_device *dev, uint16_t wValue)
|
static void set_config(usbd_device *dev, uint16_t wValue)
|
||||||
{
|
{
|
||||||
(void)wValue;
|
(void)wValue;
|
||||||
|
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_rx_callback);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, rx_callback);
|
||||||
|
|
||||||
usbd_register_control_callback(
|
|
||||||
dev,
|
|
||||||
USB_REQ_TYPE_STANDARD | USB_REQ_TYPE_INTERFACE,
|
|
||||||
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
|
||||||
hid_control_request
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static usbd_device *usbd_dev;
|
static usbd_device *usbd_dev;
|
||||||
static uint8_t usbd_control_buffer[128];
|
static uint8_t usbd_control_buffer[256] __attribute__ ((aligned (2)));
|
||||||
|
|
||||||
|
static const struct usb_device_capability_descriptor* capabilities[] = {
|
||||||
|
(const struct usb_device_capability_descriptor*)&webusb_platform_capability_descriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct usb_bos_descriptor bos_descriptor = {
|
||||||
|
.bLength = USB_DT_BOS_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_BOS,
|
||||||
|
.bNumDeviceCaps = sizeof(capabilities)/sizeof(capabilities[0]),
|
||||||
|
.capabilities = capabilities
|
||||||
|
};
|
||||||
|
|
||||||
|
void usbInit(void)
|
||||||
|
{
|
||||||
|
usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, sizeof(usb_strings)/sizeof(const char *), usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||||
|
usbd_register_set_config_callback(usbd_dev, set_config);
|
||||||
|
usb21_setup(usbd_dev, &bos_descriptor);
|
||||||
|
static const char* origin_url = "trezor.io/start";
|
||||||
|
webusb_setup(usbd_dev, origin_url);
|
||||||
|
winusb_setup(usbd_dev, USB_INTERFACE_INDEX_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
void checkButtons(void)
|
void checkButtons(void)
|
||||||
{
|
{
|
||||||
@ -715,8 +678,7 @@ void checkButtons(void)
|
|||||||
void usbLoop(bool firmware_present)
|
void usbLoop(bool firmware_present)
|
||||||
{
|
{
|
||||||
brand_new_firmware = !firmware_present;
|
brand_new_firmware = !firmware_present;
|
||||||
usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, 3, usbd_control_buffer, sizeof(usbd_control_buffer));
|
usbInit();
|
||||||
usbd_register_set_config_callback(usbd_dev, hid_set_config);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
usbd_poll(usbd_dev);
|
usbd_poll(usbd_dev);
|
||||||
if (brand_new_firmware && (flash_state == STATE_READY || flash_state == STATE_OPEN)) {
|
if (brand_new_firmware && (flash_state == STATE_READY || flash_state == STATE_OPEN)) {
|
||||||
|
245
firmware/usb.c
245
firmware/usb.c
@ -29,18 +29,27 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include "usb21_standard.h"
|
||||||
|
#include "webusb.h"
|
||||||
|
#include "winusb.h"
|
||||||
|
|
||||||
|
|
||||||
#define USB_INTERFACE_INDEX_MAIN 0
|
#define USB_INTERFACE_INDEX_MAIN 0
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
#define USB_INTERFACE_INDEX_DEBUG 1
|
#define USB_INTERFACE_INDEX_DEBUG 1
|
||||||
#define USB_INTERFACE_INDEX_U2F 2
|
#define USB_INTERFACE_INDEX_U2F 2
|
||||||
|
#define USB_INTERFACE_COUNT 3
|
||||||
#else
|
#else
|
||||||
#define USB_INTERFACE_INDEX_U2F 1
|
#define USB_INTERFACE_INDEX_U2F 1
|
||||||
|
#define USB_INTERFACE_COUNT 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ENDPOINT_ADDRESS_IN (0x81)
|
#define ENDPOINT_ADDRESS_MAIN_IN (0x81)
|
||||||
#define ENDPOINT_ADDRESS_OUT (0x01)
|
#define ENDPOINT_ADDRESS_MAIN_OUT (0x01)
|
||||||
|
#if DEBUG_LINK
|
||||||
#define ENDPOINT_ADDRESS_DEBUG_IN (0x82)
|
#define ENDPOINT_ADDRESS_DEBUG_IN (0x82)
|
||||||
#define ENDPOINT_ADDRESS_DEBUG_OUT (0x02)
|
#define ENDPOINT_ADDRESS_DEBUG_OUT (0x02)
|
||||||
|
#endif
|
||||||
#define ENDPOINT_ADDRESS_U2F_IN (0x83)
|
#define ENDPOINT_ADDRESS_U2F_IN (0x83)
|
||||||
#define ENDPOINT_ADDRESS_U2F_OUT (0x03)
|
#define ENDPOINT_ADDRESS_U2F_OUT (0x03)
|
||||||
|
|
||||||
@ -50,7 +59,7 @@
|
|||||||
X(SERIAL_NUMBER, storage_uuid_str) \
|
X(SERIAL_NUMBER, storage_uuid_str) \
|
||||||
X(INTERFACE_MAIN, "TREZOR Interface") \
|
X(INTERFACE_MAIN, "TREZOR Interface") \
|
||||||
X(INTERFACE_DEBUG, "TREZOR Debug Link Interface") \
|
X(INTERFACE_DEBUG, "TREZOR Debug Link Interface") \
|
||||||
X(INTERFACE_U2F, "U2F Interface")
|
X(INTERFACE_U2F, "TREZOR U2F Interface") \
|
||||||
|
|
||||||
#define X(name, value) USB_STRING_##name,
|
#define X(name, value) USB_STRING_##name,
|
||||||
enum {
|
enum {
|
||||||
@ -68,60 +77,20 @@ static const char *usb_strings[] = {
|
|||||||
static const struct usb_device_descriptor dev_descr = {
|
static const struct usb_device_descriptor dev_descr = {
|
||||||
.bLength = USB_DT_DEVICE_SIZE,
|
.bLength = USB_DT_DEVICE_SIZE,
|
||||||
.bDescriptorType = USB_DT_DEVICE,
|
.bDescriptorType = USB_DT_DEVICE,
|
||||||
.bcdUSB = 0x0200,
|
.bcdUSB = 0x0210,
|
||||||
.bDeviceClass = 0,
|
.bDeviceClass = 0,
|
||||||
.bDeviceSubClass = 0,
|
.bDeviceSubClass = 0,
|
||||||
.bDeviceProtocol = 0,
|
.bDeviceProtocol = 0,
|
||||||
.bMaxPacketSize0 = 64,
|
.bMaxPacketSize0 = 64,
|
||||||
.idVendor = 0x534c,
|
.idVendor = 0x534c,
|
||||||
.idProduct = 0x0001,
|
.idProduct = 0x0001,
|
||||||
.bcdDevice = 0x0100,
|
.bcdDevice = 0x0200,
|
||||||
.iManufacturer = USB_STRING_MANUFACTURER,
|
.iManufacturer = USB_STRING_MANUFACTURER,
|
||||||
.iProduct = USB_STRING_PRODUCT,
|
.iProduct = USB_STRING_PRODUCT,
|
||||||
.iSerialNumber = USB_STRING_SERIAL_NUMBER,
|
.iSerialNumber = USB_STRING_SERIAL_NUMBER,
|
||||||
.bNumConfigurations = 1,
|
.bNumConfigurations = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t hid_report_descriptor[] = {
|
|
||||||
0x06, 0x00, 0xff, // USAGE_PAGE (Vendor Defined)
|
|
||||||
0x09, 0x01, // USAGE (1)
|
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
|
||||||
0x09, 0x20, // USAGE (Input Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
||||||
0x09, 0x21, // USAGE (Output Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
|
||||||
0xc0 // END_COLLECTION
|
|
||||||
};
|
|
||||||
|
|
||||||
#if DEBUG_LINK
|
|
||||||
static const uint8_t hid_report_descriptor_debug[] = {
|
|
||||||
0x06, 0x01, 0xff, // USAGE_PAGE (Vendor Defined)
|
|
||||||
0x09, 0x01, // USAGE (1)
|
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
|
||||||
0x09, 0x20, // USAGE (Input Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
||||||
0x09, 0x21, // USAGE (Output Report Data)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x40, // REPORT_COUNT (64)
|
|
||||||
0x91, 0x02, // OUTPUT (Data,Var,Abs)
|
|
||||||
0xc0 // END_COLLECTION
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const uint8_t hid_report_descriptor_u2f[] = {
|
static const uint8_t hid_report_descriptor_u2f[] = {
|
||||||
0x06, 0xd0, 0xf1, // USAGE_PAGE (FIDO Alliance)
|
0x06, 0xd0, 0xf1, // USAGE_PAGE (FIDO Alliance)
|
||||||
0x09, 0x01, // USAGE (U2F HID Authenticator Device)
|
0x09, 0x01, // USAGE (U2F HID Authenticator Device)
|
||||||
@ -141,26 +110,6 @@ static const uint8_t hid_report_descriptor_u2f[] = {
|
|||||||
0xc0 // END_COLLECTION
|
0xc0 // END_COLLECTION
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct {
|
|
||||||
struct usb_hid_descriptor hid_descriptor;
|
|
||||||
struct {
|
|
||||||
uint8_t bReportDescriptorType;
|
|
||||||
uint16_t wDescriptorLength;
|
|
||||||
} __attribute__((packed)) hid_report;
|
|
||||||
} __attribute__((packed)) hid_function = {
|
|
||||||
.hid_descriptor = {
|
|
||||||
.bLength = sizeof(hid_function),
|
|
||||||
.bDescriptorType = USB_DT_HID,
|
|
||||||
.bcdHID = 0x0111,
|
|
||||||
.bCountryCode = 0,
|
|
||||||
.bNumDescriptors = 1,
|
|
||||||
},
|
|
||||||
.hid_report = {
|
|
||||||
.bReportDescriptorType = USB_DT_REPORT,
|
|
||||||
.wDescriptorLength = sizeof(hid_report_descriptor),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
struct usb_hid_descriptor hid_descriptor_u2f;
|
struct usb_hid_descriptor hid_descriptor_u2f;
|
||||||
struct {
|
struct {
|
||||||
@ -181,52 +130,20 @@ static const struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const struct usb_endpoint_descriptor hid_endpoints[2] = {{
|
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_IN,
|
|
||||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
|
||||||
.wMaxPacketSize = 64,
|
|
||||||
.bInterval = 1,
|
|
||||||
}, {
|
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_OUT,
|
|
||||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
|
||||||
.wMaxPacketSize = 64,
|
|
||||||
.bInterval = 1,
|
|
||||||
}};
|
|
||||||
|
|
||||||
static const struct usb_interface_descriptor hid_iface[] = {{
|
|
||||||
.bLength = USB_DT_INTERFACE_SIZE,
|
|
||||||
.bDescriptorType = USB_DT_INTERFACE,
|
|
||||||
.bInterfaceNumber = USB_INTERFACE_INDEX_MAIN,
|
|
||||||
.bAlternateSetting = 0,
|
|
||||||
.bNumEndpoints = 2,
|
|
||||||
.bInterfaceClass = USB_CLASS_HID,
|
|
||||||
.bInterfaceSubClass = 0,
|
|
||||||
.bInterfaceProtocol = 0,
|
|
||||||
.iInterface = USB_STRING_INTERFACE_MAIN,
|
|
||||||
.endpoint = hid_endpoints,
|
|
||||||
.extra = &hid_function,
|
|
||||||
.extralen = sizeof(hid_function),
|
|
||||||
}};
|
|
||||||
|
|
||||||
static const struct usb_endpoint_descriptor hid_endpoints_u2f[2] = {{
|
static const struct usb_endpoint_descriptor hid_endpoints_u2f[2] = {{
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_U2F_IN,
|
.bEndpointAddress = ENDPOINT_ADDRESS_U2F_IN,
|
||||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||||
.wMaxPacketSize = 64,
|
.wMaxPacketSize = 64,
|
||||||
.bInterval = 2,
|
.bInterval = 1,
|
||||||
}, {
|
}, {
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_U2F_OUT,
|
.bEndpointAddress = ENDPOINT_ADDRESS_U2F_OUT,
|
||||||
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||||
.wMaxPacketSize = 64,
|
.wMaxPacketSize = 64,
|
||||||
.bInterval = 2,
|
.bInterval = 1,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_interface_descriptor hid_iface_u2f[] = {{
|
static const struct usb_interface_descriptor hid_iface_u2f[] = {{
|
||||||
@ -245,7 +162,7 @@ static const struct usb_interface_descriptor hid_iface_u2f[] = {{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
static const struct usb_endpoint_descriptor hid_endpoints_debug[2] = {{
|
static const struct usb_endpoint_descriptor webusb_endpoints_debug[2] = {{
|
||||||
.bLength = USB_DT_ENDPOINT_SIZE,
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
.bDescriptorType = USB_DT_ENDPOINT,
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
.bEndpointAddress = ENDPOINT_ADDRESS_DEBUG_IN,
|
.bEndpointAddress = ENDPOINT_ADDRESS_DEBUG_IN,
|
||||||
@ -261,29 +178,64 @@ static const struct usb_endpoint_descriptor hid_endpoints_debug[2] = {{
|
|||||||
.bInterval = 1,
|
.bInterval = 1,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const struct usb_interface_descriptor hid_iface_debug[] = {{
|
static const struct usb_interface_descriptor webusb_iface_debug[] = {{
|
||||||
.bLength = USB_DT_INTERFACE_SIZE,
|
.bLength = USB_DT_INTERFACE_SIZE,
|
||||||
.bDescriptorType = USB_DT_INTERFACE,
|
.bDescriptorType = USB_DT_INTERFACE,
|
||||||
.bInterfaceNumber = USB_INTERFACE_INDEX_DEBUG,
|
.bInterfaceNumber = USB_INTERFACE_INDEX_DEBUG,
|
||||||
.bAlternateSetting = 0,
|
.bAlternateSetting = 0,
|
||||||
.bNumEndpoints = 2,
|
.bNumEndpoints = 2,
|
||||||
.bInterfaceClass = USB_CLASS_HID,
|
.bInterfaceClass = USB_CLASS_VENDOR,
|
||||||
.bInterfaceSubClass = 0,
|
.bInterfaceSubClass = 0,
|
||||||
.bInterfaceProtocol = 0,
|
.bInterfaceProtocol = 0,
|
||||||
.iInterface = USB_STRING_INTERFACE_DEBUG,
|
.iInterface = USB_STRING_INTERFACE_DEBUG,
|
||||||
.endpoint = hid_endpoints_debug,
|
.endpoint = webusb_endpoints_debug,
|
||||||
.extra = &hid_function,
|
.extra = NULL,
|
||||||
.extralen = sizeof(hid_function),
|
.extralen = 0,
|
||||||
}};
|
}};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static const struct usb_endpoint_descriptor webusb_endpoints_main[2] = {{
|
||||||
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
.bEndpointAddress = ENDPOINT_ADDRESS_MAIN_IN,
|
||||||
|
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||||
|
.wMaxPacketSize = 64,
|
||||||
|
.bInterval = 1,
|
||||||
|
}, {
|
||||||
|
.bLength = USB_DT_ENDPOINT_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_ENDPOINT,
|
||||||
|
.bEndpointAddress = ENDPOINT_ADDRESS_MAIN_OUT,
|
||||||
|
.bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT,
|
||||||
|
.wMaxPacketSize = 64,
|
||||||
|
.bInterval = 1,
|
||||||
|
}};
|
||||||
|
|
||||||
|
static const struct usb_interface_descriptor webusb_iface_main[] = {{
|
||||||
|
.bLength = USB_DT_INTERFACE_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_INTERFACE,
|
||||||
|
.bInterfaceNumber = USB_INTERFACE_INDEX_MAIN,
|
||||||
|
.bAlternateSetting = 0,
|
||||||
|
.bNumEndpoints = 2,
|
||||||
|
.bInterfaceClass = USB_CLASS_VENDOR,
|
||||||
|
.bInterfaceSubClass = 0,
|
||||||
|
.bInterfaceProtocol = 0,
|
||||||
|
.iInterface = USB_STRING_INTERFACE_MAIN,
|
||||||
|
.endpoint = webusb_endpoints_main,
|
||||||
|
.extra = NULL,
|
||||||
|
.extralen = 0,
|
||||||
|
}};
|
||||||
|
|
||||||
|
|
||||||
|
// Windows are strict about interfaces appearing
|
||||||
|
// in correct order
|
||||||
static const struct usb_interface ifaces[] = {{
|
static const struct usb_interface ifaces[] = {{
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
.altsetting = hid_iface,
|
.altsetting = webusb_iface_main,
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
}, {
|
}, {
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
.altsetting = hid_iface_debug,
|
.altsetting = webusb_iface_debug,
|
||||||
#endif
|
#endif
|
||||||
}, {
|
}, {
|
||||||
.num_altsetting = 1,
|
.num_altsetting = 1,
|
||||||
@ -294,11 +246,7 @@ static const struct usb_config_descriptor config = {
|
|||||||
.bLength = USB_DT_CONFIGURATION_SIZE,
|
.bLength = USB_DT_CONFIGURATION_SIZE,
|
||||||
.bDescriptorType = USB_DT_CONFIGURATION,
|
.bDescriptorType = USB_DT_CONFIGURATION,
|
||||||
.wTotalLength = 0,
|
.wTotalLength = 0,
|
||||||
#if DEBUG_LINK
|
.bNumInterfaces = USB_INTERFACE_COUNT,
|
||||||
.bNumInterfaces = 3,
|
|
||||||
#else
|
|
||||||
.bNumInterfaces = 2,
|
|
||||||
#endif
|
|
||||||
.bConfigurationValue = 1,
|
.bConfigurationValue = 1,
|
||||||
.iConfiguration = 0,
|
.iConfiguration = 0,
|
||||||
.bmAttributes = 0x80,
|
.bmAttributes = 0x80,
|
||||||
@ -312,40 +260,24 @@ static int hid_control_request(usbd_device *dev, struct usb_setup_data *req, uin
|
|||||||
(void)dev;
|
(void)dev;
|
||||||
|
|
||||||
if ((req->bmRequestType != 0x81) ||
|
if ((req->bmRequestType != 0x81) ||
|
||||||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
|
(req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
|
||||||
(req->wValue != 0x2200))
|
(req->wValue != 0x2200))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (req->wIndex == USB_INTERFACE_INDEX_U2F) {
|
debugLog(0, "", "hid_control_request u2f");
|
||||||
debugLog(0, "", "hid_control_request u2f");
|
*buf = (uint8_t *)hid_report_descriptor_u2f;
|
||||||
*buf = (uint8_t *)hid_report_descriptor_u2f;
|
*len = MIN(*len, sizeof(hid_report_descriptor_u2f));
|
||||||
*len = sizeof(hid_report_descriptor_u2f);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG_LINK
|
|
||||||
if (req->wIndex == USB_INTERFACE_INDEX_DEBUG) {
|
|
||||||
debugLog(0, "", "hid_control_request debug");
|
|
||||||
*buf = (uint8_t *)hid_report_descriptor_debug;
|
|
||||||
*len = sizeof(hid_report_descriptor_debug);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
debugLog(0, "", "hid_control_request main");
|
|
||||||
*buf = (uint8_t *)hid_report_descriptor;
|
|
||||||
*len = sizeof(hid_report_descriptor);
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static volatile char tiny = 0;
|
static volatile char tiny = 0;
|
||||||
|
|
||||||
static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
static void main_rx_callback(usbd_device *dev, uint8_t ep)
|
||||||
{
|
{
|
||||||
(void)ep;
|
(void)ep;
|
||||||
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
||||||
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_OUT, buf, 64) != 64) return;
|
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_MAIN_OUT, buf, 64) != 64) return;
|
||||||
debugLog(0, "", "hid_rx_callback");
|
debugLog(0, "", "main_rx_callback");
|
||||||
if (!tiny) {
|
if (!tiny) {
|
||||||
msg_read(buf, 64);
|
msg_read(buf, 64);
|
||||||
} else {
|
} else {
|
||||||
@ -353,23 +285,23 @@ static void hid_rx_callback(usbd_device *dev, uint8_t ep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hid_u2f_rx_callback(usbd_device *dev, uint8_t ep)
|
static void u2f_rx_callback(usbd_device *dev, uint8_t ep)
|
||||||
{
|
{
|
||||||
(void)ep;
|
(void)ep;
|
||||||
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
||||||
|
|
||||||
debugLog(0, "", "hid_u2f_rx_callback");
|
debugLog(0, "", "u2f_rx_callback");
|
||||||
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return;
|
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_U2F_OUT, buf, 64) != 64) return;
|
||||||
u2fhid_read(tiny, (const U2FHID_FRAME *) (void*) buf);
|
u2fhid_read(tiny, (const U2FHID_FRAME *) (void*) buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
static void hid_debug_rx_callback(usbd_device *dev, uint8_t ep)
|
static void debug_rx_callback(usbd_device *dev, uint8_t ep)
|
||||||
{
|
{
|
||||||
(void)ep;
|
(void)ep;
|
||||||
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
static CONFIDENTIAL uint8_t buf[64] __attribute__ ((aligned(4)));
|
||||||
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_DEBUG_OUT, buf, 64) != 64) return;
|
if ( usbd_ep_read_packet(dev, ENDPOINT_ADDRESS_DEBUG_OUT, buf, 64) != 64) return;
|
||||||
debugLog(0, "", "hid_debug_rx_callback");
|
debugLog(0, "", "debug_rx_callback");
|
||||||
if (!tiny) {
|
if (!tiny) {
|
||||||
msg_debug_read(buf, 64);
|
msg_debug_read(buf, 64);
|
||||||
} else {
|
} else {
|
||||||
@ -378,17 +310,17 @@ static void hid_debug_rx_callback(usbd_device *dev, uint8_t ep)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void hid_set_config(usbd_device *dev, uint16_t wValue)
|
static void set_config(usbd_device *dev, uint16_t wValue)
|
||||||
{
|
{
|
||||||
(void)wValue;
|
(void)wValue;
|
||||||
|
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_MAIN_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_rx_callback);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_MAIN_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, main_rx_callback);
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_u2f_rx_callback);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_U2F_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, u2f_rx_callback);
|
||||||
#if DEBUG_LINK
|
#if DEBUG_LINK
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_IN, USB_ENDPOINT_ATTR_INTERRUPT, 64, 0);
|
||||||
usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, hid_debug_rx_callback);
|
usbd_ep_setup(dev, ENDPOINT_ADDRESS_DEBUG_OUT, USB_ENDPOINT_ATTR_INTERRUPT, 64, debug_rx_callback);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
usbd_register_control_callback(
|
usbd_register_control_callback(
|
||||||
@ -399,12 +331,29 @@ static void hid_set_config(usbd_device *dev, uint16_t wValue)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static usbd_device *usbd_dev;
|
static usbd_device *usbd_dev;
|
||||||
static uint8_t usbd_control_buffer[128];
|
static uint8_t usbd_control_buffer[256] __attribute__ ((aligned (2)));
|
||||||
|
|
||||||
|
static const struct usb_device_capability_descriptor* capabilities[] = {
|
||||||
|
(const struct usb_device_capability_descriptor*)&webusb_platform_capability_descriptor,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct usb_bos_descriptor bos_descriptor = {
|
||||||
|
.bLength = USB_DT_BOS_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_BOS,
|
||||||
|
.bNumDeviceCaps = sizeof(capabilities)/sizeof(capabilities[0]),
|
||||||
|
.capabilities = capabilities
|
||||||
|
};
|
||||||
|
|
||||||
void usbInit(void)
|
void usbInit(void)
|
||||||
{
|
{
|
||||||
usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, sizeof(usb_strings) / sizeof(*usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer));
|
usbd_dev = usbd_init(&otgfs_usb_driver, &dev_descr, &config, usb_strings, sizeof(usb_strings) / sizeof(*usb_strings), usbd_control_buffer, sizeof(usbd_control_buffer));
|
||||||
usbd_register_set_config_callback(usbd_dev, hid_set_config);
|
usbd_register_set_config_callback(usbd_dev, set_config);
|
||||||
|
usb21_setup(usbd_dev, &bos_descriptor);
|
||||||
|
static const char* origin_url = "trezor.io/start";
|
||||||
|
webusb_setup(usbd_dev, origin_url);
|
||||||
|
// Debug link interface does not have WinUSB set;
|
||||||
|
// if you really need debug link on windows, edit the descriptor in winusb.c
|
||||||
|
winusb_setup(usbd_dev, USB_INTERFACE_INDEX_MAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbPoll(void)
|
void usbPoll(void)
|
||||||
@ -415,7 +364,7 @@ void usbPoll(void)
|
|||||||
// write pending data
|
// write pending data
|
||||||
data = msg_out_data();
|
data = msg_out_data();
|
||||||
if (data) {
|
if (data) {
|
||||||
while ( usbd_ep_write_packet(usbd_dev, ENDPOINT_ADDRESS_IN, data, 64) != 64 ) {}
|
while ( usbd_ep_write_packet(usbd_dev, ENDPOINT_ADDRESS_MAIN_IN, data, 64) != 64 ) {}
|
||||||
}
|
}
|
||||||
data = u2f_out_data();
|
data = u2f_out_data();
|
||||||
if (data) {
|
if (data) {
|
||||||
|
@ -22,10 +22,8 @@
|
|||||||
#include <libopencm3/usb/usbd.h>
|
#include <libopencm3/usb/usbd.h>
|
||||||
|
|
||||||
/* USB 3.1 Descriptor Types - Table 9-6 */
|
/* USB 3.1 Descriptor Types - Table 9-6 */
|
||||||
#define USB_DT_BOS 15
|
#define USB_DT_BOS 15
|
||||||
#define USB_DT_DEVICE_CAPABILITY 16
|
#define USB_DT_DEVICE_CAPABILITY 16
|
||||||
#define USB_DT_SUPERSPEED_USB_ENDPOINT_COMPANION 48
|
|
||||||
#define USB_DT_SUPERSPEEDPLUS_ISOCHRONOUS_ENDPOINT_COMPANION 49
|
|
||||||
|
|
||||||
struct usb_device_capability_descriptor {
|
struct usb_device_capability_descriptor {
|
||||||
uint8_t bLength;
|
uint8_t bLength;
|
||||||
@ -45,18 +43,7 @@ struct usb_bos_descriptor {
|
|||||||
#define USB_DT_BOS_SIZE 5
|
#define USB_DT_BOS_SIZE 5
|
||||||
|
|
||||||
/* USB Device Capability Types - USB 3.1 Table 9-14 */
|
/* USB Device Capability Types - USB 3.1 Table 9-14 */
|
||||||
#define USB_DC_WIRELESS_USB 1
|
#define USB_DC_PLATFORM 5
|
||||||
#define USB_DC_USB_2_0_EXTENSION 2
|
|
||||||
#define USB_DC_SUPERSPEED_USB 3
|
|
||||||
#define USB_DC_CONTAINER_ID 4
|
|
||||||
#define USB_DC_PLATFORM 5
|
|
||||||
#define USB_DC_POWER_DELIVERY_CAPABILITY 6
|
|
||||||
#define USB_DC_BATTERY_INFO_CAPABILITY 7
|
|
||||||
#define USB_DC_PD_CONSUMER_PORT_CAPABILITY 8
|
|
||||||
#define USB_DC_PD_PROVIDER_PORT_CAPABILITY 9
|
|
||||||
#define USB_DC_SUPERSPEED_PLUS 10
|
|
||||||
#define USB_DC_PRECISION_TIME_MEASUREMENT 11
|
|
||||||
#define USB_DC_WIRELESS_USB_EXT 12
|
|
||||||
|
|
||||||
extern void usb21_setup(usbd_device* usbd_dev, const struct usb_bos_descriptor* binary_object_store);
|
extern void usb21_setup(usbd_device* usbd_dev, const struct usb_bos_descriptor* binary_object_store);
|
||||||
|
|
||||||
|
94
webusb.c
Normal file
94
webusb.c
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
#include "webusb.h"
|
||||||
|
#include "usb21_standard.h"
|
||||||
|
|
||||||
|
const struct webusb_platform_descriptor webusb_platform_capability_descriptor = {
|
||||||
|
.bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE,
|
||||||
|
.bDescriptorType = USB_DT_DEVICE_CAPABILITY,
|
||||||
|
.bDevCapabilityType = USB_DC_PLATFORM,
|
||||||
|
.bReserved = 0,
|
||||||
|
.platformCapabilityUUID = WEBUSB_UUID,
|
||||||
|
.bcdVersion = 0x0100,
|
||||||
|
.bVendorCode = WEBUSB_VENDOR_CODE,
|
||||||
|
.iLandingPage = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* webusb_https_url;
|
||||||
|
|
||||||
|
static int webusb_control_vendor_request(usbd_device *usbd_dev,
|
||||||
|
struct usb_setup_data *req,
|
||||||
|
uint8_t **buf, uint16_t *len,
|
||||||
|
usbd_control_complete_callback* complete) {
|
||||||
|
(void)complete;
|
||||||
|
(void)usbd_dev;
|
||||||
|
|
||||||
|
if (req->bRequest != WEBUSB_VENDOR_CODE) {
|
||||||
|
return USBD_REQ_NEXT_CALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = USBD_REQ_NOTSUPP;
|
||||||
|
switch (req->wIndex) {
|
||||||
|
case WEBUSB_REQ_GET_URL: {
|
||||||
|
struct webusb_url_descriptor* url = (struct webusb_url_descriptor*)(*buf);
|
||||||
|
uint16_t index = req->wValue;
|
||||||
|
if (index == 0) {
|
||||||
|
return USBD_REQ_NOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 1) {
|
||||||
|
size_t url_len = strlen(webusb_https_url);
|
||||||
|
url->bLength = WEBUSB_DT_URL_DESCRIPTOR_SIZE + url_len;
|
||||||
|
url->bDescriptorType = WEBUSB_DT_URL;
|
||||||
|
url->bScheme = WEBUSB_URL_SCHEME_HTTPS;
|
||||||
|
memcpy(&url->URL, webusb_https_url, url_len);
|
||||||
|
*len = MIN(*len, url->bLength);
|
||||||
|
status = USBD_REQ_HANDLED;
|
||||||
|
} else {
|
||||||
|
// TODO: stall instead?
|
||||||
|
status = USBD_REQ_NOTSUPP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
status = USBD_REQ_NOTSUPP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void webusb_set_config(usbd_device* usbd_dev, uint16_t wValue) {
|
||||||
|
(void)wValue;
|
||||||
|
usbd_register_control_callback(
|
||||||
|
usbd_dev,
|
||||||
|
USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_DEVICE,
|
||||||
|
USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT,
|
||||||
|
webusb_control_vendor_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void webusb_setup(usbd_device* usbd_dev, const char* https_url) {
|
||||||
|
webusb_https_url = https_url;
|
||||||
|
|
||||||
|
usbd_register_set_config_callback(usbd_dev, webusb_set_config);
|
||||||
|
}
|
31
webusb.h
Normal file
31
webusb.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBUSB_H_INCLUDED
|
||||||
|
#define WEBUSB_H_INCLUDED
|
||||||
|
|
||||||
|
#include <libopencm3/usb/usbd.h>
|
||||||
|
#include "webusb_defs.h"
|
||||||
|
|
||||||
|
// Arbitrary
|
||||||
|
#define WEBUSB_VENDOR_CODE 0x01
|
||||||
|
|
||||||
|
extern const struct webusb_platform_descriptor webusb_platform_capability_descriptor;
|
||||||
|
extern void webusb_setup(usbd_device* usbd_dev, const char* https_url);
|
||||||
|
|
||||||
|
#endif
|
61
webusb_defs.h
Normal file
61
webusb_defs.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WEBUSB_DEFS_H_INCLUDED
|
||||||
|
#define WEBUSB_DEFS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define WEBUSB_REQ_GET_URL 0x02
|
||||||
|
|
||||||
|
#define WEBUSB_DT_DESCRIPTOR_SET_HEADER 0
|
||||||
|
#define WEBUSB_DT_CONFIGURATION_SUBSET_HEADER 1
|
||||||
|
#define WEBUSB_DT_FUNCTION_SUBSET_HEADER 2
|
||||||
|
#define WEBUSB_DT_URL 3
|
||||||
|
|
||||||
|
#define WEBUSB_URL_SCHEME_HTTP 0
|
||||||
|
#define WEBUSB_URL_SCHEME_HTTPS 1
|
||||||
|
|
||||||
|
struct webusb_platform_descriptor {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bDevCapabilityType;
|
||||||
|
uint8_t bReserved;
|
||||||
|
uint8_t platformCapabilityUUID[16];
|
||||||
|
uint16_t bcdVersion;
|
||||||
|
uint8_t bVendorCode;
|
||||||
|
uint8_t iLandingPage;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor)
|
||||||
|
|
||||||
|
// from https://wicg.github.io/webusb/#webusb-platform-capability-descriptor
|
||||||
|
// see also this (for endianness explanation)
|
||||||
|
// https://github.com/WICG/webusb/issues/115#issuecomment-352206549
|
||||||
|
#define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65}
|
||||||
|
|
||||||
|
struct webusb_url_descriptor {
|
||||||
|
uint8_t bLength;
|
||||||
|
uint8_t bDescriptorType;
|
||||||
|
uint8_t bScheme;
|
||||||
|
char URL[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3
|
||||||
|
|
||||||
|
#endif
|
161
winusb.c
Normal file
161
winusb.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libopencm3/usb/usbd.h>
|
||||||
|
#include "util.h"
|
||||||
|
#include "winusb.h"
|
||||||
|
|
||||||
|
static int usb_descriptor_type(uint16_t wValue) {
|
||||||
|
return wValue >> 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usb_descriptor_index(uint16_t wValue) {
|
||||||
|
return wValue & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct winusb_compatible_id_descriptor winusb_wcid = {
|
||||||
|
.header = {
|
||||||
|
.dwLength = sizeof(struct winusb_compatible_id_descriptor_header) +
|
||||||
|
1 * sizeof(struct winusb_compatible_id_function_section),
|
||||||
|
.bcdVersion = WINUSB_BCD_VERSION,
|
||||||
|
.wIndex = WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR,
|
||||||
|
.bNumSections = 1,
|
||||||
|
.reserved = { 0, 0, 0, 0, 0, 0, 0 },
|
||||||
|
},
|
||||||
|
.functions = {
|
||||||
|
{
|
||||||
|
// note - bInterfaceNumber is rewritten in winusb_setup with the correct interface number
|
||||||
|
.bInterfaceNumber = 0,
|
||||||
|
.reserved0 = { 1 },
|
||||||
|
.compatibleId = "WINUSB",
|
||||||
|
.subCompatibleId = "",
|
||||||
|
.reserved1 = { 0, 0, 0, 0, 0, 0}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct usb_string_descriptor winusb_string_descriptor = {
|
||||||
|
.bLength = 0x12,
|
||||||
|
.bDescriptorType = USB_DT_STRING,
|
||||||
|
.wData = WINUSB_EXTRA_STRING
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct winusb_extended_properties_descriptor guid = {
|
||||||
|
.header = {
|
||||||
|
.dwLength = sizeof(struct winusb_extended_properties_descriptor_header)
|
||||||
|
+ 1 * sizeof (struct winusb_extended_properties_feature_descriptor),
|
||||||
|
.bcdVersion = WINUSB_BCD_VERSION,
|
||||||
|
.wIndex = WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR,
|
||||||
|
.wNumFeatures = 1,
|
||||||
|
},
|
||||||
|
.features = {
|
||||||
|
{
|
||||||
|
.dwLength = sizeof(struct winusb_extended_properties_feature_descriptor),
|
||||||
|
.dwPropertyDataType = WINUSB_EXTENDED_PROPERTIES_MULTISZ_DATA_TYPE,
|
||||||
|
.wNameLength = WINUSB_EXTENDED_PROPERTIES_GUID_NAME_SIZE_C,
|
||||||
|
.name = WINUSB_EXTENDED_PROPERTIES_GUID_NAME,
|
||||||
|
.dwPropertyDataLength = WINUSB_EXTENDED_PROPERTIES_GUID_DATA_SIZE_C,
|
||||||
|
.propertyData = WINUSB_EXTENDED_PROPERTIES_GUID_DATA,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int winusb_descriptor_request(usbd_device *usbd_dev,
|
||||||
|
struct usb_setup_data *req,
|
||||||
|
uint8_t **buf, uint16_t *len,
|
||||||
|
usbd_control_complete_callback* complete) {
|
||||||
|
(void)complete;
|
||||||
|
(void)usbd_dev;
|
||||||
|
|
||||||
|
if ((req->bmRequestType & USB_REQ_TYPE_TYPE) != USB_REQ_TYPE_STANDARD) {
|
||||||
|
return USBD_REQ_NEXT_CALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->bRequest == USB_REQ_GET_DESCRIPTOR && usb_descriptor_type(req->wValue) == USB_DT_STRING) {
|
||||||
|
if (usb_descriptor_index(req->wValue) == WINUSB_EXTRA_STRING_INDEX) {
|
||||||
|
*buf = (uint8_t*)(&winusb_string_descriptor);
|
||||||
|
*len = MIN(*len, winusb_string_descriptor.bLength);
|
||||||
|
return USBD_REQ_HANDLED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return USBD_REQ_NEXT_CALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int winusb_control_vendor_request(usbd_device *usbd_dev,
|
||||||
|
struct usb_setup_data *req,
|
||||||
|
uint8_t **buf, uint16_t *len,
|
||||||
|
usbd_control_complete_callback* complete) {
|
||||||
|
(void)complete;
|
||||||
|
(void)usbd_dev;
|
||||||
|
|
||||||
|
if (req->bRequest != WINUSB_MS_VENDOR_CODE) {
|
||||||
|
return USBD_REQ_NEXT_CALLBACK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = USBD_REQ_NOTSUPP;
|
||||||
|
if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_DEVICE) &&
|
||||||
|
(req->wIndex == WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR)) {
|
||||||
|
*buf = (uint8_t*)(&winusb_wcid);
|
||||||
|
*len = MIN(*len, winusb_wcid.header.dwLength);
|
||||||
|
status = USBD_REQ_HANDLED;
|
||||||
|
|
||||||
|
} else if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_INTERFACE) &&
|
||||||
|
(req->wIndex == WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR) &&
|
||||||
|
(usb_descriptor_index(req->wValue) == winusb_wcid.functions[0].bInterfaceNumber)) {
|
||||||
|
|
||||||
|
*buf = (uint8_t*)(&guid);
|
||||||
|
*len = MIN(*len, guid.header.dwLength);
|
||||||
|
status = USBD_REQ_HANDLED;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
status = USBD_REQ_NOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void winusb_set_config(usbd_device* usbd_dev, uint16_t wValue) {
|
||||||
|
(void)wValue;
|
||||||
|
usbd_register_control_callback(
|
||||||
|
usbd_dev,
|
||||||
|
USB_REQ_TYPE_VENDOR,
|
||||||
|
USB_REQ_TYPE_TYPE,
|
||||||
|
winusb_control_vendor_request);
|
||||||
|
}
|
||||||
|
|
||||||
|
void winusb_setup(usbd_device* usbd_dev, uint8_t interface) {
|
||||||
|
winusb_wcid.functions[0].bInterfaceNumber = interface;
|
||||||
|
|
||||||
|
usbd_register_set_config_callback(usbd_dev, winusb_set_config);
|
||||||
|
|
||||||
|
/* Windows probes the compatible ID before setting the configuration,
|
||||||
|
so also register the callback now */
|
||||||
|
|
||||||
|
usbd_register_control_callback(
|
||||||
|
usbd_dev,
|
||||||
|
USB_REQ_TYPE_VENDOR,
|
||||||
|
USB_REQ_TYPE_TYPE,
|
||||||
|
winusb_control_vendor_request);
|
||||||
|
|
||||||
|
usbd_register_control_callback(
|
||||||
|
usbd_dev,
|
||||||
|
USB_REQ_TYPE_DEVICE,
|
||||||
|
USB_REQ_TYPE_RECIPIENT,
|
||||||
|
winusb_descriptor_request);
|
||||||
|
}
|
||||||
|
|
30
winusb.h
Normal file
30
winusb.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINUSB_H_INCLUDED
|
||||||
|
#define WINUSB_H_INCLUDED
|
||||||
|
|
||||||
|
#include "winusb_defs.h"
|
||||||
|
|
||||||
|
// Arbitrary, but must be equivalent to the last character in extra string
|
||||||
|
#define WINUSB_MS_VENDOR_CODE '!'
|
||||||
|
#define WINUSB_EXTRA_STRING {'M', 'S', 'F', 'T', '1', '0', '0', WINUSB_MS_VENDOR_CODE}
|
||||||
|
|
||||||
|
extern void winusb_setup(usbd_device* usbd_dev, uint8_t interface);
|
||||||
|
|
||||||
|
#endif
|
89
winusb_defs.h
Normal file
89
winusb_defs.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, Devan Lai
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software
|
||||||
|
* for any purpose with or without fee is hereby granted, provided
|
||||||
|
* that the above copyright notice and this permission notice
|
||||||
|
* appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
||||||
|
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
||||||
|
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||||
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef WINUSB_DEFS_H_INCLUDED
|
||||||
|
#define WINUSB_DEFS_H_INCLUDED
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Microsoft OS 1.0 descriptors */
|
||||||
|
|
||||||
|
/* Extended Compat ID OS Feature Descriptor Specification */
|
||||||
|
#define WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04
|
||||||
|
#define WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05
|
||||||
|
#define WINUSB_BCD_VERSION 0x0100
|
||||||
|
|
||||||
|
// Apparently using DeviceInterfaceGUID does not always work on Windows 7.
|
||||||
|
// DeviceInterfaceGUIDs does seem to work.
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_NAME u"DeviceInterfaceGUIDs"
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_NAME_SIZE_C sizeof(WINUSB_EXTENDED_PROPERTIES_GUID_NAME)
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_NAME_SIZE_U (sizeof(WINUSB_EXTENDED_PROPERTIES_GUID_NAME) / 2)
|
||||||
|
|
||||||
|
// extra null is intentional - it's an array of GUIDs with 1 item
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_DATA u"{0263b512-88cb-4136-9613-5c8e109d8ef5}\x00"
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_DATA_SIZE_C sizeof(WINUSB_EXTENDED_PROPERTIES_GUID_DATA)
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_GUID_DATA_SIZE_U (sizeof(WINUSB_EXTENDED_PROPERTIES_GUID_DATA) / 2)
|
||||||
|
#define WINUSB_EXTENDED_PROPERTIES_MULTISZ_DATA_TYPE 7
|
||||||
|
|
||||||
|
#define WINUSB_EXTRA_STRING_INDEX 0xee
|
||||||
|
|
||||||
|
/* Table 2. Function Section */
|
||||||
|
struct winusb_compatible_id_function_section {
|
||||||
|
uint8_t bInterfaceNumber;
|
||||||
|
uint8_t reserved0[1];
|
||||||
|
char compatibleId[8];
|
||||||
|
char subCompatibleId[8];
|
||||||
|
uint8_t reserved1[6];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* Table 1. Header Section */
|
||||||
|
struct winusb_compatible_id_descriptor_header {
|
||||||
|
uint32_t dwLength;
|
||||||
|
uint16_t bcdVersion;
|
||||||
|
uint16_t wIndex;
|
||||||
|
uint8_t bNumSections;
|
||||||
|
uint8_t reserved[7];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct winusb_compatible_id_descriptor {
|
||||||
|
struct winusb_compatible_id_descriptor_header header;
|
||||||
|
struct winusb_compatible_id_function_section functions[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct winusb_extended_properties_feature_descriptor {
|
||||||
|
uint32_t dwLength;
|
||||||
|
uint32_t dwPropertyDataType;
|
||||||
|
uint16_t wNameLength;
|
||||||
|
uint16_t name[WINUSB_EXTENDED_PROPERTIES_GUID_NAME_SIZE_U];
|
||||||
|
uint32_t dwPropertyDataLength;
|
||||||
|
uint16_t propertyData[WINUSB_EXTENDED_PROPERTIES_GUID_DATA_SIZE_U];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct winusb_extended_properties_descriptor_header {
|
||||||
|
uint32_t dwLength;
|
||||||
|
uint16_t bcdVersion;
|
||||||
|
uint16_t wIndex;
|
||||||
|
uint16_t wNumFeatures;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct winusb_extended_properties_descriptor {
|
||||||
|
struct winusb_extended_properties_descriptor_header header;
|
||||||
|
struct winusb_extended_properties_feature_descriptor features[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user