Joel Challis 5 лет назад
Родитель
Сommit
5f82b0782f

+ 1 - 0
tmk_core/common.mk

@@ -10,6 +10,7 @@ TMK_COMMON_SRC +=	$(COMMON_DIR)/host.c \
 	$(COMMON_DIR)/action_util.c \
 	$(COMMON_DIR)/print.c \
 	$(COMMON_DIR)/debug.c \
+	$(COMMON_DIR)/sendchar_null.c \
 	$(COMMON_DIR)/util.c \
 	$(COMMON_DIR)/eeconfig.c \
 	$(COMMON_DIR)/report.c \

+ 1 - 1
tmk_core/common/sendchar_null.c

@@ -16,4 +16,4 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 #include "sendchar.h"
 
-int8_t sendchar(uint8_t c) { return 0; }
+__attribute__((weak)) int8_t sendchar(uint8_t c) { return 0; }

+ 3 - 1
tmk_core/protocol/ibm4704.c

@@ -161,7 +161,9 @@ ISR(IBM4704_INT_VECT) {
         case STOP:
             // Data:Low
             WAIT(data_lo, 100, state);
-            rbuf_enqueue(data);
+            if (!rbuf_enqueue(data)) {
+                print("rbuf: full\n");
+            }
             ibm4704_error = IBM4704_ERR_NONE;
             goto DONE;
             break;

+ 0 - 2
tmk_core/protocol/lufa/lufa.c

@@ -801,8 +801,6 @@ ERROR_EXIT:
     Endpoint_SelectEndpoint(ep);
     return -1;
 }
-#else
-int8_t sendchar(uint8_t c) { return 0; }
 #endif
 
 /*******************************************************************************

+ 3 - 4
tmk_core/protocol/vusb.mk

@@ -9,13 +9,12 @@ SRC +=	$(VUSB_DIR)/main.c \
 	$(VUSB_DIR)/usbdrv/oddebug.c
 
 
-ifdef NO_UART
-SRC +=	$(COMMON_DIR)/sendchar_null.c
-else
+ifneq ($(strip $(CONSOLE_ENABLE)), yes)
+ifndef NO_UART
 SRC +=	$(COMMON_DIR)/sendchar_uart.c \
 	$(COMMON_DIR)/uart.c
 endif
-
+endif
 
 # Search Path
 VPATH += $(TMK_PATH)/$(VUSB_DIR)

+ 42 - 5
tmk_core/protocol/vusb/main.c

@@ -21,12 +21,23 @@
 #include "uart.h"
 #include "debug.h"
 #include "suspend.h"
+#include "wait.h"
+#include "sendchar.h"
+
 #ifdef SLEEP_LED_ENABLE
 #    include "sleep_led.h"
 #endif
 
 #define UART_BAUD_RATE 115200
 
+#ifdef CONSOLE_ENABLE
+void console_task(void);
+#endif
+
+#ifdef RAW_ENABLE
+void raw_hid_task(void);
+#endif
+
 /* This is from main.c of USBaspLoader */
 static void initForUsbConnectivity(void) {
     uint8_t i = 0;
@@ -39,10 +50,9 @@ static void initForUsbConnectivity(void) {
         _delay_ms(1);
     }
     usbDeviceConnect();
-    sei();
 }
 
