summary refs log tree commit diff
path: root/tmk_core/protocol
diff options
context:
space:
mode:
authorStanley Lai <stanleylai.sg@gmail.com>2017-02-13 12:36:22 -0800
committerStanley Lai <stanleylai.sg@gmail.com>2017-02-13 12:36:22 -0800
commita8eba1bddaf55224939a86bfa4d8e1b53e1d82db (patch)
tree906568677ed027a807d5e9c0c1bc1c2ae001f0f6 /tmk_core/protocol
parent53ea854462c0b3b2c3c58a36b714ac02f773c74f (diff)
parentfd2925efbac0d7963f3d267dd5264f08a0a4e9dc (diff)
Merge remote-tracking branch 'refs/remotes/qmk/master'
Diffstat (limited to 'tmk_core/protocol')
-rw-r--r--tmk_core/protocol/lufa.mk3
-rw-r--r--tmk_core/protocol/lufa/lufa.c148
-rw-r--r--tmk_core/protocol/lufa/lufa.h4
-rw-r--r--tmk_core/protocol/lufa/outputselect.c56
-rw-r--r--tmk_core/protocol/lufa/outputselect.h41
-rw-r--r--tmk_core/protocol/ps2_mouse.h5
-rw-r--r--tmk_core/protocol/vusb.mk3
-rw-r--r--tmk_core/protocol/vusb/main.c6
-rw-r--r--tmk_core/protocol/vusb/vusb.c22
9 files changed, 199 insertions, 89 deletions
diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk
index 151d26cbc8..de0cc795f6 100644
--- a/tmk_core/protocol/lufa.mk
+++ b/tmk_core/protocol/lufa.mk
@@ -8,13 +8,14 @@ LUFA_PATH ?= $(LUFA_DIR)/LUFA-git
 ifneq (, $(wildcard $(TMK_PATH)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk))
     # New build system from 20120730
     LUFA_ROOT_PATH = $(LUFA_PATH)/LUFA
-    include $(TMK_PATH)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk 
+    include $(TMK_PATH)/$(LUFA_PATH)/LUFA/Build/lufa_sources.mk
 else
     include $(TMK_PATH)/$(LUFA_PATH)/LUFA/makefile
 endif
 
 LUFA_SRC = lufa.c \
 	   descriptor.c \
+	   outputselect.c \
 	   $(LUFA_SRC_USB)
 
 ifeq ($(strip $(MIDI_ENABLE)), yes)
diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c
index 0971897706..ba49284c9b 100644
--- a/tmk_core/protocol/lufa/lufa.c
+++ b/tmk_core/protocol/lufa/lufa.c
@@ -53,6 +53,7 @@
 #include "lufa.h"
 #include "quantum.h"
 #include <util/atomic.h>
+#include "outputselect.h"
 
 #ifdef NKRO_ENABLE
   #include "keycode_config.h"
@@ -589,59 +590,33 @@ void EVENT_USB_Device_ControlRequest(void)
 
 /*******************************************************************************
  * Host driver
-p
  ******************************************************************************/
 static uint8_t keyboard_leds(void)
 {
     return keyboard_led_stats;
 }
 
-#define SendToUSB 1
-#define SendToBT  2
-#define SendToBLE 4
-
-static inline uint8_t where_to_send(void) {
-#ifdef ADAFRUIT_BLE_ENABLE
-#if 0
-  if (adafruit_ble_is_connected()) {
-    // For testing, send to BLE as a priority
-    return SendToBLE;
-  }
-#endif
-
-  // This is the real policy
-  if (USB_DeviceState != DEVICE_STATE_Configured) {
-    if (adafruit_ble_is_connected()) {
-      return SendToBLE;
-    }
-  }
-#endif
-  return ((USB_DeviceState == DEVICE_STATE_Configured) ? SendToUSB : 0)
-#ifdef BLUETOOTH_ENABLE
-    || SendToBT
-#endif
-    ;
-}
-
 static void send_keyboard(report_keyboard_t *report)
 {
+    uint8_t timeout = 255;
+    uint8_t where = where_to_send();
+
 #ifdef BLUETOOTH_ENABLE
-    bluefruit_serial_send(0xFD);
-    for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
-        bluefruit_serial_send(report->raw[i]);
+    if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+        bluefruit_serial_send(0xFD);
+        for (uint8_t i = 0; i < KEYBOARD_EPSIZE; i++) {
+            bluefruit_serial_send(report->raw[i]);
+        }
     }
 #endif
 
