diff --git a/webusb.c b/webusb.c new file mode 100644 index 0000000..beb909c --- /dev/null +++ b/webusb.c @@ -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 + +#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); +} diff --git a/webusb.h b/webusb.h new file mode 100644 index 0000000..f41695f --- /dev/null +++ b/webusb.h @@ -0,0 +1,32 @@ +/* + * 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 +#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_urls, size_t num_https_urls); + +#endif diff --git a/webusb_defs.h b/webusb_defs.h new file mode 100644 index 0000000..45b5f24 --- /dev/null +++ b/webusb_defs.h @@ -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 + +#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