-void usb_remote_wakeup(void) {
+static void usb_remote_wakeup(void) {
     cli();
 
     int8_t ddr_orig = USBDDR;
@@ -59,6 +69,23 @@ void usb_remote_wakeup(void) {
     sei();
 }
 
+/** \brief Setup USB
+ *
+ * FIXME: Needs doc
+ */
+static void setup_usb(void) {
+    // debug("initForUsbConnectivity()\n");
+    initForUsbConnectivity();
+
+    // for Console_Task
+    print_set_sendchar(sendchar);
+}
+
+/** \brief Main
+ *
+ * FIXME: Needs doc
+ */
+int main(void) __attribute__((weak));
 int main(void) {
     bool suspended = false;
 #if USB_COUNT_SOF
@@ -76,8 +103,10 @@ int main(void) {
     keyboard_setup();
 
     host_set_driver(vusb_driver());
-    debug("initForUsbConnectivity()\n");
-    initForUsbConnectivity();
+    setup_usb();
+    sei();
+
+    wait_ms(50);
 
     keyboard_init();
 #ifdef SLEEP_LED_ENABLE
@@ -120,18 +149,26 @@ int main(void) {
         if (!suspended) {
             usbPoll();
 
-            // TODO: configuration process is incosistent. it sometime fails.
+            // TODO: configuration process is inconsistent. it sometime fails.
             // To prevent failing to configure NOT scan keyboard during configuration
             if (usbConfiguration && usbInterruptIsReady()) {
                 keyboard_task();
             }
             vusb_transfer_keyboard();
+
 #ifdef RAW_ENABLE
             usbPoll();
 
             if (usbConfiguration && usbInterruptIsReady3()) {
                 raw_hid_task();
             }
+#endif
+#ifdef CONSOLE_ENABLE
+            usbPoll();
+
+            if (usbConfiguration && usbInterruptIsReady3()) {
+                console_task();
+            }
 #endif
         } else if (suspend_wakeup_condition()) {
             usb_remote_wakeup();

+ 187 - 26
tmk_core/protocol/vusb/vusb.c

@@ -15,25 +15,50 @@ 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 <util/delay.h>
 #include <stdint.h>
 #include "usbdrv.h"
 #include "usbconfig.h"
 #include "host.h"
 #include "report.h"
-#include "print.h"
-#include "debug.h"
 #include "host_driver.h"
 #include "vusb.h"
-#include <util/delay.h>
+#include "print.h"
+#include "debug.h"
 
 #ifdef RAW_ENABLE
 #    include "raw_hid.h"
 #endif
 
-#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)) && defined(RAW_ENABLE)
-#    error "Enabling Mousekeys/Extrakeys and Raw HID at the same time is not currently supported on V-USB."
+#if defined(CONSOLE_ENABLE)
+#    define RBUF_SIZE 128
+#    include "ring_buffer.h"
+#endif
+
+#define NEXT_INTERFACE __COUNTER__
+
+/*
+ * Interface indexes
+ */
+enum usb_interfaces {
+    KEYBOARD_INTERFACE = NEXT_INTERFACE,
+#if (defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE))
+    MOUSE_EXTRA_INTERFACE = NEXT_INTERFACE,
+#endif
+#ifdef RAW_ENABLE
+    RAW_INTERFACE = NEXT_INTERFACE,
+#endif
+#ifdef CONSOLE_ENABLE
+    CONSOLE_INTERFACE = NEXT_INTERFACE,
+#endif
+    TOTAL_INTERFACES = NEXT_INTERFACE,
+};
+
+#define MAX_INTERFACES 2
+
+#if (NEXT_INTERFACE - 1) > MAX_INTERFACES
+#    error There are not enough available interfaces to support all functions. Please disable one or more of the following: Mouse Keys, Extra Keys, Raw HID, Console
 #endif
 
 static uint8_t vusb_keyboard_leds = 0;
@@ -120,7 +145,60 @@ void raw_hid_task(void) {
         raw_output_received_bytes = 0;
     }
 }
+#endif
+
+/*------------------------------------------------------------------*
+ * Console
+ *------------------------------------------------------------------*/
+#ifdef CONSOLE_ENABLE
+#    define CONSOLE_BUFFER_SIZE 32
+#    define CONSOLE_EPSIZE 8
+
+int8_t sendchar(uint8_t c) {
+    rbuf_enqueue(c);
+    return 0;
+}
+
+static inline bool usbSendData3(char *data, uint8_t len) {
+    uint8_t retries = 5;
+    while (!usbInterruptIsReady3()) {
+        if (!(retries--)) {
+            return false;
+        }
+        usbPoll();
+    }
+
+    usbSetInterrupt3((unsigned char *)data, len);
+    return true;
+}
+
+void console_task(void) {
+    if (!usbConfiguration) {
+        return;
+    }
+
+    if (!rbuf_has_data()) {
+        return;
+    }
+
+    // Send in chunks of 8 padded to 32
+    char    send_buf[CONSOLE_BUFFER_SIZE] = {0};
+    uint8_t send_buf_count                = 0;
+    while (rbuf_has_data() && send_buf_count < CONSOLE_EPSIZE) {
+        send_buf[send_buf_count++] = rbuf_dequeue();
+    }
 
+    char *temp = send_buf;
+    for (uint8_t i = 0; i < 4; i++) {
+        if (!usbSendData3(temp, 8)) {
+            break;
+        }
+        temp += 8;
+    }
+
+    usbSendData3(0, 0);
+    usbPoll();
+}
 #endif
 
 /*------------------------------------------------------------------*
@@ -429,7 +507,30 @@ const PROGMEM uchar raw_hid_report[] = {
     0x95, RAW_BUFFER_SIZE,  //   Report Count
     0x75, 0x08,             //   Report Size (8)
     0x91, 0x02,             //   Output (Data, Variable, Absolute)
-    0xC0,                   // End Collection
+    0xC0                    // End Collection
+};
+#endif
+
+#if defined(CONSOLE_ENABLE)
+const PROGMEM uchar console_hid_report[] = {
+    0x06, 0x31, 0xFF,  // Usage Page (Vendor Defined - PJRC Teensy compatible)
+    0x09, 0x74,        // Usage (Vendor Defined - PJRC Teensy compatible)
+    0xA1, 0x01,        // Collection (Application)
+    // Data to host
+    0x09, 0x75,                 //   Usage (Vendor Defined)
+    0x15, 0x00,                 //   Logical Minimum (0x00)
+    0x26, 0xFF, 0x00,           //   Logical Maximum (0x00FF)
+    0x95, CONSOLE_BUFFER_SIZE,  //   Report Count
+    0x75, 0x08,                 //   Report Size (8)
+    0x81, 0x02,                 //   Input (Data, Variable, Absolute)
+    // Data from host
+    0x09, 0x76,                 //   Usage (Vendor Defined)
+    0x15, 0x00,                 //   Logical Minimum (0x00)
+    0x26, 0xFF, 0x00,           //   Logical Maximum (0x00FF)
+    0x95, CONSOLE_BUFFER_SIZE,  //   Report Count
+    0x75, 0x08,                 //   Report Size (8)
+    0x91, 0x02,                 //   Output (Data)
+    0xC0                        // End Collection
 };
 #endif
 
@@ -511,11 +612,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
             .bDescriptorType = USBDESCR_CONFIG
         },
         .wTotalLength        = sizeof(usbConfigurationDescriptor_t),
-#    if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE) || defined(RAW_ENABLE)
-        .bNumInterfaces      = 2,
-#    else
-        .bNumInterfaces      = 1,
-#    endif
+        .bNumInterfaces      = TOTAL_INTERFACES,
         .bConfigurationValue = 0x01,
         .iConfiguration      = 0x00,
         .bmAttributes        = (1 << 7) | USBATTR_REMOTEWAKE,
@@ -530,7 +627,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
             .bLength         = sizeof(usbInterfaceDescriptor_t),
             .bDescriptorType = USBDESCR_INTERFACE
         },
-        .bInterfaceNumber    = 0,
+        .bInterfaceNumber    = KEYBOARD_INTERFACE,
         .bAlternateSetting   = 0x00,
         .bNumEndpoints       = 1,
         .bInterfaceClass     = 0x03,
@@ -569,7 +666,7 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
             .bLength         = sizeof(usbInterfaceDescriptor_t),
             .bDescriptorType = USBDESCR_INTERFACE
         },
-        .bInterfaceNumber    = 1,
+        .bInterfaceNumber    = MOUSE_EXTRA_INTERFACE,
         .bAlternateSetting   = 0x00,
         .bNumEndpoints       = 1,
         .bInterfaceClass     = 0x03,
@@ -597,14 +694,15 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
         .bmAttributes        = 0x03,
         .wMaxPacketSize      = 8,
         .bInterval           = USB_POLLING_INTERVAL_MS
-    }
-#    elif defined(RAW_ENABLE)
+    },
+#    endif
+#    if defined(RAW_ENABLE)
     .rawInterface = {
         .header = {
             .bLength         = sizeof(usbInterfaceDescriptor_t),
             .bDescriptorType = USBDESCR_INTERFACE
         },
-        .bInterfaceNumber    = 1,
+        .bInterfaceNumber    = RAW_INTERFACE,
         .bAlternateSetting   = 0x00,
         .bNumEndpoints       = 2,
         .bInterfaceClass     = 0x03,
@@ -642,7 +740,56 @@ const PROGMEM usbConfigurationDescriptor_t usbConfigurationDescriptor = {
         .bmAttributes        = 0x03,
         .wMaxPacketSize      = RAW_EPSIZE,
         .bInterval           = USB_POLLING_INTERVAL_MS
-    }
+    },
+#    endif
+#    if defined(CONSOLE_ENABLE)
+    /*
+     * Console
+     */
+    .consoleInterface = {
+        .header = {
+            .bLength         = sizeof(usbInterfaceDescriptor_t),
+            .bDescriptorType = USBDESCR_INTERFACE
+        },
+        .bInterfaceNumber    = CONSOLE_INTERFACE,
+        .bAlternateSetting   = 0x00,
+        .bNumEndpoints       = 2,
+        .bInterfaceClass     = 0x03,
+        .bInterfaceSubClass  = 0x00,
+        .bInterfaceProtocol  = 0x00,
+        .iInterface          = 0x00
+    },
+    .consoleHID = {
+        .header = {
+            .bLength         = sizeof(usbHIDDescriptor_t),
+            .bDescriptorType = USBDESCR_HID
+        },
+        .bcdHID              = 0x0111,
+        .bCountryCode        = 0x00,
+        .bNumDescriptors     = 1,
+        .bDescriptorType     = USBDESCR_HID_REPORT,
+        .wDescriptorLength   = sizeof(console_hid_report)
+    },
+    .consoleINEndpoint = {
+        .header = {
+            .bLength         = sizeof(usbEndpointDescriptor_t),
+            .bDescriptorType = USBDESCR_ENDPOINT
+        },
+        .bEndpointAddress    = (USBRQ_DIR_DEVICE_TO_HOST | USB_CFG_EP3_NUMBER),
+        .bmAttributes        = 0x03,
+        .wMaxPacketSize      = CONSOLE_EPSIZE,
+        .bInterval           = 0x01
+    },
+    .consoleOUTEndpoint = {
+        .header = {
+            .bLength         = sizeof(usbEndpointDescriptor_t),
+            .bDescriptorType = USBDESCR_ENDPOINT
+        },
+        .bEndpointAddress    = (USBRQ_DIR_HOST_TO_DEVICE | USB_CFG_EP3_NUMBER),
+        .bmAttributes        = 0x03,
+        .wMaxPacketSize      = CONSOLE_EPSIZE,
+        .bInterval           = 0x01
+    },
 #    endif
 };
 
@@ -690,40 +837,54 @@ USB_PUBLIC usbMsgLen_t usbFunctionDescriptor(struct usbRequest *rq) {
             break;
         case USBDESCR_HID:
             switch (rq->wValue.bytes[0]) {
-                case 0:
+                case KEYBOARD_INTERFACE:
                     usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.keyboardHID;
                     len       = sizeof(usbHIDDescriptor_t);
                     break;
 #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
-                case 1:
+                case MOUSE_EXTRA_INTERFACE:
                     usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.mouseExtraHID;
                     len       = sizeof(usbHIDDescriptor_t);
                     break;
-#elif defined(RAW_ENABLE)
-                case 1:
+#endif
+#if defined(RAW_ENABLE)
+                case RAW_INTERFACE:
                     usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.rawHID;
                     len       = sizeof(usbHIDDescriptor_t);
                     break;
+#endif
+#if defined(CONSOLE_ENABLE)
+                case CONSOLE_INTERFACE:
+                    usbMsgPtr = (unsigned char *)&usbConfigurationDescriptor.consoleHID;
+                    len       = sizeof(usbHIDDescriptor_t);
+                    break;
 #endif
             }
             break;
         case USBDESCR_HID_REPORT:
             /* interface index */
             switch (rq->wIndex.word) {
-                case 0:
+                case KEYBOARD_INTERFACE:
                     usbMsgPtr = (unsigned char *)keyboard_hid_report;
                     len       = sizeof(keyboard_hid_report);
                     break;
 #if defined(MOUSE_ENABLE) || defined(EXTRAKEY_ENABLE)
-                case 1:
+                case MOUSE_EXTRA_INTERFACE:
                     usbMsgPtr = (unsigned char *)mouse_extra_hid_report;
                     len       = sizeof(mouse_extra_hid_report);
                     break;
-#elif defined(RAW_ENABLE)
-                case 1:
+#endif
+#if defined(RAW_ENABLE)
+                case RAW_INTERFACE:
                     usbMsgPtr = (unsigned char *)raw_hid_report;
                     len       = sizeof(raw_hid_report);
                     break;
+#endif
+#if defined(CONSOLE_ENABLE)
+                case CONSOLE_INTERFACE:
+                    usbMsgPtr = (unsigned char *)console_hid_report;
+                    len       = sizeof(console_hid_report);
+                    break;
 #endif
             }
             break;

+ 10 - 5
tmk_core/protocol/vusb/vusb.h

@@ -93,19 +93,24 @@ typedef struct usbConfigurationDescriptor {
     usbInterfaceDescriptor_t mouseExtraInterface;
     usbHIDDescriptor_t       mouseExtraHID;
     usbEndpointDescriptor_t  mouseExtraINEndpoint;
-#elif defined(RAW_ENABLE)
+#endif
+
+#if defined(RAW_ENABLE)
     usbInterfaceDescriptor_t rawInterface;
     usbHIDDescriptor_t       rawHID;
     usbEndpointDescriptor_t  rawINEndpoint;
     usbEndpointDescriptor_t  rawOUTEndpoint;
 #endif
+
+#if defined(CONSOLE_ENABLE)
+    usbInterfaceDescriptor_t consoleInterface;
+    usbHIDDescriptor_t       consoleHID;
+    usbEndpointDescriptor_t  consoleINEndpoint;
+    usbEndpointDescriptor_t  consoleOUTEndpoint;
+#endif
 } __attribute__((packed)) usbConfigurationDescriptor_t;
 
 #define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1))
 
 host_driver_t *vusb_driver(void);
 void           vusb_transfer_keyboard(void);
-
-#ifdef RAW_ENABLE
-void raw_hid_task(void);
-#endif

+ 9 - 4
tmk_core/ring_buffer.h

@@ -3,21 +3,26 @@
 /*--------------------------------------------------------------------
  * Ring buffer to store scan codes from keyboard
  *------------------------------------------------------------------*/
-#define RBUF_SIZE 32
+#ifndef RBUF_SIZE
+#    define RBUF_SIZE 32
+#endif
 #include <util/atomic.h>
+#include <stdint.h>
+#include <stdbool.h>
 static uint8_t     rbuf[RBUF_SIZE];
 static uint8_t     rbuf_head = 0;
 static uint8_t     rbuf_tail = 0;
-static inline void rbuf_enqueue(uint8_t data) {
+static inline bool rbuf_enqueue(uint8_t data) {
+    bool ret = false;
     ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
         uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
         if (next != rbuf_tail) {
             rbuf[rbuf_head] = data;
             rbuf_head       = next;
-        } else {
-            print("rbuf: full\n");
+            ret             = true;
         }
     }
+    return ret;
 }
 static inline uint8_t rbuf_dequeue(void) {
     uint8_t val = 0;