summaryrefslogtreecommitdiff
path: root/tmk_core/protocol/lufa/lufa.c
diff options
context:
space:
mode:
Diffstat (limited to 'tmk_core/protocol/lufa/lufa.c')
-rw-r--r--tmk_core/protocol/lufa/lufa.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 85d71d0835..b1af36d113 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -85,6 +85,9 @@ extern keymap_config_t keymap_config;
# include "raw_hid.h"
#endif
+#ifdef WEBUSB_ENABLE
+# include "webusb.h"
+#endif
#ifdef JOYSTICK_ENABLE
# include "joystick.h"
#endif
@@ -307,6 +310,66 @@ 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_Write_Stream_LE(data, length, NULL)) {
+ // Stream failed to complete, resetting WEBUSB's state
+ webusb_state.paired = false;
+ webusb_state.pairing = false;
+ }
+ Endpoint_ClearIN();
+}
+
+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
+
/*******************************************************************************
* Joystick
******************************************************************************/
@@ -509,6 +572,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
/* Setup MIDI stream endpoints */
ConfigSuccess &= Endpoint_ConfigureEndpoint((MIDI_STREAM_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_BULK, MIDI_STREAM_EPSIZE, 1);
@@ -647,6 +716,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
@@ -797,7 +908,13 @@ static void send_system(uint16_t data) {
static void send_consumer(uint16_t data) {
#ifdef EXTRAKEY_ENABLE
# ifdef BLUETOOTH_ENABLE
+<<<<<<< HEAD
+ uint8_t where = where_to_send();
+
+ if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+=======
if (where_to_send() == OUTPUT_BLUETOOTH) {
+>>>>>>> 0.12.52~1
# ifdef MODULE_ADAFRUIT_BLE
adafruit_ble_send_consumer_key(data);
# elif MODULE_RN42
@@ -811,6 +928,12 @@ static void send_consumer(uint16_t data) {
serial_send(bitmap & 0xFF);
serial_send((bitmap >> 8) & 0xFF);
# endif
+<<<<<<< HEAD
+ }
+
+ if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
+=======
+>>>>>>> 0.12.52~1
return;
}
# endif
@@ -829,7 +952,11 @@ static void send_consumer(uint16_t data) {
* FIXME: Needs doc
*/
int8_t sendchar(uint8_t c) {
+<<<<<<< HEAD
+ // Not wait once timeouted.
+=======
// Do not wait if the previous write has timed_out.
+>>>>>>> 0.12.52~1
// Because sendchar() is called so many times, waiting each call causes big lag.
// The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state.
static bool timed_out = false;
@@ -1102,6 +1229,10 @@ int main(void) {
raw_hid_task();
#endif
+#ifdef WEBUSB_ENABLE
+ webusb_task();
+#endif
+
#if !defined(INTERRUPT_CONTROL_ENDPOINT)
USB_USBTask();
#endif