-    uint8_t timeout = 255;
-    uint8_t where = where_to_send();
-
 #ifdef ADAFRUIT_BLE_ENABLE
-    if (where & SendToBLE) {
+    if (where == OUTPUT_ADAFRUIT_BLE) {
       adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys));
     }
 #endif
 
-    if (!(where & SendToUSB)) {
+    if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
       return;
     }
 
@@ -681,30 +656,31 @@ static void send_keyboard(report_keyboard_t *report)
 static void send_mouse(report_mouse_t *report)
 {
 #ifdef MOUSE_ENABLE
+    uint8_t timeout = 255;
+    uint8_t where = where_to_send();
 
 #ifdef BLUETOOTH_ENABLE
-    bluefruit_serial_send(0xFD);
-    bluefruit_serial_send(0x00);
-    bluefruit_serial_send(0x03);
-    bluefruit_serial_send(report->buttons);
-    bluefruit_serial_send(report->x);
-    bluefruit_serial_send(report->y);
-    bluefruit_serial_send(report->v); // should try sending the wheel v here
-    bluefruit_serial_send(report->h); // should try sending the wheel h here
-    bluefruit_serial_send(0x00);
+    if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+        bluefruit_serial_send(0xFD);
+        bluefruit_serial_send(0x00);
+        bluefruit_serial_send(0x03);
+        bluefruit_serial_send(report->buttons);
+        bluefruit_serial_send(report->x);
+        bluefruit_serial_send(report->y);
+        bluefruit_serial_send(report->v); // should try sending the wheel v here
+        bluefruit_serial_send(report->h); // should try sending the wheel h here
+        bluefruit_serial_send(0x00);
+    }
 #endif
 
-    uint8_t timeout = 255;
-
-    uint8_t where = where_to_send();
-
 #ifdef ADAFRUIT_BLE_ENABLE
-    if (where & SendToBLE) {
+    if (where == OUTPUT_ADAFRUIT_BLE) {
       // FIXME: mouse buttons
       adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h);
     }
 #endif
-    if (!(where & SendToUSB)) {
+
+    if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
       return;
     }
 
@@ -746,32 +722,34 @@ static void send_system(uint16_t data)
 
 static void send_consumer(uint16_t data)
 {
+    uint8_t timeout = 255;
+    uint8_t where = where_to_send();
 
 #ifdef BLUETOOTH_ENABLE
-    static uint16_t last_data = 0;
-    if (data == last_data) return;
-    last_data = data;
-    uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
-    bluefruit_serial_send(0xFD);
-    bluefruit_serial_send(0x00);
-    bluefruit_serial_send(0x02);
-    bluefruit_serial_send((bitmap>>8)&0xFF);
-    bluefruit_serial_send(bitmap&0xFF);
-    bluefruit_serial_send(0x00);
-    bluefruit_serial_send(0x00);
-    bluefruit_serial_send(0x00);
-    bluefruit_serial_send(0x00);
+    if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) {
+        static uint16_t last_data = 0;
+        if (data == last_data) return;
+        last_data = data;
+        uint16_t bitmap = CONSUMER2BLUEFRUIT(data);
+        bluefruit_serial_send(0xFD);
+        bluefruit_serial_send(0x00);
+        bluefruit_serial_send(0x02);
+        bluefruit_serial_send((bitmap>>8)&0xFF);
+        bluefruit_serial_send(bitmap&0xFF);
+        bluefruit_serial_send(0x00);
+        bluefruit_serial_send(0x00);
+        bluefruit_serial_send(0x00);
+        bluefruit_serial_send(0x00);
+    }
 #endif
 
