diff options
Diffstat (limited to 'tmk_core/protocol')
27 files changed, 112 insertions, 3393 deletions
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c deleted file mode 100644 index 367f1b09fa..0000000000 --- a/tmk_core/protocol/adb.c +++ /dev/null @@ -1,535 +0,0 @@ -/* -Copyright 2011-19 Jun WAKO <wakojun@gmail.com> -Copyright 2013 Shay Green <gblargg@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 <util/delay.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include "adb.h" -#include "print.h" - -// GCC doesn't inline functions normally -#define data_lo() (ADB_DDR |= (1 << ADB_DATA_BIT)) -#define data_hi() (ADB_DDR &= ~(1 << ADB_DATA_BIT)) -#define data_in() (ADB_PIN & (1 << ADB_DATA_BIT)) - -#ifdef ADB_PSW_BIT -static inline void psw_lo(void); -static inline void psw_hi(void); -static inline bool psw_in(void); -#endif - -static inline void attention(void); -static inline void place_bit0(void); -static inline void place_bit1(void); -static inline void send_byte(uint8_t data); -static inline uint16_t wait_data_lo(uint16_t us); -static inline uint16_t wait_data_hi(uint16_t us); - -void adb_host_init(void) { - ADB_PORT &= ~(1 << ADB_DATA_BIT); - data_hi(); -#ifdef ADB_PSW_BIT - psw_hi(); -#endif -} - -#ifdef ADB_PSW_BIT -bool adb_host_psw(void) { return psw_in(); } -#endif - -/* - * Don't call this in a row without the delay, otherwise it makes some of poor controllers - * overloaded and misses strokes. Recommended interval is 12ms. - * - * Thanks a lot, blargg! - * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> - * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> - */ -uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); } - -#ifdef ADB_MOUSE_ENABLE -__attribute__((weak)) void adb_mouse_init(void) { return; } - -__attribute__((weak)) void adb_mouse_task(void) { return; } - -uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); } -#endif - -// This sends Talk command to read data from register and returns length of the data. -uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { - for (int8_t i = 0; i < len; i++) buf[i] = 0; - - cli(); - attention(); - send_byte((addr << 4) | ADB_CMD_TALK | reg); - place_bit0(); // Stopbit(0) - // TODO: Service Request(Srq): - // Device holds low part of comannd stopbit for 140-260us - // - // Command: - // ......._ ______________________ ___ ............_ ------- - // | | | | | | | - // Command | | | | | Data bytes | | - // ........|___| | 140-260 |__| |_............|___| - // |stop0 | Tlt Stop-to-Start |start1| |stop0 | - // - // Command without data: - // ......._ __________________________ - // | | - // Command | | - // ........|___| | 140-260 | - // |stop0 | Tlt Stop-to-Start | - // - // Service Request: - // ......._ ______ ___ ............_ ------- - // | 140-260 | | | | | | - // Command | Service Request | | | | Data bytes | | - // ........|___________________| |__| |_............|___| - // |stop0 | |start1| |stop0 | - // ......._ __________ - // | 140-260 | - // Command | Service Request | - // ........|___________________| - // |stop0 | - // This can be happened? - // ......._ ______________________ ___ ............_ ----- - // | | | | | | 140-260 | - // Command | | | | | Data bytes | Service Request | - // ........|___| | 140-260 |__| |_............|_________________| - // |stop0 | Tlt Stop-to-Start |start1| |stop0 | - // - // "Service requests are issued by the devices during a very specific time at the - // end of the reception of the command packet. - // If a device in need of service issues a service request, it must do so within - // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs." - // - // "A device sends a Service Request signal by holding the bus low during the low - // portion of the stop bit of any command or data transaction. The device must lengthen - // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15." - // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf - if (!wait_data_hi(500)) { // Service Request(310us Adjustable Keyboard): just ignored - xprintf("R"); - sei(); - return 0; - } - if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) - sei(); - return 0; // No data from device(not error); - } - - // start bit(1) - if (!wait_data_hi(40)) { - xprintf("S"); - sei(); - return 0; - } - if (!wait_data_lo(100)) { - xprintf("s"); - sei(); - return 0; - } - - uint8_t n = 0; // bit count - do { - // - // |<- bit_cell_max(130) ->| - // | |<- lo ->| - // | | |<-hi->| - // _______ - // | | | - // | 130-lo | lo-hi | - // |________| | - // - uint8_t lo = (uint8_t)wait_data_hi(130); - if (!lo) goto error; // no more bit or after stop bit - - uint8_t hi = (uint8_t)wait_data_lo(lo); - if (!hi) goto error; // stop bit extedned by Srq? - - if (n / 8 >= len) continue; // can't store in buf - - buf[n / 8] <<= 1; - if ((130 - lo) < (lo - hi)) { - buf[n / 8] |= 1; - } - } while (++n); - -error: - sei(); - return n / 8; -} - -uint16_t adb_host_talk(uint8_t addr, uint8_t reg) { - uint8_t len; - uint8_t buf[8]; - len = adb_host_talk_buf(addr, reg, buf, 8); - if (len != 2) return 0; - return (buf[0] << 8 | buf[1]); -} - -void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len) { - cli(); - attention(); - send_byte((addr << 4) | ADB_CMD_LISTEN | reg); - place_bit0(); // Stopbit(0) - // TODO: Service Request - _delay_us(200); // Tlt/Stop to Start - place_bit1(); // Startbit(1) - for (int8_t i = 0; i < len; i++) { - send_byte(buf[i]); - // xprintf("%02X ", buf[i]); - } - place_bit0(); // Stopbit(0); - sei(); -} - -void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l) { - uint8_t buf[2] = {data_h, data_l}; - adb_host_listen_buf(addr, reg, buf, 2); -} - -void adb_host_flush(uint8_t addr) { - cli(); - attention(); - send_byte((addr << 4) | ADB_CMD_FLUSH); - place_bit0(); // Stopbit(0) - _delay_us(200); // Tlt/Stop to Start - sei(); -} - -// send state of LEDs -void adb_host_kbd_led(uint8_t led) { - // Listen Register2 - // upper byte: not used - // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock - adb_host_listen(ADB_ADDR_KEYBOARD, ADB_REG_2, 0, led & 0x07); -} - -#ifdef ADB_PSW_BIT -static inline void psw_lo() { - ADB_DDR |= (1 << ADB_PSW_BIT); - ADB_PORT &= ~(1 << ADB_PSW_BIT); -} -static inline void psw_hi() { - ADB_PORT |= (1 << ADB_PSW_BIT); - ADB_DDR &= ~(1 << ADB_PSW_BIT); -} -static inline bool psw_in() { - ADB_PORT |= (1 << ADB_PSW_BIT); - ADB_DDR &= ~(1 << ADB_PSW_BIT); - return ADB_PIN & (1 << ADB_PSW_BIT); -} -#endif - -static inline void attention(void) { - data_lo(); - _delay_us(800 - 35); // bit1 holds lo for 35 more - place_bit1(); -} - -static inline void place_bit0(void) { - data_lo(); - _delay_us(65); - data_hi(); - _delay_us(35); -} - -static inline void place_bit1(void) { - data_lo(); - _delay_us(35); - data_hi(); - _delay_us(65); -} - -static inline void send_byte(uint8_t data) { - for (int i = 0; i < 8; i++) { - if (data & (0x80 >> i)) - place_bit1(); - else - place_bit0(); - } -} - -// These are carefully coded to take 6 cycles of overhead. -// inline asm approach became too convoluted -static inline uint16_t wait_data_lo(uint16_t us) { - do { - if (!data_in()) break; - _delay_us(1 - (6 * 1000000.0 / F_CPU)); - } while (--us); - return us; -} - -static inline uint16_t wait_data_hi(uint16_t us) { - do { - if (data_in()) break; - _delay_us(1 - (6 * 1000000.0 / F_CPU)); - } while (--us); - return us; -} - -/* -ADB Protocol -============ - -Resources ---------- -ADB - The Untold Story: Space Aliens Ate My Mouse - http://developer.apple.com/legacy/mac/library/#technotes/hw/hw_01.html -ADB Manager - http://developer.apple.com/legacy/mac/library/documentation/mac/pdf/Devices/ADB_Manager.pdf - Service request(5-17) -Apple IIgs Hardware Reference Second Edition [Chapter6 p121] - ftp://ftp.apple.asimov.net/pub/apple_II/documentation/Apple%20IIgs%20Hardware%20Reference.pdf -ADB Keycode - http://72.0.193.250/Documentation/macppc/adbkeycodes/ - http://m0115.web.fc2.com/m0115.jpg - [Inside Macintosh volume V, pages 191-192] - http://www.opensource.apple.com/source/IOHIDFamily/IOHIDFamily-421.18.3/IOHIDFamily/Cosmo_USB2ADB.c -ADB Signaling - http://kbdbabel.sourceforge.net/doc/kbd_signaling_pcxt_ps2_adb.pdf -ADB Overview & History - http://en.wikipedia.org/wiki/Apple_Desktop_Bus -Microchip Application Note: ADB device(with code for PIC16C) - http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en011062 -AVR ATtiny2131 ADB to PS/2 converter(Japanese) - http://hp.vector.co.jp/authors/VA000177/html/KeyBoardA5DEA5CBA5A2II.html - - -Pinouts -------- - ADB female socket from the front: - __________ - | | <--- top - | 4o o3 | - |2o o1| - | == | - |________| <--- bottom - | | <--- 4pins - - - ADB female socket from bottom: - - ========== <--- front - | | - | | - |2o o1| - |4o o3| - ---------- <--- back - - 1: Data - 2: Power SW(low when press Power key) - 3: Vcc(5V) - 4: GND - - -Commands --------- - ADB command is 1byte and consists of 4bit-address, 2bit-command - type and 2bit-register. The commands are always sent by Host. - - Command format: - 7 6 5 4 3 2 1 0 - | | | |------------ address - | |-------- command type - | |---- register - - bits commands - ------------------------------------------------------ - - - - - 0 0 0 0 Send Reset(reset all devices) - A A A A 0 0 0 1 Flush(reset a device) - - - - - 0 0 1 0 Reserved - - - - - 0 0 1 1 Reserved - - - - - 0 1 - - Reserved - A A A A 1 0 R R Listen(write to a device) - A A A A 1 1 R R Talk(read from a device) - - The command to read keycodes from keyboard is 0x2C which - consist of keyboard address 2 and Talk against register 0. - - Address: - 2: keyboard - 3: mice - - Registers: - 0: application(keyboard uses this to store its data.) - 1: application - 2: application(keyboard uses this for LEDs and state of modifiers) - 3: status and command - - -Communication -------------- - This is a minimum information for keyboard communication. - See "Resources" for detail. - - Signaling: - - ~~~~____________~~||||||||||||__~~~~~_~~|||||||||||||||__~~~~ - - |800us | |7 Command 0| | | |15-64 Data 0|Stopbit(0) - +Attention | | | +Startbit(1) - +Startbit(1) | +Tlt(140-260us) - +stopbit(0) - - Bit cells: - - bit0: ______~~~ - 65 :35us - - bit1: ___~~~~~~ - 35 :65us - - bit0 low time: 60-70% of bit cell(42-91us) - bit1 low time: 30-40% of bit cell(21-52us) - bit cell time: 70-130us - [from Apple IIgs Hardware Reference Second Edition] - - Criterion for bit0/1: - After 55us if line is low/high then bit is 0/1. - - Attention & start bit: - Host asserts low in 560-1040us then places start bit(1). - - Tlt(Stop to Start): - Bus stays high in 140-260us then device places start bit(1). - - Global reset: - Host asserts low in 2.8-5.2ms. All devices are forced to reset. - - Service request from device(Srq): - Device can request to send at commad(Global only?) stop bit. - Requesting device keeps low for 140-260us at stop bit of command. - - -Keyboard Data(Register0) - This 16bit data can contains two keycodes and two released flags. - First keycode is palced in upper byte. When one keyocode is sent, - lower byte is 0xFF. - Release flag is 1 when key is released. - - 1514 . . . . . 8 7 6 . . . . . 0 - | | | | | | | | | +-+-+-+-+-+-+- Keycode2 - | | | | | | | | +--------------- Released2(1 when the key is released) - | +-+-+-+-+-+-+----------------- Keycode1 - +------------------------------- Released1(1 when the key is released) - - Keycodes: - Scancode consists of 7bit keycode and 1bit release flag. - Device can send two keycodes at once. If just one keycode is sent - keycode1 contains it and keyocode2 is 0xFF. - - Power switch: - You can read the state from PSW line(active low) however - the switch has a special scancode 0x7F7F, so you can - also read from Data line. It uses 0xFFFF for release scancode. - -Keyboard LEDs & state of keys(Register2) - This register hold current state of three LEDs and nine keys. - The state of LEDs can be changed by sending Listen command. - - 1514 . . . . . . 7 6 5 . 3 2 1 0 - | | | | | | | | | | | | | | | +- LED1(NumLock) - | | | | | | | | | | | | | | +--- LED2(CapsLock) - | | | | | | | | | | | | | +----- LED3(ScrollLock) - | | | | | | | | | | +-+-+------- Reserved - | | | | | | | | | +------------- ScrollLock - | | | | | | | | +--------------- NumLock - | | | | | | | +----------------- Apple/Command - | | | | | | +------------------- Option - | | | | | +--------------------- Shift - | | | | +----------------------- Control - | | | +------------------------- Reset/Power - | | +--------------------------- CapsLock - | +----------------------------- Delete - +------------------------------- Reserved - -Address, Handler ID and bits(Register3) - 1514131211 . . 8 7 . . . . . . 0 - | | | | | | | | | | | | | | | | - | | | | | | | | +-+-+-+-+-+-+-+- Handler ID - | | | | +-+-+-+----------------- Address - | | | +------------------------- 0 - | | +--------------------------- Service request enable(1 = enabled) - | +----------------------------- Exceptional event(alwyas 1 if not used) - +------------------------------- 0 - -ADB Bit Cells - bit cell time: 70-130us - low part of bit0: 60-70% of bit cell - low part of bit1: 30-40% of bit cell - - bit cell time 70us 130us - -------------------------------------------- - low part of bit0 42-49 78-91 - high part of bit0 21-28 39-52 - low part of bit1 21-28 39-52 - high part of bit1 42-49 78-91 - - - bit0: - 70us bit cell: - ____________~~~~~~ - 42-49 21-28 - - 130us bit cell: - ____________~~~~~~ - 78-91 39-52 - - bit1: - 70us bit cell: - ______~~~~~~~~~~~~ - 21-28 42-49 - - 130us bit cell: - ______~~~~~~~~~~~~ - 39-52 78-91 - - [from Apple IIgs Hardware Reference Second Edition] - -Keyboard Handle ID - Apple Standard Keyboard M0116: 0x01 - Apple Extended Keyboard M0115: 0x02 - Apple Extended Keyboard II M3501: 0x02 - Apple Adjustable Keybaord: 0x10 - - http://lxr.free-electrons.com/source/drivers/macintosh/adbhid.c?v=4.4#L802 - -END_OF_ADB -*/ diff --git a/tmk_core/protocol/adb.h b/tmk_core/protocol/adb.h deleted file mode 100644 index fe8becc2d5..0000000000 --- a/tmk_core/protocol/adb.h +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2011-19 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 - -#include <stdint.h> -#include <stdbool.h> - -#if !(defined(ADB_PORT) && defined(ADB_PIN) && defined(ADB_DDR) && defined(ADB_DATA_BIT)) -# error "ADB port setting is required in config.h" -#endif - -#define ADB_POWER 0x7F -#define ADB_CAPS 0x39 - -/* ADB commands */ -// Default Address -#define ADB_ADDR_0 0 -#define ADB_ADDR_DONGLE 1 -#define ADB_ADDR_KEYBOARD 2 -#define ADB_ADDR_MOUSE 3 -#define ADB_ADDR_TABLET 4 -#define ADB_ADDR_APPLIANCE 7 -#define ADB_ADDR_8 8 -#define ADB_ADDR_9 9 -#define ADB_ADDR_10 10 -#define ADB_ADDR_11 11 -#define ADB_ADDR_12 12 -#define ADB_ADDR_13 13 -#define ADB_ADDR_14 14 -#define ADB_ADDR_15 15 -// for temporary purpose, do not use for polling -#define ADB_ADDR_TMP 15 -#define ADB_ADDR_MOUSE_POLL 10 -// Command Type -#define ADB_CMD_RESET 0 -#define ADB_CMD_FLUSH 1 -#define ADB_CMD_LISTEN 8 -#define ADB_CMD_TALK 12 -// Register -#define ADB_REG_0 0 -#define ADB_REG_1 1 -#define ADB_REG_2 2 -#define ADB_REG_3 3 - -/* ADB keyboard handler id */ -#define ADB_HANDLER_STD 0x01 /* IIGS, M0116 */ -#define ADB_HANDLER_AEK 0x02 /* M0115, M3501 */ -#define ADB_HANDLER_AEK_RMOD 0x03 /* M0115, M3501, alternate mode enableing right modifiers */ -#define ADB_HANDLER_STD_ISO 0x04 /* M0118, ISO swapping keys */ -#define ADB_HANDLER_AEK_ISO 0x05 /* M0115, M3501, ISO swapping keys */ -#define ADB_HANDLER_M1242_ANSI 0x10 /* Adjustable keyboard */ -#define ADB_HANDLER_CLASSIC1_MOUSE 0x01 -#define ADB_HANDLER_CLASSIC2_MOUSE 0x02 -#define ADB_HANDLER_EXTENDED_MOUSE 0x04 -#define ADB_HANDLER_TURBO_MOUSE 0x32 - -// ADB host -void adb_host_init(void); -bool adb_host_psw(void); -uint16_t adb_host_talk(uint8_t addr, uint8_t reg); -uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); -void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l); -void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len); -void adb_host_flush(uint8_t addr); -void adb_host_kbd_led(uint8_t led); -uint16_t adb_host_kbd_recv(void); -uint16_t adb_host_mouse_recv(void); - -// ADB Mouse -void adb_mouse_task(void); -void adb_mouse_init(void); diff --git a/tmk_core/protocol/chibios/chibios.c b/tmk_core/protocol/chibios/chibios.c index 78a2e3fcbb..c860328c80 100644 --- a/tmk_core/protocol/chibios/chibios.c +++ b/tmk_core/protocol/chibios/chibios.c @@ -27,6 +27,7 @@ #include "keyboard.h" #include "action.h" #include "action_util.h" +#include "usb_device_state.h" #include "mousekey.h" #include "led.h" #include "sendchar.h" @@ -42,12 +43,6 @@ #ifdef SLEEP_LED_ENABLE # include "sleep_led.h" #endif -#ifdef SERIAL_LINK_ENABLE -# include "serial_link/system/serial_link.h" -#endif -#ifdef VISUALIZER_ENABLE -# include "visualizer/visualizer.h" -#endif #ifdef MIDI_ENABLE # include "qmk_midi.h" #endif @@ -139,6 +134,8 @@ void boardInit(void) { } void protocol_setup(void) { + usb_device_state_init(); + // TESTING // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); @@ -154,19 +151,11 @@ void protocol_init(void) { setup_midi(); #endif -#ifdef SERIAL_LINK_ENABLE - init_serial_link(); -#endif - -#ifdef VISUALIZER_ENABLE - visualizer_init(); -#endif - host_driver_t *driver = NULL; - /* Wait until the USB or serial link is active */ + /* Wait until USB is active */ while (true) { -#if defined(WAIT_FOR_USB) || defined(SERIAL_LINK_ENABLE) +#if defined(WAIT_FOR_USB) if (USB_DRIVER.state == USB_ACTIVE) { driver = &chibios_driver; break; @@ -175,13 +164,6 @@ void protocol_init(void) { driver = &chibios_driver; break; #endif -#ifdef SERIAL_LINK_ENABLE - if (is_serial_link_connected()) { - driver = get_serial_link_driver(); - break; - } - serial_link_update(); -#endif wait_ms(50); } @@ -211,14 +193,8 @@ void protocol_task(void) { #if !defined(NO_USB_STARTUP_CHECK) if (USB_DRIVER.state == USB_SUSPENDED) { print("[s]"); -# ifdef VISUALIZER_ENABLE - visualizer_suspend(); -# endif while (USB_DRIVER.state == USB_SUSPENDED) { /* Do this in the suspended state */ -# ifdef SERIAL_LINK_ENABLE - serial_link_update(); -# endif suspend_power_down(); // on AVR this deep sleeps for 15ms /* Remote wakeup */ if (suspend_wakeup_condition()) { @@ -232,10 +208,6 @@ void protocol_task(void) { # ifdef MOUSEKEY_ENABLE mousekey_send(); # endif /* MOUSEKEY_ENABLE */ - -# ifdef VISUALIZER_ENABLE - visualizer_resume(); -# endif } #endif diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index cc282e6a9b..9b139b3992 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -39,6 +39,7 @@ # include "led.h" #endif #include "wait.h" +#include "usb_device_state.h" #include "usb_descriptor.h" #include "usb_driver.h" @@ -412,6 +413,7 @@ static inline bool usb_event_queue_dequeue(usbevent_t *event) { } static inline void usb_event_suspend_handler(void) { + usb_device_state_set_suspend(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); #ifdef SLEEP_LED_ENABLE sleep_led_enable(); #endif /* SLEEP_LED_ENABLE */ @@ -419,6 +421,7 @@ static inline void usb_event_suspend_handler(void) { static inline void usb_event_wakeup_handler(void) { suspend_wakeup_init(); + usb_device_state_set_resume(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); #ifdef SLEEP_LED_ENABLE sleep_led_disable(); // NOTE: converters may not accept this @@ -440,6 +443,15 @@ void usb_event_queue_task(void) { last_suspend_state = false; usb_event_wakeup_handler(); break; + case USB_EVENT_CONFIGURED: + usb_device_state_set_configuration(USB_DRIVER.configuration != 0, USB_DRIVER.configuration); + break; + case USB_EVENT_UNCONFIGURED: + usb_device_state_set_configuration(false, 0); + break; + case USB_EVENT_RESET: + usb_device_state_set_reset(); + break; default: // Nothing to do, we don't handle it. break; @@ -482,13 +494,14 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { if (last_suspend_state) { usb_event_queue_enqueue(USB_EVENT_WAKEUP); } + usb_event_queue_enqueue(USB_EVENT_CONFIGURED); return; case USB_EVENT_SUSPEND: - usb_event_queue_enqueue(USB_EVENT_SUSPEND); /* Falls into.*/ case USB_EVENT_UNCONFIGURED: /* Falls into.*/ case USB_EVENT_RESET: + usb_event_queue_enqueue(event); for (int i = 0; i < NUM_USB_DRIVERS; i++) { chSysLockFromISR(); /* Disconnection event on suspend.*/ 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..753762358d 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -52,6 +52,7 @@ #include "usb_descriptor.h" #include "lufa.h" #include "quantum.h" +#include "usb_device_state.h" #include <util/atomic.h> #ifdef NKRO_ENABLE @@ -142,7 +143,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 @@ -413,7 +415,10 @@ void EVENT_USB_Device_Disconnect(void) { * * FIXME: Needs doc */ -void EVENT_USB_Device_Reset(void) { print("[R]"); } +void EVENT_USB_Device_Reset(void) { + print("[R]"); + usb_device_state_set_reset(); +} /** \brief Event USB Device Connect * @@ -421,6 +426,8 @@ void EVENT_USB_Device_Reset(void) { print("[R]"); } */ void EVENT_USB_Device_Suspend() { print("[S]"); + usb_device_state_set_suspend(USB_Device_ConfigurationNumber != 0, USB_Device_ConfigurationNumber); + #ifdef SLEEP_LED_ENABLE sleep_led_enable(); #endif @@ -436,6 +443,8 @@ void EVENT_USB_Device_WakeUp() { suspend_wakeup_init(); #endif + usb_device_state_set_resume(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber); + #ifdef SLEEP_LED_ENABLE sleep_led_disable(); // NOTE: converters may not accept this @@ -528,6 +537,8 @@ void EVENT_USB_Device_ConfigurationChanged(void) { /* Setup digitizer endpoint */ ConfigSuccess &= Endpoint_ConfigureEndpoint((DIGITIZER_IN_EPNUM | ENDPOINT_DIR_IN), EP_TYPE_INTERRUPT, DIGITIZER_EPSIZE, 1); #endif + + usb_device_state_set_configuration(USB_DeviceState == DEVICE_STATE_Configured, USB_Device_ConfigurationNumber); } /* FIXME: Expose this table in the docs somehow @@ -760,29 +771,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 +839,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 ******************************************************************************/ @@ -1044,6 +1069,7 @@ void protocol_setup(void) { #endif setup_mcu(); + usb_device_state_init(); keyboard_setup(); } diff --git a/tmk_core/protocol/lufa/lufa.h b/tmk_core/protocol/lufa/lufa.h index 348a84c031..6a5205609e 100644 --- a/tmk_core/protocol/lufa/lufa.h +++ b/tmk_core/protocol/lufa/lufa.h @@ -56,14 +56,3 @@ extern host_driver_t lufa_driver; #ifdef __cplusplus } #endif - -#ifdef API_ENABLE -# include "api.h" -#endif - -#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 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/m0110.c b/tmk_core/protocol/m0110.c deleted file mode 100644 index 64f2fa50ab..0000000000 --- a/tmk_core/protocol/m0110.c +++ /dev/null @@ -1,583 +0,0 @@ -/* -Copyright 2011,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. -*/ -/* M0110A Support was contributed by skagon@github */ - -#include <stdbool.h> -#include <avr/io.h> -#include <avr/interrupt.h> -#include <util/delay.h> -#include "m0110.h" -#include "debug.h" - -static inline uint8_t raw2scan(uint8_t raw); -static inline uint8_t inquiry(void); -static inline uint8_t instant(void); -static inline void clock_lo(void); -static inline void clock_hi(void); -static inline bool clock_in(void); -static inline void data_lo(void); -static inline void data_hi(void); -static inline bool data_in(void); -static inline uint16_t wait_clock_lo(uint16_t us); -static inline uint16_t wait_clock_hi(uint16_t us); -static inline uint16_t wait_data_lo(uint16_t us); -static inline uint16_t wait_data_hi(uint16_t us); -static inline void idle(void); -static inline void request(void); - -#define WAIT_US(stat, us, err) \ - do { \ - if (!wait_##stat(us)) { \ - m0110_error = err; \ - goto ERROR; \ - } \ - } while (0) - -#define WAIT_MS(stat, ms, err) \ - do { \ - uint16_t _ms = ms; \ - while (_ms) { \ - if (wait_##stat(1000)) { \ - break; \ - } \ - _ms--; \ - } \ - if (_ms == 0) { \ - m0110_error = err; \ - goto ERROR; \ - } \ - } while (0) - -#define KEY(raw) ((raw)&0x7f) -#define IS_BREAK(raw) (((raw)&0x80) == 0x80) - -uint8_t m0110_error = 0; - -void m0110_init(void) { - idle(); - _delay_ms(1000); - - /* Not needed to initialize in fact. - uint8_t data; - m0110_send(M0110_MODEL); - data = m0110_recv(); - print("m0110_init model: "); print_hex8(data); print("\n"); - - m0110_send(M0110_TEST); - data = m0110_recv(); - print("m0110_init test: "); print_hex8(data); print("\n"); - */ -} - -uint8_t m0110_send(uint8_t data) { - m0110_error = 0; - - request(); - WAIT_MS(clock_lo, 250, 1); // keyboard may block long time - for (uint8_t bit = 0x80; bit; bit >>= 1) { - WAIT_US(clock_lo, 250, 3); - if (data & bit) { - data_hi(); - } else { - data_lo(); - } - WAIT_US(clock_hi, 200, 4); - } - _delay_us(100); // hold last bit for 80us - idle(); - return 1; -ERROR: - print("m0110_send err: "); - print_hex8(m0110_error); - print("\n"); - _delay_ms(500); - idle(); - return 0; -} - -uint8_t m0110_recv(void) { - uint8_t data = 0; - m0110_error = 0; - - WAIT_MS(clock_lo, 250, 1); // keyboard may block long time - for (uint8_t i = 0; i < 8; i++) { - data <<= 1; - WAIT_US(clock_lo, 200, 2); - WAIT_US(clock_hi, 200, 3); - if (data_in()) { - data |= 1; - } - } - idle(); - return data; -ERROR: - print("m0110_recv err: "); - print_hex8(m0110_error); - print("\n"); - _delay_ms(500); - idle(); - return 0xFF; -} - -/* -Handling for exceptional case of key combinations for M0110A - -Shift and Calc/Arrow key could be operated simultaneously: - - Case Shift Arrow Events Interpret - ------------------------------------------------------------------- - 1 Down Down 71, 79, DD Calc(d)*a *b - 2 Down Up 71, 79, UU Arrow&Calc(u)*a - 3 Up Down F1, 79, DD Shift(u) *c - 4 Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a - - Case Shift Calc Events Interpret - ------------------------------------------------------------------- - 5(1) Down Down 71, 71, 79, DD Shift(d) and Cacl(d) - 6(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a - 7(1) Up Down F1, 71, 79, DD Shift(u) and Calc(d) - 8(4) Up Up F1, F1, 79, UU Shift(ux2) and Arrow&Calc(u)*a - -During Calc key is hold: - Case Shift Arrow Events Interpret - ------------------------------------------------------------------- - A(3) ---- Down F1, 79, DD Shift(u) *c - B ---- Up 79, UU Arrow&Calc(u)*a - C Down ---- F1, 71 Shift(u) and Shift(d) - D Up ---- F1 Shift(u) - E Hold Down 79, DD Normal - F Hold Up 79, UU Arrow&Calc(u)*a - G(1) Down Down F1, 71, 79, DD Shift(u)*b and Calc(d)*a - H(2) Down Up F1, 71, 79, UU Shift(u) and Arrow&Calc(u)*a - I(3) Up Down F1, F1, 79, DD Shift(ux2) *c - J(4) Up Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a - - Case Shift Calc Events Interpret - ------------------------------------------------------------------- - K(1) ---- Down 71, 79, DD Calc(d)*a - L(4) ---- Up F1, 79, UU Shift(u) and Arrow&Calc(u)*a - M(1) Hold Down 71, 79, DD Calc(d)*a - N Hold Up 79, UU Arrow&Calc(u)*a - - Where DD/UU indicates part of Keypad Down/Up event. - *a: Impossible to distinguish btween Arrow and Calc event. - *b: Shift(d) event is ignored. - *c: Arrow/Calc(d) event is ignored. -*/ -uint8_t m0110_recv_key(void) { - static uint8_t keybuf = 0x00; - static uint8_t keybuf2 = 0x00; - static uint8_t rawbuf = 0x00; - uint8_t raw, raw2, raw3; - - if (keybuf) { - raw = keybuf; - keybuf = 0x00; - return raw; - } - if (keybuf2) { - raw = keybuf2; - keybuf2 = 0x00; - return raw; - } - - if (rawbuf) { - raw = rawbuf; - rawbuf = 0x00; - } else { - raw = instant(); // Use INSTANT for better response. Should be INQUIRY ? - } - switch (KEY(raw)) { - case M0110_KEYPAD: - raw2 = instant(); - switch (KEY(raw2)) { - case M0110_ARROW_UP: - case M0110_ARROW_DOWN: - case M0110_ARROW_LEFT: - case M0110_ARROW_RIGHT: - if (IS_BREAK(raw2)) { - // Case B,F,N: - keybuf = (raw2scan(raw2) | M0110_CALC_OFFSET); // Calc(u) - return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); // Arrow(u) - } - break; - } - // Keypad or Arrow - return (raw2scan(raw2) | M0110_KEYPAD_OFFSET); - break; - case M0110_SHIFT: - raw2 = instant(); - switch (KEY(raw2)) { - case M0110_SHIFT: - // Case: 5-8,C,G,H - rawbuf = raw2; - return raw2scan(raw); // Shift(d/u) - break; - case M0110_KEYPAD: - // Shift + Arrow, Calc, or etc. - raw3 = instant(); - switch (KEY(raw3)) { - case M0110_ARROW_UP: - case M0110_ARROW_DOWN: - case M0110_ARROW_LEFT: - case M0110_ARROW_RIGHT: - if (IS_BREAK(raw)) { - if (IS_BREAK(raw3)) { - // Case 4: - print("(4)\n"); - keybuf2 = raw2scan(raw); // Shift(u) - keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u) - return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u) - } else { - // Case 3: - print("(3)\n"); - return (raw2scan(raw)); // Shift(u) - } - } else { - if (IS_BREAK(raw3)) { - // Case 2: - print("(2)\n"); - keybuf = (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(u) - return (raw2scan(raw3) | M0110_KEYPAD_OFFSET); // Arrow(u) - } else { - // Case 1: - print("(1)\n"); - return (raw2scan(raw3) | M0110_CALC_OFFSET); // Calc(d) - } - } - break; - default: - // Shift + Keypad - keybuf = (raw2scan(raw3) | M0110_KEYPAD_OFFSET); - return raw2scan(raw); // Shift(d/u) - break; - } - break; - default: - // Shift + Normal keys - keybuf = raw2scan(raw2); - return raw2scan(raw); // Shift(d/u) - break; - } - break; - default: - // Normal keys - return raw2scan(raw); - break; - } -} - -static inline uint8_t raw2scan(uint8_t raw) { return (raw == M0110_NULL) ? M0110_NULL : ((raw == M0110_ERROR) ? M0110_ERROR : (((raw & 0x80) | ((raw & 0x7F) >> 1)))); } - -static inline uint8_t inquiry(void) { - m0110_send(M0110_INQUIRY); - return m0110_recv(); -} - -static inline uint8_t instant(void) { - m0110_send(M0110_INSTANT); - uint8_t data = m0110_recv(); - if (data != M0110_NULL) { - debug_hex(data); - debug(" "); - } - return data; -} - -static inline void clock_lo() { - M0110_CLOCK_PORT &= ~(1 << M0110_CLOCK_BIT); - M0110_CLOCK_DDR |= (1 << M0110_CLOCK_BIT); -} -static inline void clock_hi() { - /* input with pull up */ - M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); - M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); -} -static inline bool clock_in() { - M0110_CLOCK_DDR &= ~(1 << M0110_CLOCK_BIT); - M0110_CLOCK_PORT |= (1 << M0110_CLOCK_BIT); - _delay_us(1); - return M0110_CLOCK_PIN & (1 << M0110_CLOCK_BIT); -} -static inline void data_lo() { - M0110_DATA_PORT &= ~(1 << M0110_DATA_BIT); - M0110_DATA_DDR |= (1 << M0110_DATA_BIT); -} -static inline void data_hi() { - /* input with pull up */ - M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); - M0110_DATA_PORT |= (1 << M0110_DATA_BIT); -} -static inline bool data_in() { - M0110_DATA_DDR &= ~(1 << M0110_DATA_BIT); - M0110_DATA_PORT |= (1 << M0110_DATA_BIT); - _delay_us(1); - return M0110_DATA_PIN & (1 << M0110_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; -} - -static inline void idle(void) { - clock_hi(); - data_hi(); -} - -static inline void request(void) { - clock_hi(); - data_lo(); -} - -/* -Primitive M0110 Library for AVR -============================== - - -Signaling ---------- -CLOCK is always from KEYBOARD. DATA are sent with MSB first. - -1) IDLE: both lines are high. - CLOCK ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - DATA ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -2) KEYBOARD->HOST: HOST reads bit on rising edge. - CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ - DATA ~~~~~~~~~~~~X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ - <--> 160us(clock low) - <---> 180us(clock high) - -3) HOST->KEYBOARD: HOST asserts bit on falling edge. - CLOCK ~~~~~~~~~~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~|__|~~~~~~~~~~~ - DATA ~~~~~~|_____X777777X666666X555555X444444X333333X222222X111111X000000X~~~~~~~ - <----> 840us(request to send by host) <---> 80us(hold DATA) - <--> 180us(clock low) - <---> 220us(clock high) - - -Protocol --------- -COMMAND: - Inquiry 0x10 get key event with block - Instant 0x12 get key event - Model 0x14 get model number(M0110 responds with 0x09) - bit 7 1 if another device connected(used when keypad exists?) - bit4-6 next device model number - bit1-3 keyboard model number - bit 0 always 1 - Test 0x16 test(ACK:0x7D/NAK:0x77) - -KEY EVENT: - bit 7 key state(0:press 1:release) - bit 6-1 scan code(see below) - bit 0 always 1 - To get scan code use this: ((bits&(1<<7)) | ((bits&0x7F))>>1). - - Note: On the M0110A, Keypad keys and Arrow keys are preceded by 0x79. - Moreover, some Keypad keys(=, /, * and +) are preceded by 0x71 on press and 0xF1 on release. - -ARROW KEYS: - Arrow keys and Calc keys(+,*,/,= on keypad) share same byte sequence and preceding byte of - Calc keys(0x71 and 0xF1) means press and release event of SHIFT. This causes a very confusing situation, - it is difficult or impossible to tell Calc key from Arrow key plus SHIFT in some cases. - - Raw key events: - press release - ---------------- ---------------- - Left: 0x79, 0x0D 0x79, 0x8D - Right: 0x79, 0x05 0x79, 0x85 - Up: 0x79, 0x1B 0x79, 0x9B - Down: 0x79, 0x11 0x79, 0x91 - Pad+: 0x71, 0x79, 0x0D 0xF1, 0x79, 0x8D - Pad*: 0x71, 0x79, 0x05 0xF1, 0x79, 0x85 - Pad/: 0x71, 0x79, 0x1B 0xF1, 0x79, 0x9B - Pad=: 0x71, 0x79, 0x11 0xF1, 0x79, 0x91 - - -RAW CODE: - M0110A - ,---------------------------------------------------------. ,---------------. - | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| - |---------------------------------------------------------| |---------------| - |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| - |-----------------------------------------------------' | |---------------| - |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| - |---------------------------------------------------------| |---------------| - |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | - |---------------------------------------------------------' |-----------|Ent| - |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | - `---------------------------------------------------------' `---------------' - ,---------------------------------------------------------. ,---------------. - | 65| 25| 27| 29| 2B| 2F| 2D| 35| 39| 33| 3B| 37| 31| 67| |+0F|*11|*1B|*05| - |---------------------------------------------------------| |---------------| - | 61| 19| 1B| 1D| 1F| 23| 21| 41| 45| 3F| 47| 43| 3D| | |+33|+37|+39|+1D| - |-----------------------------------------------------' | |---------------| - | 73| 01| 03| 05| 07| 0B| 09| 4D| 51| 4B| 53| 4F| 49| |+2D|+2F|+31|*0D| - |---------------------------------------------------------| |---------------| - | 71| 0D| 0F| 11| 13| 17| 5B| 5D| 27| 5F| 59| 71|+1B| |+27|+29|+2B| | - |---------------------------------------------------------' |-----------|+19| - | 75| 6F| 63 | 55|+0D|+05|+11| | +25|+03| | - `---------------------------------------------------------' `---------------' - + 0x79, 0xDD / 0xF1, 0xUU - * 0x71, 0x79,DD / 0xF1, 0x79, 0xUU - - -MODEL NUMBER: - M0110: 0x09 00001001 : model number 4 (100) - M0110A: 0x0B 00001011 : model number 5 (101) - M0110 & M0120: ??? - - -Scan Code ---------- - m0110_recv_key() function returns following scan codes instead of M0110 raw codes. - Scan codes are 1 byte size and MSB(bit7) is set when key is released. - - scancode = ((raw&0x80) | ((raw&0x7F)>>1)) - - M0110 M0120 - ,---------------------------------------------------------. ,---------------. - | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt| - |---------------------------------------------------------| |---------------| - |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up | - |---------------------------------------------------------| |---------------| - |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn | - |---------------------------------------------------------| |---------------| - |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| | - `---------------------------------------------------------' |-----------|Ent| - |Opt|Mac | Space |Enter|Opt| | 0| .| | - `------------------------------------------------' `---------------' - ,---------------------------------------------------------. ,---------------. - | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42| - |---------------------------------------------------------| |---------------| - | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D| - |---------------------------------------------------------| |---------------| - | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48| - |---------------------------------------------------------| |---------------| - | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| | - `---------------------------------------------------------' |-----------| 4C| - | 3A| 37| 31 | 34| 3A| | 52| 41| | - `------------------------------------------------' `---------------' - - International keyboard(See page 22 of "Technical Info for 128K/512K") - ,---------------------------------------------------------. - | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| - |---------------------------------------------------------| - | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| - |------------------------------------------------------ | - | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | - |---------------------------------------------------------| - | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 0A| 38| - `---------------------------------------------------------' - | 3A| 37| 34 | 31| 3A| - `------------------------------------------------' - - M0110A - ,---------------------------------------------------------. ,---------------. - | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bcksp| |Clr| =| /| *| - |---------------------------------------------------------| |---------------| - |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| | | 7| 8| 9| -| - |-----------------------------------------------------' | |---------------| - |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6| +| - |---------------------------------------------------------| |---------------| - |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shft|Up | | 1| 2| 3| | - |---------------------------------------------------------' |-----------|Ent| - |Optio|Mac | Space | \|Lft|Rgt|Dn | | 0| .| | - `---------------------------------------------------------' `---------------' - ,---------------------------------------------------------. ,---------------. - | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 68| 6D| 62| - |---------------------------------------------------------| |---------------| - | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| | | 59| 5B| 5C| 4E| - |-----------------------------------------------------' | |---------------| - | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 66| - |---------------------------------------------------------| |---------------| - | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| 4D| | 53| 54| 55| | - |---------------------------------------------------------' |-----------| 4C| - | 3A| 37| 31 | 2A| 46| 42| 48| | 52| 41| | - `---------------------------------------------------------' `---------------' - - -References ----------- -Technical Info for 128K/512K and Plus - ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20128K.pdf - ftp://ftp.apple.asimov.net/pub/apple_II/documentation/macintosh/Mac%20Hardware%20Info%20-%20Mac%20Plus.pdf -Protocol: - Page 20 of Tech Info for 128K/512K - http://www.mac.linux-m68k.org/devel/plushw.php -Connector: - Page 20 of Tech Info for 128K/512K - http://www.kbdbabel.org/conn/kbd_connector_macplus.png -Signaling: - http://www.kbdbabel.org/signaling/kbd_signaling_mac.png - http://typematic.blog.shinobi.jp/Entry/14/ -M0110 raw scan codes: - Page 22 of Tech Info for 128K/512K - Page 07 of Tech Info for Plus - http://m0115.web.fc2.com/m0110.jpg - http://m0115.web.fc2.com/m0110a.jpg -*/ diff --git a/tmk_core/protocol/m0110.h b/tmk_core/protocol/m0110.h deleted file mode 100644 index 63ff3e90ec..0000000000 --- a/tmk_core/protocol/m0110.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2011,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 - -/* port settings for clock and data line */ -#if !(defined(M0110_CLOCK_PORT) && defined(M0110_CLOCK_PIN) && defined(M0110_CLOCK_DDR) && defined(M0110_CLOCK_BIT)) -# error "M0110 clock port setting is required in config.h" -#endif - -#if !(defined(M0110_DATA_PORT) && defined(M0110_DATA_PIN) && defined(M0110_DATA_DDR) && defined(M0110_DATA_BIT)) -# error "M0110 data port setting is required in config.h" -#endif - -/* Commands */ -#define M0110_INQUIRY 0x10 -#define M0110_INSTANT 0x14 -#define M0110_MODEL 0x16 -#define M0110_TEST 0x36 - -/* Response(raw byte from M0110) */ -#define M0110_NULL 0x7B -#define M0110_KEYPAD 0x79 -#define M0110_TEST_ACK 0x7D -#define M0110_TEST_NAK 0x77 -#define M0110_SHIFT 0x71 -#define M0110_ARROW_UP 0x1B -#define M0110_ARROW_DOWN 0x11 -#define M0110_ARROW_LEFT 0x0D -#define M0110_ARROW_RIGHT 0x05 - -/* This inidcates no response. */ -#define M0110_ERROR 0xFF - -/* scan code offset for keypad and arrow keys */ -#define M0110_KEYPAD_OFFSET 0x40 -#define M0110_CALC_OFFSET 0x60 - -extern uint8_t m0110_error; - -/* host role */ -void m0110_init(void); -uint8_t m0110_send(uint8_t data); -uint8_t m0110_recv(void); -uint8_t m0110_recv_key(void); -uint8_t m0110_inquiry(void); -uint8_t m0110_instant(void); diff --git a/tmk_core/protocol/midi/qmk_midi.c b/tmk_core/protocol/midi/qmk_midi.c index c18dbf9930..3a454d61ae 100644 --- a/tmk_core/protocol/midi/qmk_midi.c +++ b/tmk_core/protocol/midi/qmk_midi.c @@ -4,9 +4,6 @@ #include "midi.h" #include "usb_descriptor.h" #include "process_midi.h" -#if API_SYSEX_ENABLE -# include "api_sysex.h" -#endif /******************************************************************************* * MIDI @@ -124,41 +121,6 @@ static void cc_callback(MidiDevice* device, uint8_t chan, uint8_t num, uint8_t v // midi_send_cc(device, (chan + 1) % 16, num, val); } -#ifdef API_SYSEX_ENABLE -uint8_t midi_buffer[MIDI_SYSEX_BUFFER] = {0}; - -static void sysex_callback(MidiDevice* device, uint16_t start, uint8_t length, uint8_t* data) { - // 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); - 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 - void midi_init(void); void setup_midi(void) { @@ -170,7 +132,4 @@ void setup_midi(void) { midi_device_set_pre_input_process_func(&midi_device, usb_get_midi); midi_register_fallthrough_callback(&midi_device, fallthrough_callback); midi_register_cc_callback(&midi_device, cc_callback); -#ifdef API_SYSEX_ENABLE - midi_register_sysex_callback(&midi_device, sysex_callback); -#endif } 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 diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h deleted file mode 100644 index 538ff0e459..0000000000 --- a/tmk_core/protocol/xt.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2018 Jun WAKO <wakojun@gmail.com> -Copyright 2016 Ethan Apodaca <papodaca@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 - -#include "quantum.h" - -#define XT_DATA_IN() \ - do { \ - setPinInput(XT_DATA_PIN); \ - writePinHigh(XT_DATA_PIN); \ - } while (0) - -#define XT_DATA_READ() readPin(XT_DATA_PIN) - -#define XT_DATA_LO() \ - do { \ - writePinLow(XT_DATA_PIN); \ - setPinOutput(XT_DATA_PIN); \ - } while (0) - -#define XT_CLOCK_IN() \ - do { \ - setPinInput(XT_CLOCK_PIN); \ - writePinHigh(XT_CLOCK_PIN); \ - } while (0) - -#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN) - -#define XT_CLOCK_LO() \ - do { \ - writePinLow(XT_CLOCK_PIN); \ - setPinOutput(XT_CLOCK_PIN); \ - } while (0) - -void xt_host_init(void); - -uint8_t xt_host_recv(void); diff --git a/tmk_core/protocol/xt_interrupt.c b/tmk_core/protocol/xt_interrupt.c deleted file mode 100644 index ba9d71848f..0000000000 --- a/tmk_core/protocol/xt_interrupt.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2018 Jun WAKO <wakojun@gmail.com> -Copyright 2016 Ethan Apodaca <papodaca@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/interrupt.h> -#include "xt.h" -#include "wait.h" -#include "debug.h" - -static inline uint8_t pbuf_dequeue(void); -static inline void pbuf_enqueue(uint8_t data); -static inline bool pbuf_has_data(void); -static inline void pbuf_clear(void); - -void xt_host_init(void) { - XT_INT_INIT(); - XT_INT_OFF(); - - /* hard reset */ -#ifdef XT_RESET - XT_RESET(); -#endif - - /* soft reset: pull clock line down for 20ms */ - XT_DATA_LO(); - XT_CLOCK_LO(); - wait_ms(20); - - /* input mode with pullup */ - XT_CLOCK_IN(); - XT_DATA_IN(); - - XT_INT_ON(); -} - -/* get data received by interrupt */ -uint8_t xt_host_recv(void) { - if (pbuf_has_data()) { - return pbuf_dequeue(); - } else { - return 0; - } -} - -ISR(XT_INT_VECT) { - /* - * XT signal format consits of 10 or 9 clocks and sends start bits and 8-bit data, - * which should be read on falling edge of clock. - * - * start(0), start(1), bit0, bit1, bit2, bit3, bit4, bit5, bit6, bit7 - * - * Original IBM XT keyboard sends start(0) bit while some of clones don't. - * Start(0) bit is read as low on data line while start(1) as high. - * - * https://github.com/tmk/tmk_keyboard/wiki/IBM-PC-XT-Keyboard-Protocol - */ - static enum { START, BIT0, BIT1, BIT2, BIT3, BIT4, BIT5, BIT6, BIT7 } state = START; - static uint8_t data = 0; - - uint8_t dbit = XT_DATA_READ(); - - // This is needed if using PCINT which can be called on both falling and rising edge - // if (XT_CLOCK_READ()) return; - - switch (state) { - case START: - // ignore start(0) bit - if (!dbit) return; - break; - case BIT0 ... BIT7: - data >>= 1; - if (dbit) data |= 0x80; - break; - } - if (state++ == BIT7) { - pbuf_enqueue(data); - state = START; - data = 0; - } - return; -} - -/*-------------------------------------------------------------------- - * Ring buffer to store scan codes from keyboard - *------------------------------------------------------------------*/ -#define PBUF_SIZE 32 -static uint8_t pbuf[PBUF_SIZE]; -static uint8_t pbuf_head = 0; -static uint8_t pbuf_tail = 0; - -static inline void pbuf_enqueue(uint8_t data) { - uint8_t sreg = SREG; - cli(); - uint8_t next = (pbuf_head + 1) % PBUF_SIZE; - if (next != pbuf_tail) { - pbuf[pbuf_head] = data; - pbuf_head = next; - } else { - dprintf("pbuf: full\n"); - } - SREG = sreg; -} - -static inline uint8_t pbuf_dequeue(void) { - uint8_t val = 0; - - uint8_t sreg = SREG; - cli(); - if (pbuf_head != pbuf_tail) { - val = pbuf[pbuf_tail]; - pbuf_tail = (pbuf_tail + 1) % PBUF_SIZE; - } - SREG = sreg; - - return val; -} - -static inline bool pbuf_has_data(void) { - uint8_t sreg = SREG; - cli(); - bool has_data = (pbuf_head != pbuf_tail); - SREG = sreg; - return has_data; -} - -static inline void pbuf_clear(void) { - uint8_t sreg = SREG; - cli(); - pbuf_head = pbuf_tail = 0; - SREG = sreg; -} |