diff options
Diffstat (limited to 'tmk_core/protocol')
| -rw-r--r-- | tmk_core/protocol/ibm4704.c | 185 | ||||
| -rw-r--r-- | tmk_core/protocol/ibm4704.h | 103 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa.mk | 27 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/adafruit_ble.cpp | 701 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/adafruit_ble.h | 59 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/lufa.c | 35 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/outputselect.c | 79 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/outputselect.h | 34 | ||||
| -rw-r--r-- | tmk_core/protocol/lufa/ringbuffer.hpp | 66 | ||||
| -rw-r--r-- | tmk_core/protocol/news.c | 161 | ||||
| -rw-r--r-- | tmk_core/protocol/news.h | 48 | ||||
| -rw-r--r-- | tmk_core/protocol/next_kbd.c | 219 | ||||
| -rw-r--r-- | tmk_core/protocol/next_kbd.h | 60 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_descriptor.c | 19 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_hid/parser.h | 5 | ||||
| -rw-r--r-- | tmk_core/protocol/usb_hid/usb_hid.h | 6 | ||||
| -rw-r--r-- | tmk_core/protocol/vusb/vusb.c | 36 | 
17 files changed, 81 insertions, 1762 deletions
| diff --git a/tmk_core/protocol/ibm4704.c b/tmk_core/protocol/ibm4704.c deleted file mode 100644 index a19443976e..0000000000 --- a/tmk_core/protocol/ibm4704.c +++ /dev/null @@ -1,185 +0,0 @@ -/* -Copyright 2010,2011,2012,2013 Jun WAKO <wakojun@gmail.com> -*/ -#include <stdbool.h> -#include <util/delay.h> -#include "debug.h" -#include "ring_buffer.h" -#include "ibm4704.h" - -#define WAIT(stat, us, err)      \ -    do {                         \ -        if (!wait_##stat(us)) {  \ -            ibm4704_error = err; \ -            goto ERROR;          \ -        }                        \ -    } while (0) - -uint8_t ibm4704_error = 0; - -void ibm4704_init(void) { -    inhibit();  // keep keyboard from sending -    IBM4704_INT_INIT(); -    IBM4704_INT_ON(); -    idle();  // allow keyboard sending -} - -/* -Host to Keyboard ----------------- -Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. - -        ____        __   __   __   __   __   __   __   __   __   ________ -Clock       \______/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/ -            ^   ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ___ -Data    ____|__/    X____X____X____X____X____X____X____X____X____X   \___ -            |  Start   0    1    2    3    4    5    6    7    P   Stop -            Request by host - -Start bit:  can be long as 300-350us. -Request:    Host pulls Clock line down to request to send a command. -Timing:     After Request keyboard pull up Data and down Clock line to low for start bit. -            After request host release Clock line once Data line becomes hi. -            Host writes a bit while Clock is hi and Keyboard reads while low. -Stop bit:   Host releases or pulls up Data line to hi after 9th clock and waits for keyboard pull down the line to lo. -*/ -uint8_t ibm4704_send(uint8_t data) { -    bool parity   = true;  // odd parity -    ibm4704_error = 0; - -    IBM4704_INT_OFF(); - -    /* Request to send */ -    idle(); -    clock_lo(); - -    /* wait for Start bit(Clock:lo/Data:hi) */ -    WAIT(data_hi, 300, 0x30); - -    /* Data bit */ -    for (uint8_t i = 0; i < 8; i++) { -        WAIT(clock_hi, 100, 0x40 + i); -        if (data & (1 << i)) { -            parity = !parity; -            data_hi(); -        } else { -            data_lo(); -        } -        WAIT(clock_lo, 100, 0x48 + i); -    } - -    /* Parity bit */ -    WAIT(clock_hi, 100, 0x34); -    if (parity) { -        data_hi(); -    } else { -        data_lo(); -    } -    WAIT(clock_lo, 100, 0x35); - -    /* Stop bit */ -    WAIT(clock_hi, 100, 0x34); -    data_hi(); - -    /* End */ -    WAIT(data_lo, 100, 0x36); - -    idle(); -    IBM4704_INT_ON(); -    return 0; -ERROR: -    idle(); -    if (ibm4704_error > 0x30) { -        xprintf("S:%02X ", ibm4704_error); -    } -    IBM4704_INT_ON(); -    return -1; -} - -/* wait forever to receive data */ -uint8_t ibm4704_recv_response(void) { -    while (!rbuf_has_data()) { -        _delay_ms(1); -    } -    return rbuf_dequeue(); -} - -uint8_t ibm4704_recv(void) { -    if (rbuf_has_data()) { -        return rbuf_dequeue(); -    } else { -        return -1; -    } -} - -/* -Keyboard to Host ----------------- -Data bits are LSB first and Parity is odd. Clock has around 60us high and 30us low part. - -        ____       __   __   __   __   __   __   __   __   __   _______ -Clock       \_____/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/  \_/ -             ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ -Data    ____/    X____X____X____X____X____X____X____X____X____X________ -            Start   0    1    2    3    4    5    6    7    P  Stop - -Start bit:  can be long as 300-350us. -Inhibit:    Pull Data line down to inhibit keyboard to send. -Timing:     Host reads bit while Clock is hi.(rising edge) -Stop bit:   Keyboard pulls down Data line to lo after 9th clock. -*/ -ISR(IBM4704_INT_VECT) { -    static enum { BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7, PARITY, STOP } state = BIT0; -    // LSB first -    static uint8_t data = 0; -    // Odd parity -    static uint8_t parity = false; - -    ibm4704_error = 0; - -    switch (state) { -        case BIT0: -        case BIT1: -        case BIT2: -        case BIT3: -        case BIT4: -        case BIT5: -        case BIT6: -        case BIT7: -            data >>= 1; -            if (data_in()) { -                data |= 0x80; -                parity = !parity; -            } -            break; -        case PARITY: -            if (data_in()) { -                parity = !parity; -            } -            if (!parity) goto ERROR; -            break; -        case STOP: -            // Data:Low -            WAIT(data_lo, 100, state); -            if (!rbuf_enqueue(data)) { -                print("rbuf: full\n"); -            } -            ibm4704_error = IBM4704_ERR_NONE; -            goto DONE; -            break; -        default: -            goto ERROR; -    } -    state++; -    goto RETURN; -ERROR: -    ibm4704_error = state; -    while (ibm4704_send(0xFE)) _delay_ms(1);  // resend -    xprintf("R:%02X%02X\n", state, data); -DONE: -    state  = BIT0; -    data   = 0; -    parity = false; -RETURN: -    return; -} diff --git a/tmk_core/protocol/ibm4704.h b/tmk_core/protocol/ibm4704.h deleted file mode 100644 index 4f88d148b3..0000000000 --- a/tmk_core/protocol/ibm4704.h +++ /dev/null @@ -1,103 +0,0 @@ -/* -Copyright 2014 Jun WAKO <wakojun@gmail.com> -*/ - -#pragma once - -#define IBM4704_ERR_NONE 0 -#define IBM4704_ERR_PARITY 0x70 - -void    ibm4704_init(void); -uint8_t ibm4704_send(uint8_t data); -uint8_t ibm4704_recv_response(void); -uint8_t ibm4704_recv(void); - -/* Check pin configuration */ -#if !(defined(IBM4704_CLOCK_PORT) && defined(IBM4704_CLOCK_PIN) && defined(IBM4704_CLOCK_DDR) && defined(IBM4704_CLOCK_BIT)) -#    error "ibm4704 clock pin configuration is required in config.h" -#endif - -#if !(defined(IBM4704_DATA_PORT) && defined(IBM4704_DATA_PIN) && defined(IBM4704_DATA_DDR) && defined(IBM4704_DATA_BIT)) -#    error "ibm4704 data pin configuration is required in config.h" -#endif - -/*-------------------------------------------------------------------- - * static functions - *------------------------------------------------------------------*/ -static inline void clock_lo(void) { -    IBM4704_CLOCK_PORT &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_DDR |= (1 << IBM4704_CLOCK_BIT); -} -static inline void clock_hi(void) { -    /* input with pull up */ -    IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT); -} -static inline bool clock_in(void) { -    IBM4704_CLOCK_DDR &= ~(1 << IBM4704_CLOCK_BIT); -    IBM4704_CLOCK_PORT |= (1 << IBM4704_CLOCK_BIT); -    _delay_us(1); -    return IBM4704_CLOCK_PIN & (1 << IBM4704_CLOCK_BIT); -} -static inline void data_lo(void) { -    IBM4704_DATA_PORT &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_DDR |= (1 << IBM4704_DATA_BIT); -} -static inline void data_hi(void) { -    /* input with pull up */ -    IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT); -} -static inline bool data_in(void) { -    IBM4704_DATA_DDR &= ~(1 << IBM4704_DATA_BIT); -    IBM4704_DATA_PORT |= (1 << IBM4704_DATA_BIT); -    _delay_us(1); -    return IBM4704_DATA_PIN & (1 << IBM4704_DATA_BIT); -} - -static inline uint16_t wait_clock_lo(uint16_t us) { -    while (clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_clock_hi(uint16_t us) { -    while (!clock_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_lo(uint16_t us) { -    while (data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} -static inline uint16_t wait_data_hi(uint16_t us) { -    while (!data_in() && us) { -        asm(""); -        _delay_us(1); -        us--; -    } -    return us; -} - -/* idle state that device can send */ -static inline void idle(void) { -    clock_hi(); -    data_hi(); -} - -/* inhibit device to send - * keyboard checks Data line on start bit(Data:hi) and it stops sending if Data line is low. - */ -static inline void inhibit(void) { -    clock_hi(); -    data_lo(); -} diff --git a/tmk_core/protocol/lufa.mk b/tmk_core/protocol/lufa.mk index c8935dacb7..00fec478ac 100644 --- a/tmk_core/protocol/lufa.mk +++ b/tmk_core/protocol/lufa.mk @@ -3,7 +3,6 @@ LUFA_DIR = protocol/lufa  # Path to the LUFA library  LUFA_PATH = $(LIB_PATH)/lufa -  # Create the LUFA source path variables by including the LUFA makefile  ifneq (, $(wildcard $(LUFA_PATH)/LUFA/Build/lufa_sources.mk))      # New build system from 20120730 @@ -22,23 +21,6 @@ ifeq ($(strip $(MIDI_ENABLE)), yes)  	include $(TMK_PATH)/protocol/midi.mk  endif -ifeq ($(strip $(BLUETOOTH_ENABLE)), yes) -	LUFA_SRC += outputselect.c \ -		$(TMK_DIR)/protocol/serial_uart.c -endif - -ifeq ($(strip $(BLUETOOTH)), AdafruitBLE) -	LUFA_SRC += spi_master.c \ -		analog.c \ -		outputselect.c \ -		$(LUFA_DIR)/adafruit_ble.cpp -endif - -ifeq ($(strip $(BLUETOOTH)), RN42) -	LUFA_SRC += outputselect.c \ -		$(TMK_DIR)/protocol/serial_uart.c -endif -  ifeq ($(strip $(VIRTSER_ENABLE)), yes)  	LUFA_SRC += $(LUFA_ROOT_PATH)/Drivers/USB/Class/Device/CDCClassDevice.c  endif @@ -50,19 +32,10 @@ SRC += $(LUFA_DIR)/usb_util.c  VPATH += $(TMK_PATH)/$(LUFA_DIR)  VPATH += $(LUFA_PATH) -# Option modules -#ifdef $(or MOUSEKEY_ENABLE, PS2_MOUSE_ENABLE) -#endif - -#ifdef EXTRAKEY_ENABLE -#endif -  # LUFA library compile-time options and predefined tokens  LUFA_OPTS  = -DUSB_DEVICE_ONLY  LUFA_OPTS += -DUSE_FLASH_DESCRIPTORS  LUFA_OPTS += -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)" -#LUFA_OPTS += -DINTERRUPT_CONTROL_ENDPOINT -LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8  LUFA_OPTS += -DFIXED_CONTROL_ENDPOINT_SIZE=8  LUFA_OPTS += -DFIXED_NUM_CONFIGURATIONS=1 diff --git a/tmk_core/protocol/lufa/adafruit_ble.cpp b/tmk_core/protocol/lufa/adafruit_ble.cpp deleted file mode 100644 index 3f2cc35734..0000000000 --- a/tmk_core/protocol/lufa/adafruit_ble.cpp +++ /dev/null @@ -1,701 +0,0 @@ -#include "adafruit_ble.h" - -#include <stdio.h> -#include <stdlib.h> -#include <alloca.h> -#include "debug.h" -#include "timer.h" -#include "action_util.h" -#include "ringbuffer.hpp" -#include <string.h> -#include "spi_master.h" -#include "wait.h" -#include "analog.h" -#include "progmem.h" - -// These are the pin assignments for the 32u4 boards. -// You may define them to something else in your config.h -// if yours is wired up differently. -#ifndef AdafruitBleResetPin -#    define AdafruitBleResetPin D4 -#endif - -#ifndef AdafruitBleCSPin -#    define AdafruitBleCSPin B4 -#endif - -#ifndef AdafruitBleIRQPin -#    define AdafruitBleIRQPin E6 -#endif - -#ifndef AdafruitBleSpiClockSpeed -#    define AdafruitBleSpiClockSpeed 4000000UL  // SCK frequency -#endif - -#define SCK_DIVISOR (F_CPU / AdafruitBleSpiClockSpeed) - -#define SAMPLE_BATTERY -#define ConnectionUpdateInterval 1000 /* milliseconds */ - -#ifndef BATTERY_LEVEL_PIN -#    define BATTERY_LEVEL_PIN B5 -#endif - -static struct { -    bool is_connected; -    bool initialized; -    bool configured; - -#define ProbedEvents 1 -#define UsingEvents 2 -    bool event_flags; - -#ifdef SAMPLE_BATTERY -    uint16_t last_battery_update; -    uint32_t vbat; -#endif -    uint16_t last_connection_update; -} state; - -// Commands are encoded using SDEP and sent via SPI -// https://github.com/adafruit/Adafruit_BluefruitLE_nRF51/blob/master/SDEP.md - -#define SdepMaxPayload 16 -struct sdep_msg { -    uint8_t type; -    uint8_t cmd_low; -    uint8_t cmd_high; -    struct __attribute__((packed)) { -        uint8_t len : 7; -        uint8_t more : 1; -    }; -    uint8_t payload[SdepMaxPayload]; -} __attribute__((packed)); - -// The recv latency is relatively high, so when we're hammering keys quickly, -// we want to avoid waiting for the responses in the matrix loop.  We maintain -// a short queue for that.  Since there is quite a lot of space overhead for -// the AT command representation wrapped up in SDEP, we queue the minimal -// information here. - -enum queue_type { -    QTKeyReport,  // 1-byte modifier + 6-byte key report -    QTConsumer,   // 16-bit key code -#ifdef MOUSE_ENABLE -    QTMouseMove,  // 4-byte mouse report -#endif -}; - -struct queue_item { -    enum queue_type queue_type; -    uint16_t        added; -    union __attribute__((packed)) { -        struct __attribute__((packed)) { -            uint8_t modifier; -            uint8_t keys[6]; -        } key; - -        uint16_t consumer; -        struct __attribute__((packed)) { -            int8_t  x, y, scroll, pan; -            uint8_t buttons; -        } mousemove; -    }; -}; - -// Items that we wish to send -static RingBuffer<queue_item, 40> send_buf; -// Pending response; while pending, we can't send any more requests. -// This records the time at which we sent the command for which we -// are expecting a response. -static RingBuffer<uint16_t, 2> resp_buf; - -static bool process_queue_item(struct queue_item *item, uint16_t timeout); - -enum sdep_type { -    SdepCommand       = 0x10, -    SdepResponse      = 0x20, -    SdepAlert         = 0x40, -    SdepError         = 0x80, -    SdepSlaveNotReady = 0xFE,  // Try again later -    SdepSlaveOverflow = 0xFF,  // You read more data than is available -}; - -enum ble_cmd { -    BleInitialize = 0xBEEF, -    BleAtWrapper  = 0x0A00, -    BleUartTx     = 0x0A01, -    BleUartRx     = 0x0A02, -}; - -enum ble_system_event_bits { -    BleSystemConnected    = 0, -    BleSystemDisconnected = 1, -    BleSystemUartRx       = 8, -    BleSystemMidiRx       = 10, -}; - -#define SdepTimeout 150             /* milliseconds */ -#define SdepShortTimeout 10         /* milliseconds */ -#define SdepBackOff 25              /* microseconds */ -#define BatteryUpdateInterval 10000 /* milliseconds */ - -static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout = SdepTimeout); -static bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose = false); - -// Send a single SDEP packet -static bool sdep_send_pkt(const struct sdep_msg *msg, uint16_t timeout) { -    spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -    uint16_t timerStart = timer_read(); -    bool     success    = false; -    bool     ready      = false; - -    do { -        ready = spi_write(msg->type) != SdepSlaveNotReady; -        if (ready) { -            break; -        } - -        // Release it and let it initialize -        spi_stop(); -        wait_us(SdepBackOff); -        spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -    } while (timer_elapsed(timerStart) < timeout); - -    if (ready) { -        // Slave is ready; send the rest of the packet -        spi_transmit(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload)) + msg->len); -        success = true; -    } - -    spi_stop(); - -    return success; -} - -static inline void sdep_build_pkt(struct sdep_msg *msg, uint16_t command, const uint8_t *payload, uint8_t len, bool moredata) { -    msg->type     = SdepCommand; -    msg->cmd_low  = command & 0xFF; -    msg->cmd_high = command >> 8; -    msg->len      = len; -    msg->more     = (moredata && len == SdepMaxPayload) ? 1 : 0; - -    static_assert(sizeof(*msg) == 20, "msg is correctly packed"); - -    memcpy(msg->payload, payload, len); -} - -// Read a single SDEP packet -static bool sdep_recv_pkt(struct sdep_msg *msg, uint16_t timeout) { -    bool     success    = false; -    uint16_t timerStart = timer_read(); -    bool     ready      = false; - -    do { -        ready = readPin(AdafruitBleIRQPin); -        if (ready) { -            break; -        } -        wait_us(1); -    } while (timer_elapsed(timerStart) < timeout); - -    if (ready) { -        spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); - -        do { -            // Read the command type, waiting for the data to be ready -            msg->type = spi_read(); -            if (msg->type == SdepSlaveNotReady || msg->type == SdepSlaveOverflow) { -                // Release it and let it initialize -                spi_stop(); -                wait_us(SdepBackOff); -                spi_start(AdafruitBleCSPin, false, 0, SCK_DIVISOR); -                continue; -            } - -            // Read the rest of the header -            spi_receive(&msg->cmd_low, sizeof(*msg) - (1 + sizeof(msg->payload))); - -            // and get the payload if there is any -            if (msg->len <= SdepMaxPayload) { -                spi_receive(msg->payload, msg->len); -            } -            success = true; -            break; -        } while (timer_elapsed(timerStart) < timeout); - -        spi_stop(); -    } -    return success; -} - -static void resp_buf_read_one(bool greedy) { -    uint16_t last_send; -    if (!resp_buf.peek(last_send)) { -        return; -    } - -    if (readPin(AdafruitBleIRQPin)) { -        struct sdep_msg msg; - -    again: -        if (sdep_recv_pkt(&msg, SdepTimeout)) { -            if (!msg.more) { -                // We got it; consume this entry -                resp_buf.get(last_send); -                dprintf("recv latency %dms\n", TIMER_DIFF_16(timer_read(), last_send)); -            } - -            if (greedy && resp_buf.peek(last_send) && readPin(AdafruitBleIRQPin)) { -                goto again; -            } -        } - -    } else if (timer_elapsed(last_send) > SdepTimeout * 2) { -        dprintf("waiting_for_result: timeout, resp_buf size %d\n", (int)resp_buf.size()); - -        // Timed out: consume this entry -        resp_buf.get(last_send); -    } -} - -static void send_buf_send_one(uint16_t timeout = SdepTimeout) { -    struct queue_item item; - -    // Don't send anything more until we get an ACK -    if (!resp_buf.empty()) { -        return; -    } - -    if (!send_buf.peek(item)) { -        return; -    } -    if (process_queue_item(&item, timeout)) { -        // commit that peek -        send_buf.get(item); -        dprintf("send_buf_send_one: have %d remaining\n", (int)send_buf.size()); -    } else { -        dprint("failed to send, will retry\n"); -        wait_ms(SdepTimeout); -        resp_buf_read_one(true); -    } -} - -static void resp_buf_wait(const char *cmd) { -    bool didPrint = false; -    while (!resp_buf.empty()) { -        if (!didPrint) { -            dprintf("wait on buf for %s\n", cmd); -            didPrint = true; -        } -        resp_buf_read_one(true); -    } -} - -static bool ble_init(void) { -    state.initialized  = false; -    state.configured   = false; -    state.is_connected = false; - -    setPinInput(AdafruitBleIRQPin); - -    spi_init(); - -    // Perform a hardware reset -    setPinOutput(AdafruitBleResetPin); -    writePinHigh(AdafruitBleResetPin); -    writePinLow(AdafruitBleResetPin); -    wait_ms(10); -    writePinHigh(AdafruitBleResetPin); - -    wait_ms(1000);  // Give it a second to initialize - -    state.initialized = true; -    return state.initialized; -} - -static inline uint8_t min(uint8_t a, uint8_t b) { return a < b ? a : b; } - -static bool read_response(char *resp, uint16_t resplen, bool verbose) { -    char *dest = resp; -    char *end  = dest + resplen; - -    while (true) { -        struct sdep_msg msg; - -        if (!sdep_recv_pkt(&msg, 2 * SdepTimeout)) { -            dprint("sdep_recv_pkt failed\n"); -            return false; -        } - -        if (msg.type != SdepResponse) { -            *resp = 0; -            return false; -        } - -        uint8_t len = min(msg.len, end - dest); -        if (len > 0) { -            memcpy(dest, msg.payload, len); -            dest += len; -        } - -        if (!msg.more) { -            // No more data is expected! -            break; -        } -    } - -    // Ensure the response is NUL terminated -    *dest = 0; - -    // "Parse" the result text; we want to snip off the trailing OK or ERROR line -    // Rewind past the possible trailing CRLF so that we can strip it -    --dest; -    while (dest > resp && (dest[0] == '\n' || dest[0] == '\r')) { -        *dest = 0; -        --dest; -    } - -    // Look back for start of preceeding line -    char *last_line = strrchr(resp, '\n'); -    if (last_line) { -        ++last_line; -    } else { -        last_line = resp; -    } - -    bool              success       = false; -    static const char kOK[] PROGMEM = "OK"; - -    success = !strcmp_P(last_line, kOK); - -    if (verbose || !success) { -        dprintf("result: %s\n", resp); -    } -    return success; -} - -static bool at_command(const char *cmd, char *resp, uint16_t resplen, bool verbose, uint16_t timeout) { -    const char *    end = cmd + strlen(cmd); -    struct sdep_msg msg; - -    if (verbose) { -        dprintf("ble send: %s\n", cmd); -    } - -    if (resp) { -        // They want to decode the response, so we need to flush and wait -        // for all pending I/O to finish before we start this one, so -        // that we don't confuse the results -        resp_buf_wait(cmd); -        *resp = 0; -    } - -    // Fragment the command into a series of SDEP packets -    while (end - cmd > SdepMaxPayload) { -        sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, SdepMaxPayload, true); -        if (!sdep_send_pkt(&msg, timeout)) { -            return false; -        } -        cmd += SdepMaxPayload; -    } - -    sdep_build_pkt(&msg, BleAtWrapper, (uint8_t *)cmd, end - cmd, false); -    if (!sdep_send_pkt(&msg, timeout)) { -        return false; -    } - -    if (resp == NULL) { -        uint16_t now = timer_read(); -        while (!resp_buf.enqueue(now)) { -            resp_buf_read_one(false); -        } -        uint16_t later = timer_read(); -        if (TIMER_DIFF_16(later, now) > 0) { -            dprintf("waited %dms for resp_buf\n", TIMER_DIFF_16(later, now)); -        } -        return true; -    } - -    return read_response(resp, resplen, verbose); -} - -bool at_command_P(const char *cmd, char *resp, uint16_t resplen, bool verbose) { -    char *cmdbuf = (char *)alloca(strlen_P(cmd) + 1); -    strcpy_P(cmdbuf, cmd); -    return at_command(cmdbuf, resp, resplen, verbose); -} - -bool adafruit_ble_is_connected(void) { return state.is_connected; } - -bool adafruit_ble_enable_keyboard(void) { -    char resbuf[128]; - -    if (!state.initialized && !ble_init()) { -        return false; -    } - -    state.configured = false; - -    // Disable command echo -    static const char kEcho[] PROGMEM = "ATE=0"; -    // Make the advertised name match the keyboard -    static const char kGapDevName[] PROGMEM = "AT+GAPDEVNAME=" STR(PRODUCT); -    // Turn on keyboard support -    static const char kHidEnOn[] PROGMEM = "AT+BLEHIDEN=1"; - -    // Adjust intervals to improve latency.  This causes the "central" -    // system (computer/tablet) to poll us every 10-30 ms.  We can't -    // set a smaller value than 10ms, and 30ms seems to be the natural -    // processing time on my macbook.  Keeping it constrained to that -    // feels reasonable to type to. -    static const char kGapIntervals[] PROGMEM = "AT+GAPINTERVALS=10,30,,"; - -    // Reset the device so that it picks up the above changes -    static const char kATZ[] PROGMEM = "ATZ"; - -    // Turn down the power level a bit -    static const char  kPower[] PROGMEM             = "AT+BLEPOWERLEVEL=-12"; -    static PGM_P const configure_commands[] PROGMEM = { -        kEcho, kGapIntervals, kGapDevName, kHidEnOn, kPower, kATZ, -    }; - -    uint8_t i; -    for (i = 0; i < sizeof(configure_commands) / sizeof(configure_commands[0]); ++i) { -        PGM_P cmd; -        memcpy_P(&cmd, configure_commands + i, sizeof(cmd)); - -        if (!at_command_P(cmd, resbuf, sizeof(resbuf))) { -            dprintf("failed BLE command: %S: %s\n", cmd, resbuf); -            goto fail; -        } -    } - -    state.configured = true; - -    // Check connection status in a little while; allow the ATZ time -    // to kick in. -    state.last_connection_update = timer_read(); -fail: -    return state.configured; -} - -static void set_connected(bool connected) { -    if (connected != state.is_connected) { -        if (connected) { -            dprint("BLE connected\n"); -        } else { -            dprint("BLE disconnected\n"); -        } -        state.is_connected = connected; - -        // TODO: if modifiers are down on the USB interface and -        // we cut over to BLE or vice versa, they will remain stuck. -        // This feels like a good point to do something like clearing -        // the keyboard and/or generating a fake all keys up message. -        // However, I've noticed that it takes a couple of seconds -        // for macOS to to start recognizing key presses after BLE -        // is in the connected state, so I worry that doing that -        // here may not be good enough. -    } -} - -void adafruit_ble_task(void) { -    char resbuf[48]; - -    if (!state.configured && !adafruit_ble_enable_keyboard()) { -        return; -    } -    resp_buf_read_one(true); -    send_buf_send_one(SdepShortTimeout); - -    if (resp_buf.empty() && (state.event_flags & UsingEvents) && readPin(AdafruitBleIRQPin)) { -        // Must be an event update -        if (at_command_P(PSTR("AT+EVENTSTATUS"), resbuf, sizeof(resbuf))) { -            uint32_t mask = strtoul(resbuf, NULL, 16); - -            if (mask & BleSystemConnected) { -                set_connected(true); -            } else if (mask & BleSystemDisconnected) { -                set_connected(false); -            } -        } -    } - -    if (timer_elapsed(state.last_connection_update) > ConnectionUpdateInterval) { -        bool shouldPoll = true; -        if (!(state.event_flags & ProbedEvents)) { -            // Request notifications about connection status changes. -            // This only works in SPIFRIEND firmware > 0.6.7, which is why -            // we check for this conditionally here. -            // Note that at the time of writing, HID reports only work correctly -            // with Apple products on firmware version 0.6.7! -            // https://forums.adafruit.com/viewtopic.php?f=8&t=104052 -            if (at_command_P(PSTR("AT+EVENTENABLE=0x1"), resbuf, sizeof(resbuf))) { -                at_command_P(PSTR("AT+EVENTENABLE=0x2"), resbuf, sizeof(resbuf)); -                state.event_flags |= UsingEvents; -            } -            state.event_flags |= ProbedEvents; - -            // leave shouldPoll == true so that we check at least once -            // before relying solely on events -        } else { -            shouldPoll = false; -        } - -        static const char kGetConn[] PROGMEM = "AT+GAPGETCONN"; -        state.last_connection_update         = timer_read(); - -        if (at_command_P(kGetConn, resbuf, sizeof(resbuf))) { -            set_connected(atoi(resbuf)); -        } -    } - -#ifdef SAMPLE_BATTERY -    if (timer_elapsed(state.last_battery_update) > BatteryUpdateInterval && resp_buf.empty()) { -        state.last_battery_update = timer_read(); - -        state.vbat = analogReadPin(BATTERY_LEVEL_PIN); -    } -#endif -} - -static bool process_queue_item(struct queue_item *item, uint16_t timeout) { -    char cmdbuf[48]; -    char fmtbuf[64]; - -    // Arrange to re-check connection after keys have settled -    state.last_connection_update = timer_read(); - -#if 1 -    if (TIMER_DIFF_16(state.last_connection_update, item->added) > 0) { -        dprintf("send latency %dms\n", TIMER_DIFF_16(state.last_connection_update, item->added)); -    } -#endif - -    switch (item->queue_type) { -        case QTKeyReport: -            strcpy_P(fmtbuf, PSTR("AT+BLEKEYBOARDCODE=%02x-00-%02x-%02x-%02x-%02x-%02x-%02x")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->key.modifier, item->key.keys[0], item->key.keys[1], item->key.keys[2], item->key.keys[3], item->key.keys[4], item->key.keys[5]); -            return at_command(cmdbuf, NULL, 0, true, timeout); - -        case QTConsumer: -            strcpy_P(fmtbuf, PSTR("AT+BLEHIDCONTROLKEY=0x%04x")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->consumer); -            return at_command(cmdbuf, NULL, 0, true, timeout); - -#ifdef MOUSE_ENABLE -        case QTMouseMove: -            strcpy_P(fmtbuf, PSTR("AT+BLEHIDMOUSEMOVE=%d,%d,%d,%d")); -            snprintf(cmdbuf, sizeof(cmdbuf), fmtbuf, item->mousemove.x, item->mousemove.y, item->mousemove.scroll, item->mousemove.pan); -            if (!at_command(cmdbuf, NULL, 0, true, timeout)) { -                return false; -            } -            strcpy_P(cmdbuf, PSTR("AT+BLEHIDMOUSEBUTTON=")); -            if (item->mousemove.buttons & MOUSE_BTN1) { -                strcat(cmdbuf, "L"); -            } -            if (item->mousemove.buttons & MOUSE_BTN2) { -                strcat(cmdbuf, "R"); -            } -            if (item->mousemove.buttons & MOUSE_BTN3) { -                strcat(cmdbuf, "M"); -            } -            if (item->mousemove.buttons == 0) { -                strcat(cmdbuf, "0"); -            } -            return at_command(cmdbuf, NULL, 0, true, timeout); -#endif -        default: -            return true; -    } -} - -void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys) { -    struct queue_item item; -    bool              didWait = false; - -    item.queue_type   = QTKeyReport; -    item.key.modifier = hid_modifier_mask; -    item.added        = timer_read(); - -    while (nkeys >= 0) { -        item.key.keys[0] = keys[0]; -        item.key.keys[1] = nkeys >= 1 ? keys[1] : 0; -        item.key.keys[2] = nkeys >= 2 ? keys[2] : 0; -        item.key.keys[3] = nkeys >= 3 ? keys[3] : 0; -        item.key.keys[4] = nkeys >= 4 ? keys[4] : 0; -        item.key.keys[5] = nkeys >= 5 ? keys[5] : 0; - -        if (!send_buf.enqueue(item)) { -            if (!didWait) { -                dprint("wait for buf space\n"); -                didWait = true; -            } -            send_buf_send_one(); -            continue; -        } - -        if (nkeys <= 6) { -            return; -        } - -        nkeys -= 6; -        keys += 6; -    } -} - -void adafruit_ble_send_consumer_key(uint16_t usage) { -    struct queue_item item; - -    item.queue_type = QTConsumer; -    item.consumer   = usage; - -    while (!send_buf.enqueue(item)) { -        send_buf_send_one(); -    } -} - -#ifdef MOUSE_ENABLE -void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons) { -    struct queue_item item; - -    item.queue_type        = QTMouseMove; -    item.mousemove.x       = x; -    item.mousemove.y       = y; -    item.mousemove.scroll  = scroll; -    item.mousemove.pan     = pan; -    item.mousemove.buttons = buttons; - -    while (!send_buf.enqueue(item)) { -        send_buf_send_one(); -    } -} -#endif - -uint32_t adafruit_ble_read_battery_voltage(void) { return state.vbat; } - -bool adafruit_ble_set_mode_leds(bool on) { -    if (!state.configured) { -        return false; -    } - -    // The "mode" led is the red blinky one -    at_command_P(on ? PSTR("AT+HWMODELED=1") : PSTR("AT+HWMODELED=0"), NULL, 0); - -    // Pin 19 is the blue "connected" LED; turn that off too. -    // When turning LEDs back on, don't turn that LED on if we're -    // not connected, as that would be confusing. -    at_command_P(on && state.is_connected ? PSTR("AT+HWGPIO=19,1") : PSTR("AT+HWGPIO=19,0"), NULL, 0); -    return true; -} - -// https://learn.adafruit.com/adafruit-feather-32u4-bluefruit-le/ble-generic#at-plus-blepowerlevel -bool adafruit_ble_set_power_level(int8_t level) { -    char cmd[46]; -    if (!state.configured) { -        return false; -    } -    snprintf(cmd, sizeof(cmd), "AT+BLEPOWERLEVEL=%d", level); -    return at_command(cmd, NULL, 0, false); -} diff --git a/tmk_core/protocol/lufa/adafruit_ble.h b/tmk_core/protocol/lufa/adafruit_ble.h deleted file mode 100644 index b43e0771d9..0000000000 --- a/tmk_core/protocol/lufa/adafruit_ble.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Bluetooth Low Energy Protocol for QMK. - * Author: Wez Furlong, 2016 - * Supports the Adafruit BLE board built around the nRF51822 chip. - */ - -#pragma once - -#include <stdbool.h> -#include <stdint.h> -#include <string.h> - -#include "config_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Instruct the module to enable HID keyboard support and reset */ -extern bool adafruit_ble_enable_keyboard(void); - -/* Query to see if the BLE module is connected */ -extern bool adafruit_ble_query_is_connected(void); - -/* Returns true if we believe that the BLE module is connected. - * This uses our cached understanding that is maintained by - * calling ble_task() periodically. */ -extern bool adafruit_ble_is_connected(void); - -/* Call this periodically to process BLE-originated things */ -extern void adafruit_ble_task(void); - -/* Generates keypress events for a set of keys. - * The hid modifier mask specifies the state of the modifier keys for - * this set of keys. - * Also sends a key release indicator, so that the keys do not remain - * held down. */ -extern void adafruit_ble_send_keys(uint8_t hid_modifier_mask, uint8_t *keys, uint8_t nkeys); - -/* Send a consumer usage. - * (milliseconds) */ -extern void adafruit_ble_send_consumer_key(uint16_t usage); - -#ifdef MOUSE_ENABLE -/* Send a mouse/wheel movement report. - * The parameters are signed and indicate positive or negative direction - * change. */ -extern void adafruit_ble_send_mouse_move(int8_t x, int8_t y, int8_t scroll, int8_t pan, uint8_t buttons); -#endif - -/* Compute battery voltage by reading an analog pin. - * Returns the integer number of millivolts */ -extern uint32_t adafruit_ble_read_battery_voltage(void); - -extern bool adafruit_ble_set_mode_leds(bool on); -extern bool adafruit_ble_set_power_level(int8_t level); - -#ifdef __cplusplus -} -#endif diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 5b56e8a03c..4a30d22579 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -142,7 +142,8 @@ static void    send_keyboard(report_keyboard_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_system(uint16_t data);  static void    send_consumer(uint16_t data); -host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; +static void    send_programmable_button(uint32_t data); +host_driver_t  lufa_driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};  #ifdef VIRTSER_ENABLE  // clang-format off @@ -760,29 +761,35 @@ static void send_mouse(report_mouse_t *report) {  #endif  } -/** \brief Send Extra - * - * FIXME: Needs doc - */ -#ifdef EXTRAKEY_ENABLE -static void send_extra(uint8_t report_id, uint16_t data) { +#if defined(EXTRAKEY_ENABLE) || defined(PROGRAMMABLE_BUTTON_ENABLE) +static void send_report(void *report, size_t size) {      uint8_t timeout = 255;      if (USB_DeviceState != DEVICE_STATE_Configured) return; -    static report_extra_t r; -    r = (report_extra_t){.report_id = report_id, .usage = data};      Endpoint_SelectEndpoint(SHARED_IN_EPNUM);      /* Check if write ready for a polling interval around 10ms */      while (timeout-- && !Endpoint_IsReadWriteAllowed()) _delay_us(40);      if (!Endpoint_IsReadWriteAllowed()) return; -    Endpoint_Write_Stream_LE(&r, sizeof(report_extra_t), NULL); +    Endpoint_Write_Stream_LE(report, size, NULL);      Endpoint_ClearIN();  }  #endif +/** \brief Send Extra + * + * FIXME: Needs doc + */ +#ifdef EXTRAKEY_ENABLE +static void send_extra(uint8_t report_id, uint16_t data) { +    static report_extra_t r; +    r = (report_extra_t){.report_id = report_id, .usage = data}; +    send_report(&r, sizeof(r)); +} +#endif +  /** \brief Send System   *   * FIXME: Needs doc @@ -822,6 +829,14 @@ static void send_consumer(uint16_t data) {  #endif  } +static void send_programmable_button(uint32_t data) { +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    static report_programmable_button_t r; +    r = (report_programmable_button_t){.report_id = REPORT_ID_PROGRAMMABLE_BUTTON, .usage = data}; +    send_report(&r, sizeof(r)); +#endif +} +  /*******************************************************************************   * sendchar   ******************************************************************************/ diff --git a/tmk_core/protocol/lufa/outputselect.c b/tmk_core/protocol/lufa/outputselect.c deleted file mode 100644 index f758c65280..0000000000 --- a/tmk_core/protocol/lufa/outputselect.c +++ /dev/null @@ -1,79 +0,0 @@ -/* -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 "outputselect.h" - -#if defined(PROTOCOL_LUFA) -#    include "lufa.h" -#endif - -#ifdef MODULE_ADAFRUIT_BLE -#    include "adafruit_ble.h" -#endif - -uint8_t desired_output = OUTPUT_DEFAULT; - -/** \brief Set Output - * - * FIXME: Needs doc - */ -void set_output(uint8_t output) { -    set_output_user(output); -    desired_output = output; -} - -/** \brief Set Output User - * - * FIXME: Needs doc - */ -__attribute__((weak)) void set_output_user(uint8_t output) {} - -static bool is_usb_configured(void) { -#if defined(PROTOCOL_LUFA) -    return USB_DeviceState == DEVICE_STATE_Configured; -#endif -} - -/** \brief Auto Detect Output - * - * FIXME: Needs doc - */ -uint8_t auto_detect_output(void) { -    if (is_usb_configured()) { -        return OUTPUT_USB; -    } - -#ifdef MODULE_ADAFRUIT_BLE -    if (adafruit_ble_is_connected()) { -        return OUTPUT_BLUETOOTH; -    } -#endif - -#ifdef BLUETOOTH_ENABLE -    return OUTPUT_BLUETOOTH;  // should check if BT is connected here -#endif - -    return OUTPUT_NONE; -} - -/** \brief Where To Send - * - * FIXME: Needs doc - */ -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 deleted file mode 100644 index c4548e1122..0000000000 --- a/tmk_core/protocol/lufa/outputselect.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -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/>. -*/ - -#pragma once - -#include <stdint.h> - -enum outputs { -    OUTPUT_AUTO, - -    OUTPUT_NONE, -    OUTPUT_USB, -    OUTPUT_BLUETOOTH -}; - -#ifndef OUTPUT_DEFAULT -#    define OUTPUT_DEFAULT OUTPUT_AUTO -#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); diff --git a/tmk_core/protocol/lufa/ringbuffer.hpp b/tmk_core/protocol/lufa/ringbuffer.hpp deleted file mode 100644 index 70a3c4881d..0000000000 --- a/tmk_core/protocol/lufa/ringbuffer.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -// A simple ringbuffer holding Size elements of type T -template <typename T, uint8_t Size> -class RingBuffer { - protected: -  T buf_[Size]; -  uint8_t head_{0}, tail_{0}; - public: -  inline uint8_t nextPosition(uint8_t position) { -    return (position + 1) % Size; -  } - -  inline uint8_t prevPosition(uint8_t position) { -    if (position == 0) { -      return Size - 1; -    } -    return position - 1; -  } - -  inline bool enqueue(const T &item) { -    static_assert(Size > 1, "RingBuffer size must be > 1"); -    uint8_t next = nextPosition(head_); -    if (next == tail_) { -      // Full -      return false; -    } - -    buf_[head_] = item; -    head_ = next; -    return true; -  } - -  inline bool get(T &dest, bool commit = true) { -    auto tail = tail_; -    if (tail == head_) { -      // No more data -      return false; -    } - -    dest = buf_[tail]; -    tail = nextPosition(tail); - -    if (commit) { -      tail_ = tail; -    } -    return true; -  } - -  inline bool empty() const { return head_ == tail_; } - -  inline uint8_t size() const { -    int diff = head_ - tail_; -    if (diff >= 0) { -      return diff; -    } -    return Size + diff; -  } - -  inline T& front() { -    return buf_[tail_]; -  } - -  inline bool peek(T &item) { -    return get(item, false); -  } -}; diff --git a/tmk_core/protocol/news.c b/tmk_core/protocol/news.c deleted file mode 100644 index 4463e8dd42..0000000000 --- a/tmk_core/protocol/news.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2012 Jun WAKO <wakojun@gmail.com> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#include <stdbool.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include "news.h" - -void news_init(void) { NEWS_KBD_RX_INIT(); } - -// RX ring buffer -#define RBUF_SIZE 8 -static uint8_t rbuf[RBUF_SIZE]; -static uint8_t rbuf_head = 0; -static uint8_t rbuf_tail = 0; - -uint8_t news_recv(void) { -    uint8_t data = 0; -    if (rbuf_head == rbuf_tail) { -        return 0; -    } - -    data      = rbuf[rbuf_tail]; -    rbuf_tail = (rbuf_tail + 1) % RBUF_SIZE; -    return data; -} - -// USART RX complete interrupt -ISR(NEWS_KBD_RX_VECT) { -    uint8_t next = (rbuf_head + 1) % RBUF_SIZE; -    if (next != rbuf_tail) { -        rbuf[rbuf_head] = NEWS_KBD_RX_DATA; -        rbuf_head       = next; -    } -} - -/* -SONY NEWS Keyboard Protocol -=========================== - -Resources ---------- -    Mouse protocol of NWA-5461(Japanese) -    http://groups.google.com/group/fj.sys.news/browse_thread/thread/a01b3e3ac6ae5b2d - -    SONY NEWS Info(Japanese) -    http://katsu.watanabe.name/doc/sonynews/ - - -Pinouts -------- -    EIA 232 male connector from NWP-5461 -    ------------- -    \ 1 2 3 4 5 / -     \ 6 7 8 9 / -      --------- -    1 VCC -    2 BZ(Speaker) -    3 Keyboard Data(from keyboard MCU TxD) -    4 NC -    5 GND -    6 Unknown Input(to keyboard MCU RxD via schmitt trigger) -    7 Mouse Data(from Mouse Ext connector) -    8 Unknown Input(to Keyboard MCU Input via diode and buffer) -    9 FG -    NOTE: Two LED on keyboard are controlled by pin 6,8? - -    EIA 232 male connector from NWP-411A -    ------------- -    \ 1 2 3 4 5 / -     \ 6 7 8 9 / -      --------- -    1 VCC -    2 BZ(Speaker) -    3 Keyboard Data(from keyboard MCU TxD) -    4 NC -    5 GND -    6 NC -    7 Mouse Data(from Mouse Ext connector) -    8 NC -    9 FG -    NOTE: These are just from my guess and not confirmed. - - -Signaling ---------- -    ~~~~~~~~~~ ____XOO0X111X222X333X444X555X666X777~~~~ ~~~~~~~ -    Idle    Start  LSB                         MSB Stop Idle - -    Idle:       High -    Start bit:  Low -    Stop bit:   High -    Bit order:  LSB first - -    Baud rate:  9600 -    Interface:  TTL level(5V) UART - -    NOTE: This is observed on NWP-5461 with its DIP switch all OFF. - - -Format ------- -    MSB         LSB -    7 6 5 4 3 2 1 0   bit -    | | | | | | | | -    | +-+-+-+-+-+-+-- scan code(00-7F) -    +---------------- break flag: sets when released - - -Scan Codes ----------- -    SONY NEWS NWP-5461 -    ,---.   ,------------------------, ,------------------------. ,---------. -    | 7A|   | 01 | 02 | 03 | 04 | 05 | | 06 | 07 | 08 | 09 | 0A | | 68 | 69 | ,-----------. -    `---'   `------------------------' `------------------------' `---------' | 64| 65| 52| -    ,-------------------------------------------------------------. ,---. ,---------------| -    | 0B| 0C| 0D| 0E| 0F| 10| 11| 12| 13| 14| 15| 16| 17| 18|  19 | | 6A| | 4B| 4C| 4D| 4E| -    |-------------------------------------------------------------| |---| |---------------| -    |  1A | 1B| 1C| 1D| 1E| 1F| 20| 21| 22| 23| 24| 25| 26| 27|   | | 6B| | 4F| 50| 51| 56| -    |---------------------------------------------------------'   | |---| |---------------| -    |  28  | 29| 2A| 2B| 2C| 2D| 2E| 2F| 30| 31| 32| 33| 34|  35  | | 6C| | 53| 54| 55|   | -    |-------------------------------------------------------------| |---| |-----------| 5A| -    |  36    | 37| 38| 39| 3A| 3B| 3C| 3D| 3E| 3F| 40| 41|   42   | | 6D| | 57| 59| 58|   | -    |-------------------------------------------------------------| |---| |---------------| -    | 43  | 44 | 45 |       46          |    47    | 48| 49|  4A  | | 6E| | 66| 5B| 5C| 5D| -    `-------------------------------------------------------------' `---' `---------------' -*/ diff --git a/tmk_core/protocol/news.h b/tmk_core/protocol/news.h deleted file mode 100644 index 327a13856d..0000000000 --- a/tmk_core/protocol/news.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2012 Jun WAKO <wakojun@gmail.com> - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. -*/ - -#pragma once - -/* - * Primitive PS/2 Library for AVR - */ - -/* host role */ -void    news_init(void); -uint8_t news_recv(void); - -/* device role */ diff --git a/tmk_core/protocol/next_kbd.c b/tmk_core/protocol/next_kbd.c deleted file mode 100644 index 6f118e6172..0000000000 --- a/tmk_core/protocol/next_kbd.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - -NeXT non-ADB Keyboard Protocol - -Copyright 2013, Benjamin Gould (bgould@github.com) - -Based on: -TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com> -Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license - -Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB -Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html -Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/ - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#include <stdint.h> -#include <stdbool.h> -#include <util/atomic.h> -#include <util/delay.h> -#include "next_kbd.h" -#include "debug.h" - -static inline void     out_lo(void); -static inline void     out_hi(void); -static inline void     query(void); -static inline void     reset(void); -static inline uint32_t response(void); - -/* The keyboard sends signal with 50us pulse width on OUT line - * while it seems to miss the 50us pulse on In line. - * next_kbd_set_leds() often fails to sync LED status with 50us - * but it works well with 51us(+1us) on TMK converter(ATMeaga32u2) at least. - * TODO: test on Teensy and Pro Micro configuration - */ -#define out_hi_delay(intervals)                       \ -    do {                                              \ -        out_hi();                                     \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define out_lo_delay(intervals)                       \ -    do {                                              \ -        out_lo();                                     \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define query_delay(intervals)                        \ -    do {                                              \ -        query();                                      \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); -#define reset_delay(intervals)                        \ -    do {                                              \ -        reset();                                      \ -        _delay_us((NEXT_KBD_TIMING + 1) * intervals); \ -    } while (0); - -void next_kbd_init(void) { -    out_hi(); -    NEXT_KBD_IN_DDR &= ~(1 << NEXT_KBD_IN_BIT);  // KBD_IN  to input -    NEXT_KBD_IN_PORT |= (1 << NEXT_KBD_IN_BIT);  // KBD_IN  pull up - -    query_delay(5); -    reset_delay(8); - -    query_delay(5); -    reset_delay(8); -} - -void next_kbd_set_leds(bool left, bool right) { -    cli(); -    out_lo_delay(9); - -    out_hi_delay(3); -    out_lo_delay(1); - -    if (left) { -        out_hi_delay(1); -    } else { -        out_lo_delay(1); -    } - -    if (right) { -        out_hi_delay(1); -    } else { -        out_lo_delay(1); -    } - -    out_lo_delay(7); -    out_hi(); -    sei(); -} - -#define NEXT_KBD_READ (NEXT_KBD_IN_PIN & (1 << NEXT_KBD_IN_BIT)) -uint32_t next_kbd_recv(void) { -    // First check to make sure that the keyboard is actually connected; -    // if not, just return -    // TODO: reflect the status of the keyboard in a return code -    if (!NEXT_KBD_READ) { -        sei(); -        return 0; -    } - -    query(); -    uint32_t resp = response(); - -    return resp; -} - -static inline uint32_t response(void) { -    cli(); - -    // try a 5ms read; this should be called after the query method has -    // been run so if a key is pressed we should get a response within -    // 5ms; if not then send a reset and exit -    uint8_t  i             = 0; -    uint32_t data          = 0; -    uint16_t reset_timeout = 50000; -    while (NEXT_KBD_READ && reset_timeout) { -        asm(""); -        _delay_us(1); -        reset_timeout--; -    } -    if (!reset_timeout) { -        reset(); -        sei(); -        return 0; -    } -    _delay_us(NEXT_KBD_TIMING / 2); -    for (; i < 22; i++) { -        if (NEXT_KBD_READ) { -            data |= ((uint32_t)1 << i); -            /* Note: -             * My testing with the ATmega32u4 showed that there might -             * something wrong with the timing here; by the end of the -             * second data byte some of the modifiers can get bumped out -             * to the next bit over if we just cycle through the data -             * based on the expected interval.  There is a bit (i = 10) -             * in the middle of the data that is always on followed by -             * one that is always off - so we'll use that to reset our -             * timing in case we've gotten ahead of the keyboard; -             */ -            if (i == 10) { -                i++; -                while (NEXT_KBD_READ) -                    ; -                _delay_us(NEXT_KBD_TIMING / 2); -            } -        } else { -            /* redundant - but I don't want to remove if it might screw -             * up the timing -             */ -            data |= ((uint32_t)0 << i); -        } -        _delay_us(NEXT_KBD_TIMING); -    } - -    sei(); - -    return data; -} - -static inline void out_lo(void) { -    NEXT_KBD_OUT_PORT &= ~(1 << NEXT_KBD_OUT_BIT); -    NEXT_KBD_OUT_DDR |= (1 << NEXT_KBD_OUT_BIT); -} - -static inline void out_hi(void) { -    /* input with pull up */ -    NEXT_KBD_OUT_DDR &= ~(1 << NEXT_KBD_OUT_BIT); -    NEXT_KBD_OUT_PORT |= (1 << NEXT_KBD_OUT_BIT); -} - -static inline void query(void) { -    out_lo_delay(5); -    out_hi_delay(1); -    out_lo_delay(3); -    out_hi(); -} - -static inline void reset(void) { -    out_lo_delay(1); -    out_hi_delay(4); -    out_lo_delay(1); -    out_hi_delay(6); -    out_lo_delay(10); -    out_hi(); -} diff --git a/tmk_core/protocol/next_kbd.h b/tmk_core/protocol/next_kbd.h deleted file mode 100644 index 1249ebf392..0000000000 --- a/tmk_core/protocol/next_kbd.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -NeXT non-ADB Keyboard Protocol - -Copyright 2013, Benjamin Gould (bgould@github.com) - -Based on: -TMK firmware code Copyright 2011,2012 Jun WAKO <wakojun@gmail.com> -Arduino code by "Ladyada" Limor Fried (http://ladyada.net/, http://adafruit.com/), released under BSD license - -Timing reference thanks to http://m0115.web.fc2.com/ (dead link), http://cfile7.uf.tistory.com/image/14448E464F410BF22380BB -Pinouts thanks to http://www.68k.org/~degs/nextkeyboard.html -Keycodes from http://ftp.netbsd.org/pub/NetBSD/NetBSD-release-6/src/sys/arch/next68k/dev/ - -This software is licensed with a Modified BSD License. -All of this is supposed to be Free Software, Open Source, DFSG-free, -GPL-compatible, and OK to use in both free and proprietary applications. -Additions and corrections to this file are welcome. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright -  notice, this list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright -  notice, this list of conditions and the following disclaimer in -  the documentation and/or other materials provided with the -  distribution. - -* Neither the name of the copyright holders nor the names of -  contributors may be used to endorse or promote products derived -  from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. - -*/ - -#pragma once - -#include <stdbool.h> - -#define NEXT_KBD_KMBUS_IDLE 0x300600 -#define NEXT_KBD_TIMING 50 - -extern uint8_t next_kbd_error; - -/* host role */ -void     next_kbd_init(void); -void     next_kbd_set_leds(bool left, bool right); -uint32_t next_kbd_recv(void); diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 099964ae56..a43755f899 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -237,6 +237,25 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = {      HID_RI_END_COLLECTION(0),  #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    HID_RI_USAGE_PAGE(8, 0x0C),            // Consumer +    HID_RI_USAGE(8, 0x01),                 // Consumer Control +    HID_RI_COLLECTION(8, 0x01),            // Application +        HID_RI_REPORT_ID(8, REPORT_ID_PROGRAMMABLE_BUTTON), +        HID_RI_USAGE(8, 0x03),             // Programmable Buttons +        HID_RI_COLLECTION(8, 0x04),        // Named Array +            HID_RI_USAGE_PAGE(8, 0x09),    // Button +            HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 +            HID_RI_USAGE_MAXIMUM(8, 0x20), // Button 32 +            HID_RI_LOGICAL_MINIMUM(8, 0x00), +            HID_RI_LOGICAL_MAXIMUM(8, 0x01), +            HID_RI_REPORT_COUNT(8, 32), +            HID_RI_REPORT_SIZE(8, 1), +            HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), +        HID_RI_END_COLLECTION(0), +    HID_RI_END_COLLECTION(0), +#endif +  #ifdef NKRO_ENABLE      HID_RI_USAGE_PAGE(8, 0x01),        // Generic Desktop      HID_RI_USAGE(8, 0x06),             // Keyboard diff --git a/tmk_core/protocol/usb_hid/parser.h b/tmk_core/protocol/usb_hid/parser.h index 036281fa66..ba35b7af5a 100644 --- a/tmk_core/protocol/usb_hid/parser.h +++ b/tmk_core/protocol/usb_hid/parser.h @@ -1,5 +1,4 @@ -#ifndef PARSER_H -#define PARSER_H +#pragma once  #include "hid.h"  #include "report.h" @@ -11,5 +10,3 @@ public:      uint16_t time_stamp;      virtual void Parse(HID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf);  }; - -#endif diff --git a/tmk_core/protocol/usb_hid/usb_hid.h b/tmk_core/protocol/usb_hid/usb_hid.h index 083b68d1f5..5cb5f5d035 100644 --- a/tmk_core/protocol/usb_hid/usb_hid.h +++ b/tmk_core/protocol/usb_hid/usb_hid.h @@ -1,10 +1,6 @@ -#ifndef USB_HID_H -#define USB_HID_H +#pragma once  #include "report.h" -  extern report_keyboard_t usb_hid_keyboard_report;  extern uint16_t usb_hid_time_stamp; - -#endif diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 485b20c900..e4db5d0654 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -226,8 +226,9 @@ static void    send_keyboard(report_keyboard_t *report);  static void    send_mouse(report_mouse_t *report);  static void    send_system(uint16_t data);  static void    send_consumer(uint16_t data); +static void    send_programmable_button(uint32_t data); -static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer}; +static host_driver_t driver = {keyboard_leds, send_keyboard, send_mouse, send_system, send_consumer, send_programmable_button};  host_driver_t *vusb_driver(void) { return &driver; } @@ -296,6 +297,19 @@ void send_digitizer(report_digitizer_t *report) {  #ifdef DIGITIZER_ENABLE      if (usbInterruptIsReadyShared()) {          usbSetInterruptShared((void *)report, sizeof(report_digitizer_t)); +#endif +} + +static void send_programmable_button(uint32_t data) { +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    static report_programmable_button_t report = { +        .report_id = REPORT_ID_PROGRAMMABLE_BUTTON, +    }; + +    report.usage = data; + +    if (usbInterruptIsReadyShared()) { +        usbSetInterruptShared((void *)&report, sizeof(report));      }  #endif  } @@ -558,6 +572,26 @@ const PROGMEM uchar shared_hid_report[] = {      0xC0               // End Collection  #endif +#ifdef PROGRAMMABLE_BUTTON_ENABLE +    // Programmable buttons report descriptor +    0x05, 0x0C,                           // Usage Page (Consumer) +    0x09, 0x01,                           // Usage (Consumer Control) +    0xA1, 0x01,                           // Collection (Application) +    0x85, REPORT_ID_PROGRAMMABLE_BUTTON,  //   Report ID +    0x09, 0x03,                           //   Usage (Programmable Buttons) +    0xA1, 0x04,                           //   Collection (Named Array) +    0x05, 0x09,                           //     Usage Page (Button) +    0x19, 0x01,                           //     Usage Minimum (Button 1) +    0x29, 0x20,                           //     Usage Maximum (Button 32) +    0x15, 0x00,                           //     Logical Minimum (0) +    0x25, 0x01,                           //     Logical Maximum (1) +    0x95, 0x20,                           //     Report Count (32) +    0x75, 0x01,                           //     Report Size (1) +    0x81, 0x02,                           //     Input (Data, Variable, Absolute) +    0xC0,                                 //   End Collection +    0xC0                                  // End Collection +#endif +  #ifdef SHARED_EP_ENABLE  };  #endif | 