-    uint8_t timeout = 255;
-    uint8_t where = where_to_send();
-
 #ifdef ADAFRUIT_BLE_ENABLE
-    if (where & SendToBLE) {
+    if (where == OUTPUT_ADAFRUIT_BLE) {
       adafruit_ble_send_consumer_key(data, 0);
     }
 #endif
-    if (!(where & SendToUSB)) {
+
+    if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) {
       return;
     }
 
@@ -1252,28 +1230,40 @@ void cc_callback(MidiDevice * device,
   // midi_send_cc(device, (chan + 1) % 16, num, val);
 }
 
+#ifdef API_SYSEX_ENABLE
 uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0};
+#endif
 
 void sysex_callback(MidiDevice * device, uint16_t start, uint8_t length, uint8_t * data) {
     #ifdef API_SYSEX_ENABLE
         // SEND_STRING("\n");
         // send_word(start);
         // SEND_STRING(": ");
+        // Don't store the header
+        int16_t pos = start - 4;
         for (uint8_t place = 0; place < length; place++) {
             // send_byte(*data);
-            midi_buffer[start + place] = *data;
-            if (*data == 0xF7) {
-                // SEND_STRING("\nRD: ");
-                // for (uint8_t i = 0; i < start + place + 1; i++){
-                //     send_byte(midi_buffer[i]);
-                // SEND_STRING(" ");
-                // }
-                uint8_t * decoded = malloc(sizeof(uint8_t) * (sysex_decoded_length(start + place - 4)));
-                uint16_t decode_length = sysex_decode(decoded, midi_buffer + 4, start + place - 4);
-                process_api(decode_length, decoded);
+            if (pos >= 0) {
+                if (*data == 0xF7) {
+                    // SEND_STRING("\nRD: ");
+                    // for (uint8_t i = 0; i < start + place + 1; i++){
+                    //     send_byte(midi_buffer[i]);
+                    // SEND_STRING(" ");
+                    // }
+                    const unsigned decoded_length = sysex_decoded_length(pos);
+                    uint8_t decoded[API_SYSEX_MAX_SIZE];
+                    sysex_decode(decoded, midi_buffer, pos);
+                    process_api(decoded_length, decoded);
+                    return;
+                }
+                else if (pos >= MIDI_SYSEX_BUFFER) {
+                    return;
+                }
+                midi_buffer[pos] = *data;
             }
             // SEND_STRING(" ");
             data++;
+            pos++;
         }
     #endif
 }
diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h
index b11854101d..a049fd43c9 100644
--- a/tmk_core/protocol/lufa/lufa.h
+++ b/tmk_core/protocol/lufa/lufa.h
@@ -70,7 +70,6 @@ typedef struct {
 #ifdef MIDI_ENABLE
   void MIDI_Task(void);
   MidiDevice midi_device;
-  #define MIDI_SYSEX_BUFFER 32 
 #endif
 
 #ifdef API_ENABLE
@@ -79,6 +78,9 @@ typedef struct {
 
 #ifdef API_SYSEX_ENABLE
   #include "api_sysex.h"
+  // Allocate space for encoding overhead.
+  //The header and terminator are not stored to save a few bytes of precious ram
+  #define MIDI_SYSEX_BUFFER (API_SYSEX_MAX_SIZE + API_SYSEX_MAX_SIZE / 7 + (API_SYSEX_MAX_SIZE % 7 ? 1 : 0))
 #endif
 
 // #if LUFA_VERSION_INTEGER < 0x120730
diff --git a/tmk_core/protocol/lufa/outputselect.c b/tmk_core/protocol/lufa/outputselect.c
new file mode 100644
index 0000000000..5d2457bfff
--- /dev/null
+++ b/tmk_core/protocol/lufa/outputselect.c
@@ -0,0 +1,56 @@
+/*
+Copyright 2017 Priyadi Iman Nurcahyo
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "lufa.h"
+#include "outputselect.h"
+#ifdef ADAFRUIT_BLE_ENABLE
+    #include "adafruit_ble.h"
+#endif
+
+uint8_t desired_output = OUTPUT_DEFAULT;
+
+void set_output(uint8_t output) {
+    set_output_user(output);
+    desired_output = output;
+}
+
+__attribute__((weak))
+void set_output_user(uint8_t output) {
+}
+
+uint8_t auto_detect_output(void) {
+    if (USB_DeviceState == DEVICE_STATE_Configured) {
+        return OUTPUT_USB;
+    }
+
+#ifdef ADAFRUIT_BLE_ENABLE
+    if (adafruit_ble_is_connected()) {
+        return OUTPUT_ADAFRUIT_BLE;
+    }
+#endif
+
+#ifdef BLUETOOTH_ENABLE
+    return OUTPUT_BLUETOOTH; // should check if BT is connected here
+#endif
+
+    return OUTPUT_NONE;
+}
+
+uint8_t where_to_send(void) {
+    if (desired_output == OUTPUT_AUTO) {
+        return auto_detect_output();
+    }
+    return desired_output;
+}
+
diff --git a/tmk_core/protocol/lufa/outputselect.h b/tmk_core/protocol/lufa/outputselect.h
new file mode 100644
index 0000000000..79b4dd35dd
--- /dev/null
+++ b/tmk_core/protocol/lufa/outputselect.h
@@ -0,0 +1,41 @@
+/*
+Copyright 2017 Priyadi Iman Nurcahyo
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+enum outputs {
+    OUTPUT_AUTO,
+
+    OUTPUT_NONE,
+    OUTPUT_USB,
+    OUTPUT_BLUETOOTH,
+    OUTPUT_ADAFRUIT_BLE,
+
+    // backward compatibility
+    OUTPUT_USB_AND_BT
+};
+
+/**
+ * backward compatibility for BLUETOOTH_ENABLE, send to BT and USB by default
+ */
+#ifndef OUTPUT_DEFAULT
+    #ifdef BLUETOOTH_ENABLE
+        #define OUTPUT_DEFAULT OUTPUT_USB_AND_BT
+    #else
+        #define OUTPUT_DEFAULT OUTPUT_AUTO
+    #endif
+#endif
+
+void set_output(uint8_t output);
+void set_output_user(uint8_t output);
+uint8_t auto_detect_output(void);
+uint8_t where_to_send(void);
\ No newline at end of file
diff --git a/tmk_core/protocol/ps2_mouse.h b/tmk_core/protocol/ps2_mouse.h
index 3c93a46342..eeeffe4d80 100644
--- a/tmk_core/protocol/ps2_mouse.h
+++ b/tmk_core/protocol/ps2_mouse.h
@@ -23,7 +23,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 #define PS2_MOUSE_SEND(command, message) \
 do { \
-   uint8_t rcv = ps2_host_send(command); \
+   __attribute__ ((unused)) uint8_t rcv = ps2_host_send(command); \
    if (debug_mouse) { \
         print((message)); \
         xprintf(" command: %X, result: %X, error: %X \n", command, rcv, ps2_error); \
@@ -55,13 +55,14 @@ do { \
 
 #define PS2_MOUSE_RECEIVE(message) \
 do { \
-   uint8_t rcv = ps2_host_recv_response(); \
+   __attribute__ ((unused)) uint8_t rcv = ps2_host_recv_response(); \
    if (debug_mouse) { \
         print((message)); \
         xprintf(" result: %X, error: %X \n", rcv, ps2_error); \
     } \
 } while(0)
 
+__attribute__ ((unused))
 static enum ps2_mouse_mode_e {
     PS2_MOUSE_STREAM_MODE,
     PS2_MOUSE_REMOTE_MODE,
diff --git a/tmk_core/protocol/vusb.mk b/tmk_core/protocol/vusb.mk
index 3cba3f71a3..897b833e1a 100644
--- a/tmk_core/protocol/vusb.mk
+++ b/tmk_core/protocol/vusb.mk
@@ -18,4 +18,5 @@ endif
 
 
 # Search Path
-VPATH += $(TMK_DIR)/protocol/vusb:$(TMK_DIR)/protocol/vusb/usbdrv
+VPATH += $(TMK_PATH)/$(VUSB_DIR)
+VPATH += $(TMK_PATH)/$(VUSB_DIR)/usbdrv
diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c
index 8e4a266e9b..f6a0c7e9a4 100644
--- a/tmk_core/protocol/vusb/main.c
+++ b/tmk_core/protocol/vusb/main.c
@@ -48,8 +48,12 @@ int main(void)
     uint16_t last_timer = timer_read();
 #endif
 
+#ifdef CLKPR
+    // avoid unintentional changes of clock frequency in devices that have a
+    // clock prescaler
     CLKPR = 0x80, CLKPR = 0;
-#ifndef PS2_USE_USART
+#endif
+#ifndef NO_UART
     uart_init(UART_BAUD_RATE);
 #endif
 
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index eaa1c512d8..022ac6f6bd 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
+#include <avr/eeprom.h>
+#include <avr/wdt.h>
 #include <stdint.h>
 #include "usbdrv.h"
 #include "usbconfig.h"
@@ -24,6 +26,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #include "debug.h"
 #include "host_driver.h"
 #include "vusb.h"
+#include "bootloader.h"
 
 
 static uint8_t vusb_keyboard_leds = 0;
@@ -163,6 +166,7 @@ static struct {
     uint16_t        len;
     enum {
         NONE,
+        BOOTLOADER,
         SET_LED
     }               kind;
 } last_req;
@@ -193,6 +197,11 @@ usbRequest_t    *rq = (void *)data;
                 debug("SET_LED: ");
                 last_req.kind = SET_LED;
                 last_req.len = rq->wLength.word;
+#ifdef BOOTLOADER_SIZE
+            } else if(rq->wValue.word == 0x0301) {
+                last_req.kind = BOOTLOADER;
+                last_req.len = rq->wLength.word;
+#endif
             }
             return USB_NO_MSG; // to get data in usbFunctionWrite
         } else {
@@ -220,6 +229,11 @@ uchar usbFunctionWrite(uchar *data, uchar len)
             last_req.len = 0;
             return 1;
             break;
+        case BOOTLOADER:
+            usbDeviceDisconnect();
+            bootloader_jump();
+            return 1;
+            break;
         case NONE:
         default:
             return -1;
@@ -266,7 +280,7 @@ const PROGMEM uchar keyboard_hid_report[] = {
     0x95, 0x06,          //   Report Count (6),
     0x75, 0x08,          //   Report Size (8),
     0x15, 0x00,          //   Logical Minimum (0),
-    0x25, 0xFF, 0x00     //   Logical Maximum(255),
+    0x26, 0xFF, 0x00,    //   Logical Maximum(255),
     0x05, 0x07,          //   Usage Page (Key Codes),
     0x19, 0x00,          //   Usage Minimum (0),
     0x29, 0xFF,          //   Usage Maximum (255),
@@ -336,7 +350,7 @@ const PROGMEM uchar mouse_hid_report[] = {
     0xa1, 0x01,                    // COLLECTION (Application)
     0x85, REPORT_ID_SYSTEM,        //   REPORT_ID (2)
     0x15, 0x01,                    //   LOGICAL_MINIMUM (0x1)
-    0x25, 0xb7, 0x00               //   LOGICAL_MAXIMUM (0xb7)
+    0x26, 0xb7, 0x00,              //   LOGICAL_MAXIMUM (0xb7)
     0x19, 0x01,                    //   USAGE_MINIMUM (0x1)
     0x29, 0xb7,                    //   USAGE_MAXIMUM (0xb7)
     0x75, 0x10,                    //   REPORT_SIZE (16)
@@ -481,11 +495,11 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq)
             /* interface index */
             switch (rq->wIndex.word) {
                 case 0:
-                    usbMsgPtr = keyboard_hid_report;
+                    usbMsgPtr = (unsigned char *)keyboard_hid_report;
                     len = sizeof(keyboard_hid_report);
                     break;
                 case 1:
-                    usbMsgPtr = mouse_hid_report;
+                    usbMsgPtr = (unsigned char *)mouse_hid_report;
                     len = sizeof(mouse_hid_report);
                     break;
             }