diff options
author | Florian Didron <fd@librem.one> | 2019-11-04 18:50:06 +0900 |
---|---|---|
committer | Florian Didron <fdidron@users.noreply.github.com> | 2019-12-06 08:20:51 +0900 |
commit | ae96eed205c736275b6498ba50946e99a0a35485 (patch) | |
tree | 1aaa52dc94bd351a0654cf977c9f33240a700caf /tmk_core/protocol/lufa | |
parent | 560d1c53851e5c3d45c5a0f5e16a925ee21a4396 (diff) |
feat: adds webusb
Diffstat (limited to 'tmk_core/protocol/lufa')
-rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 12a6924fd0..998db1c6d8 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -268,6 +268,65 @@ static void Console_Task(void) { } #endif +#ifdef WEBUSB_ENABLE +void webusb_send(uint8_t *data, uint8_t length) { + if (USB_DeviceState != DEVICE_STATE_Configured) { + return; + } + + Endpoint_SelectEndpoint(WEBUSB_IN_EPNUM); + + if (Endpoint_IsINReady()) { + Endpoint_Write_Stream_LE(data, length, NULL); + Endpoint_ClearIN(); + } +} + +__attribute__((weak)) void webusb_receive(uint8_t *data, uint8_t length) { } + +static void webusb_task(void) { + // Create a temporary buffer to hold the read in data from the host + uint8_t data[WEBUSB_EPSIZE]; + bool data_read = false; + + // Device must be connected and configured for the task to run + if (USB_DeviceState != DEVICE_STATE_Configured) return; + + Endpoint_SelectEndpoint(WEBUSB_OUT_EPNUM); + + // Check to see if a packet has been sent from the host + if (Endpoint_IsOUTReceived()) { + // Check to see if the packet contains data + if (Endpoint_IsReadWriteAllowed()) { + /* Read data */ + Endpoint_Read_Stream_LE(data, sizeof(data), NULL); + data_read = true; + } + + // Finalize the stream transfer to receive the last packet + Endpoint_ClearOUT(); + + if (data_read) { + webusb_receive(data, sizeof(data)); + } + } +} + +/** 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 + /******************************************************************************* * USB Events ******************************************************************************/ @@ -405,6 +464,12 @@ void EVENT_USB_Device_ConfigurationChanged(void) { # endif #endif +#ifdef WEBUSB_ENABLE + /* Setup Webusb Endpoints */ + ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_IN_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); + ConfigSuccess &= Endpoint_ConfigureEndpoint(WEBUSB_OUT_EPADDR, EP_TYPE_INTERRUPT, WEBUSB_EPSIZE, 1); +#endif + #ifdef MIDI_ENABLE ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_IN_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); ConfigSuccess &= Endpoint_ConfigureEndpoint(MIDI_STREAM_OUT_EPADDR, EP_TYPE_BULK, MIDI_STREAM_EPSIZE, ENDPOINT_BANK_SINGLE); @@ -536,6 +601,48 @@ void EVENT_USB_Device_ControlRequest(void) { } break; +#ifdef WEBUSB_ENABLE + case WEBUSB_VENDOR_CODE: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE)) { + switch (USB_ControlRequest.wIndex) { + case WebUSB_RTYPE_GetURL: + switch (USB_ControlRequest.wValue) { + case WEBUSB_LANDING_PAGE_INDEX: + Endpoint_ClearSETUP(); + /* Write the descriptor data to the control endpoint */ + Endpoint_Write_Control_PStream_LE(&WebUSB_LandingPage, WebUSB_LandingPage.Header.Size); + /* Release the endpoint after transaction. */ + Endpoint_ClearStatusStage(); + break; + default: /* Stall transfer on invalid index. */ + Endpoint_StallTransaction(); + break; + } + break; + default: /* Stall on unknown WebUSB request */ + Endpoint_StallTransaction(); + break; + } + } + + break; + case MS_OS_20_VENDOR_CODE: + if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_VENDOR | REQREC_DEVICE)) { + switch (USB_ControlRequest.wIndex) { + case MS_OS_20_DESCRIPTOR_INDEX: + Endpoint_ClearSETUP(); + /* Write the descriptor data to the control endpoint */ + Endpoint_Write_Control_PStream_LE(&MS_OS_20_Descriptor, MS_OS_20_Descriptor.Header.TotalLength); + /* Release the endpoint after transaction. */ + Endpoint_ClearStatusStage(); + break; + default: /* Stall on unknown MS OS 2.0 request */ + Endpoint_StallTransaction(); + break; + } + } + break; +#endif } #ifdef VIRTSER_ENABLE @@ -1018,6 +1125,10 @@ int main(void) { raw_hid_task(); #endif +#ifdef WEBUSB_ENABLE + webusb_task(); +#endif + #if !defined(INTERRUPT_CONTROL_ENDPOINT) USB_USBTask(); #endif |