From ae96eed205c736275b6498ba50946e99a0a35485 Mon Sep 17 00:00:00 2001 From: Florian Didron Date: Mon, 4 Nov 2019 18:50:06 +0900 Subject: feat: adds webusb --- tmk_core/protocol/chibios/usb_main.c | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'tmk_core/protocol/chibios') diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index c8a6bbb43f..e2440601e3 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -151,6 +151,22 @@ static const USBEndpointConfig shared_ep_config = { }; #endif +#ifdef WEBUSB_ENABLE +/** Microsoft OS 2.0 Descriptor. This is used by Windows to select the USB driver for the device. + * + * For WebUSB in Chrome, the correct driver is WinUSB, which is selected via CompatibleID. + * + * Additionally, while Chrome is built using libusb, a magic registry key needs to be set containing a GUID for + * the device. + */ +const MS_OS_20_Descriptor_t PROGMEM MS_OS_20_Descriptor = MS_OS_20_DESCRIPTOR; + +/** URL descriptor string. This is a UTF-8 string containing a URL excluding the prefix. At least one of these must be + * defined and returned when the Landing Page descriptor index is requested. + */ +const WebUSB_URL_Descriptor_t PROGMEM WebUSB_LandingPage = WEBUSB_URL_DESCRIPTOR(WEBUSB_LANDING_PAGE_URL); +#endif + typedef struct { size_t queue_capacity_in; size_t queue_capacity_out; @@ -232,6 +248,9 @@ typedef struct { #endif #ifdef VIRTSER_ENABLE usb_driver_config_t serial_driver; +#endif +#ifdef WEBUSB_ENABLE + usb_driver_config_t webusb_driver; #endif }; usb_driver_config_t array[0]; @@ -269,6 +288,14 @@ static usb_driver_configs_t drivers = { # define CDC_OUT_MODE USB_EP_MODE_TYPE_BULK .serial_driver = QMK_USB_DRIVER_CONFIG(CDC, CDC_NOTIFICATION_EPNUM, false), #endif + +#ifdef WEBUSB_ENABLE +# define WEBUSB_IN_CAPACITY 4 +# define WEBUSB_OUT_CAPACITY 4 +# define WEBUSB_IN_MODE USB_EP_MODE_TYPE_INTR +# define WEBUSB_OUT_MODE USB_EP_MODE_TYPE_INTR + .webusb_driver = QMK_USB_DRIVER_CONFIG(WEBUSB, 0, false), +#endif }; #define NUM_USB_DRIVERS (sizeof(drivers) / sizeof(usb_driver_config_t)) @@ -496,6 +523,27 @@ static bool usb_request_hook_cb(USBDriver *usbp) { } } +#ifdef WEBUSB_ENABLE + switch (usbp->setup[1]) { + case WEBUSB_VENDOR_CODE: + if (usbp->setup[4] == WebUSB_RTYPE_GetURL) { + if (usbp->setup[2] == WEBUSB_LANDING_PAGE_INDEX) { + usbSetupTransfer(usbp, (uint8_t *)&WebUSB_LandingPage, WebUSB_LandingPage.Header.Size, NULL); + return TRUE; + break; + } + } + break; + + case MS_OS_20_VENDOR_CODE: + if (usbp->setup[4] == MS_OS_20_DESCRIPTOR_INDEX) { + usbSetupTransfer(usbp, (uint8_t *)&MS_OS_20_Descriptor, MS_OS_20_Descriptor.Header.TotalLength, NULL); + return TRUE; + break; + } + break; + } +#endif /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */ if ((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) { dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4])); @@ -817,6 +865,28 @@ void raw_hid_task(void) { #endif +#ifdef WEBUSB_ENABLE +void webusb_send(uint8_t *data, uint8_t length) { chnWrite(&drivers.webusb_driver.driver, data, length); } + +__attribute__((weak)) void webusb_receive(uint8_t *data, uint8_t length) { + // Users should #include "raw_hid.h" in their own code + // and implement this function there. Leave this as weak linkage + // so users can opt to not handle data coming in. +} + +void webusb_task(void) { + uint8_t buffer[WEBUSB_EPSIZE]; + size_t size = 0; + do { + size_t size = chnReadTimeout(&drivers.webusb_driver.driver, buffer, sizeof(buffer), TIME_IMMEDIATE); + if (size > 0) { + webusb_receive(buffer, size); + } + } while (size > 0); +} + +#endif + #ifdef MIDI_ENABLE void send_midi_packet(MIDI_EventPacket_t *event) { chnWrite(&drivers.midi_driver.driver, (uint8_t *)event, sizeof(MIDI_EventPacket_t)); } -- cgit v1.2.3