diff options
Diffstat (limited to 'tmk_core/protocol')
30 files changed, 915 insertions, 551 deletions
diff --git a/tmk_core/protocol/adb.c b/tmk_core/protocol/adb.c index a23c919619..367f1b09fa 100644 --- a/tmk_core/protocol/adb.c +++ b/tmk_core/protocol/adb.c @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun WAKO <wakojun@gmail.com> +Copyright 2011-19 Jun WAKO <wakojun@gmail.com> Copyright 2013 Shay Green <gblargg@gmail.com> This software is licensed with a Modified BSD License. @@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. #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)) @@ -59,7 +60,6 @@ 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); -static inline uint16_t adb_host_dev_recv(uint8_t device); void adb_host_init(void) { ADB_PORT &= ~(1 << ADB_DATA_BIT); @@ -81,119 +81,164 @@ bool adb_host_psw(void) { return psw_in(); } * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> */ - -// 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] - -enum { ADDR_KEYB = 0x20, ADDR_MOUSE = 0x30 }; - -uint16_t adb_host_kbd_recv(void) { return adb_host_dev_recv(ADDR_KEYB); } +uint16_t adb_host_kbd_recv(void) { return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0); } #ifdef ADB_MOUSE_ENABLE -void adb_mouse_init(void) { return; } +__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_dev_recv(ADDR_MOUSE); } +uint16_t adb_host_mouse_recv(void) { return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0); } #endif -static inline uint16_t adb_host_dev_recv(uint8_t device) { - uint16_t data = 0; +// 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(device | 0x0C); // Addr:Keyboard(0010)/Mouse(0011), Cmd:Talk(11), Register0(00) - place_bit0(); // Stopbit(0) + 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 -30; // something wrong + return 0; } if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) sei(); - return 0; // No data to send + 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 = 17; // start bit + 16 data bits + 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; + if (!lo) goto error; // no more bit or after stop bit uint8_t hi = (uint8_t)wait_data_lo(lo); - if (!hi) goto error; + if (!hi) goto error; // stop bit extedned by Srq? - hi = lo - hi; - lo = 130 - lo; + if (n / 8 >= len) continue; // can't store in buf - data <<= 1; - if (lo < hi) { - data |= 1; - } else if (n == 17) { - sei(); - return -20; + buf[n / 8] <<= 1; + if ((130 - lo) < (lo - hi)) { + buf[n / 8] |= 1; } - } while (--n); - - // Stop bit can't be checked normally since it could have service request lenghtening - // and its high state never goes low. - if (!wait_data_hi(351) || wait_data_lo(91)) { - sei(); - return -21; - } - sei(); - return data; + } while (++n); error: sei(); - return -n; + return n / 8; } -void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) { +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(cmd); - place_bit0(); // Stopbit(0) + 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) - send_byte(data_h); - send_byte(data_l); + 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) { - // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10) - // send upper byte (not used) - // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0: - adb_host_listen(0x2A, 0, led & 0x07); + // 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 @@ -327,7 +372,7 @@ Commands bits commands ------------------------------------------------------ - - - - - 0 0 0 0 Send Request(reset all devices) + - - - - 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 @@ -435,5 +480,56 @@ Keyboard LEDs & state of keys(Register2) | +----------------------------- 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 index 34cbcf7691..fe8becc2d5 100644 --- a/tmk_core/protocol/adb.h +++ b/tmk_core/protocol/adb.h @@ -1,5 +1,5 @@ /* -Copyright 2011 Jun WAKO <wakojun@gmail.com> +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, @@ -47,12 +47,60 @@ POSSIBILITY OF SUCH DAMAGE. #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); -void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l); -void adb_host_kbd_led(uint8_t led); -void adb_mouse_task(void); -void adb_mouse_init(void); + +// ADB Mouse +void adb_mouse_task(void); +void adb_mouse_init(void); diff --git a/tmk_core/protocol/arm_atsam/i2c_master.c b/tmk_core/protocol/arm_atsam/i2c_master.c index d3319ab447..dda2f85b00 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.c +++ b/tmk_core/protocol/arm_atsam/i2c_master.c @@ -28,6 +28,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # define I2C_LED_USE_DMA 1 // Set 1 to use background DMA transfers for leds, Set 0 to use inline software transfers +DmacDescriptor dmac_desc; +DmacDescriptor dmac_desc_wb; + static uint8_t i2c_led_q[I2C_Q_SIZE]; // I2C queue circular buffer static uint8_t i2c_led_q_s; // Start of circular buffer static uint8_t i2c_led_q_e; // End of circular buffer diff --git a/tmk_core/protocol/arm_atsam/i2c_master.h b/tmk_core/protocol/arm_atsam/i2c_master.h index 44dbdfbffa..68773f213f 100644 --- a/tmk_core/protocol/arm_atsam/i2c_master.h +++ b/tmk_core/protocol/arm_atsam/i2c_master.h @@ -24,8 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. # include "issi3733_driver.h" # include "config.h" -__attribute__((__aligned__(16))) DmacDescriptor dmac_desc; -__attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb; +extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc; +extern __attribute__((__aligned__(16))) DmacDescriptor dmac_desc_wb; uint8_t I2C3733_Init_Control(void); uint8_t I2C3733_Init_Drivers(void); diff --git a/tmk_core/protocol/arm_atsam/main_arm_atsam.c b/tmk_core/protocol/arm_atsam/main_arm_atsam.c index e10be52fb8..ab5e9a9852 100644 --- a/tmk_core/protocol/arm_atsam/main_arm_atsam.c +++ b/tmk_core/protocol/arm_atsam/main_arm_atsam.c @@ -305,11 +305,5 @@ int main(void) { // dprintf("5v=%u 5vu=%u dlow=%u dhi=%u gca=%u gcd=%u\r\n", v_5v, v_5v_avg, v_5v_avg - V5_LOW, v_5v_avg - V5_HIGH, gcr_actual, gcr_desired); } #endif // CONSOLE_ENABLE - - // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); - } - return 1; } diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c index b337df7627..2b0805dc86 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix.c @@ -15,16 +15,17 @@ 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 "arm_atsam_protocol.h" -#include "tmk_core/common/led.h" -#include "rgb_matrix.h" -#include <string.h> -#include <math.h> - -#ifdef USE_MASSDROP_CONFIGURATOR +#ifdef RGB_MATRIX_ENABLE +# include "arm_atsam_protocol.h" +# include "led.h" +# include "rgb_matrix.h" +# include <string.h> +# include <math.h> + +# ifdef USE_MASSDROP_CONFIGURATOR __attribute__((weak)) led_instruction_t led_instructions[] = {{.end = 1}}; static void md_rgb_matrix_config_override(int i); -#endif // USE_MASSDROP_CONFIGURATOR +# endif // USE_MASSDROP_CONFIGURATOR void SERCOM1_0_Handler(void) { if (SERCOM1->I2CM.INTFLAG.bit.ERROR) { @@ -58,17 +59,17 @@ RGB led_buffer[ISSI3733_LED_COUNT]; uint8_t gcr_desired; uint8_t gcr_actual; uint8_t gcr_actual_last; -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR uint8_t gcr_breathe; float breathe_mult; float pomod; -#endif +# endif -#define ACT_GCR_NONE 0 -#define ACT_GCR_INC 1 -#define ACT_GCR_DEC 2 +# define ACT_GCR_NONE 0 +# define ACT_GCR_INC 1 +# define ACT_GCR_DEC 2 -#define LED_GCR_STEP_AUTO 2 +# define LED_GCR_STEP_AUTO 2 static uint8_t gcr_min_counter; static uint8_t v_5v_cat_hit; @@ -78,11 +79,11 @@ void gcr_compute(void) { uint8_t action = ACT_GCR_NONE; uint8_t gcr_use = gcr_desired; -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR if (led_animation_breathing) { gcr_use = gcr_breathe; } -#endif +# endif // If the 5v takes a catastrophic hit, disable the LED drivers briefly, assert auto gcr mode, min gcr and let the auto take over if (v_5v < V5_CAT) { @@ -150,7 +151,7 @@ void gcr_compute(void) { gcr_actual -= LED_GCR_STEP_AUTO; gcr_min_counter = 0; -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR // If breathe mode is active, the top end can fluctuate if the host can not supply enough current // So set the breathe GCR to where it becomes stable if (led_animation_breathing == 1) { @@ -159,7 +160,7 @@ void gcr_compute(void) { // and the same would happen maybe one or two more times. Therefore I'm favoring // powering through one full breathe and letting gcr settle completely } -#endif +# endif } } } @@ -196,25 +197,25 @@ void md_rgb_matrix_prepare(void) { } } -void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) { +static void led_set_one(int i, uint8_t r, uint8_t g, uint8_t b) { if (i < ISSI3733_LED_COUNT) { -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR md_rgb_matrix_config_override(i); -#else +# else led_buffer[i].r = r; led_buffer[i].g = g; led_buffer[i].b = b; -#endif +# endif } } -void led_set_all(uint8_t r, uint8_t g, uint8_t b) { +static void led_set_all(uint8_t r, uint8_t g, uint8_t b) { for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) { led_set_one(i, r, g, b); } } -void init(void) { +static void init(void) { DBGC(DC_LED_MATRIX_INIT_BEGIN); issi3733_prepare_arrays(); @@ -227,16 +228,16 @@ void init(void) { DBGC(DC_LED_MATRIX_INIT_COMPLETE); } -void flush(void) { -#ifdef USE_MASSDROP_CONFIGURATOR +static void flush(void) { +# ifdef USE_MASSDROP_CONFIGURATOR if (!led_enabled) { return; } // Prevent calculations and I2C traffic if LED drivers are not enabled -#else +# else if (!sr_exp_data.bit.SDB_N) { return; } // Prevent calculations and I2C traffic if LED drivers are not enabled -#endif +# endif // Wait for previous transfer to complete while (i2c_led_q_running) { @@ -249,7 +250,7 @@ void flush(void) { *led_map[i].rgb.b = led_buffer[i].b; } -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR breathe_mult = 1; if (led_animation_breathing) { @@ -275,7 +276,7 @@ void flush(void) { pomod = (uint32_t)pomod % 10000; pomod /= 100.0f; -#endif // USE_MASSDROP_CONFIGURATOR +# endif // USE_MASSDROP_CONFIGURATOR uint8_t drvid; @@ -295,25 +296,27 @@ void md_rgb_matrix_indicators(void) { if (kbled && rgb_matrix_config.enable) { for (uint8_t i = 0; i < ISSI3733_LED_COUNT; i++) { if ( -#if USB_LED_NUM_LOCK_SCANCODE != 255 +# if USB_LED_NUM_LOCK_SCANCODE != 255 (led_map[i].scan == USB_LED_NUM_LOCK_SCANCODE && (kbled & (1 << USB_LED_NUM_LOCK))) || -#endif // NUM LOCK -#if USB_LED_CAPS_LOCK_SCANCODE != 255 +# endif // NUM LOCK +# if USB_LED_CAPS_LOCK_SCANCODE != 255 (led_map[i].scan == USB_LED_CAPS_LOCK_SCANCODE && (kbled & (1 << USB_LED_CAPS_LOCK))) || -#endif // CAPS LOCK -#if USB_LED_SCROLL_LOCK_SCANCODE != 255 +# endif // CAPS LOCK +# if USB_LED_SCROLL_LOCK_SCANCODE != 255 (led_map[i].scan == USB_LED_SCROLL_LOCK_SCANCODE && (kbled & (1 << USB_LED_SCROLL_LOCK))) || -#endif // SCROLL LOCK -#if USB_LED_COMPOSE_SCANCODE != 255 +# endif // SCROLL LOCK +# if USB_LED_COMPOSE_SCANCODE != 255 (led_map[i].scan == USB_LED_COMPOSE_SCANCODE && (kbled & (1 << USB_LED_COMPOSE))) || -#endif // COMPOSE -#if USB_LED_KANA_SCANCODE != 255 +# endif // COMPOSE +# if USB_LED_KANA_SCANCODE != 255 (led_map[i].scan == USB_LED_KANA_SCANCODE && (kbled & (1 << USB_LED_KANA))) || -#endif // KANA +# endif // KANA (0)) { - led_buffer[i].r = 255 - led_buffer[i].r; - led_buffer[i].g = 255 - led_buffer[i].g; - led_buffer[i].b = 255 - led_buffer[i].b; + if (rgb_matrix_get_flags() & LED_FLAG_INDICATOR) { + led_buffer[i].r = 255 - led_buffer[i].r; + led_buffer[i].g = 255 - led_buffer[i].g; + led_buffer[i].b = 255 - led_buffer[i].b; + } } } } @@ -325,7 +328,7 @@ const rgb_matrix_driver_t rgb_matrix_driver = {.init = init, .flush = flush, .se = Legacy Lighting Support = ==============================================================================*/ -#ifdef USE_MASSDROP_CONFIGURATOR +# ifdef USE_MASSDROP_CONFIGURATOR // Ported from Massdrop QMK GitHub Repo // TODO?: wire these up to keymap.c @@ -467,4 +470,5 @@ static void md_rgb_matrix_config_override(int i) { led_buffer[i].b = (uint8_t)bo; } -#endif // USE_MASSDROP_CONFIGURATOR +# endif // USE_MASSDROP_CONFIGURATOR +#endif // RGB_MATRIX_ENABLE diff --git a/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c b/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c index b43008cc5b..fce225a6c4 100644 --- a/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c +++ b/tmk_core/protocol/arm_atsam/md_rgb_matrix_programs.c @@ -15,9 +15,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef USE_MASSDROP_CONFIGURATOR +#ifdef RGB_MATRIX_ENABLE +# ifdef USE_MASSDROP_CONFIGURATOR -# include "md_rgb_matrix.h" +# include "md_rgb_matrix.h" // Teal <-> Salmon led_setup_t leds_teal_salmon[] = { @@ -96,4 +97,5 @@ void *led_setups[] = {leds_rainbow_s, leds_rainbow_ns, leds_teal_salmon, leds_ye const uint8_t led_setups_count = sizeof(led_setups) / sizeof(led_setups[0]); -#endif +# endif // USE_MASSDROP_CONFIGURATOR +#endif // RGB_MATRIX_ENABLE diff --git a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c index e3fa65574e..9ea4addcfc 100644 --- a/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c +++ b/tmk_core/protocol/arm_atsam/usb/udi_hid_kbd.c @@ -374,39 +374,33 @@ static uint8_t udi_hid_exk_report_trans[UDI_HID_EXK_REPORT_SIZE]; COMPILER_WORD_ALIGNED UDC_DESC_STORAGE udi_hid_exk_report_desc_t udi_hid_exk_report_desc = {{ + // clang-format off 0x05, 0x01, // Usage Page (Generic Desktop) 0x09, 0x80, // Usage (System Control) 0xA1, 0x01, // Collection (Application) 0x85, REPORT_ID_SYSTEM, // Report ID - 0x1A, 0x81, - 0x00, // Usage Minimum (81) (System Power Down) - 0x2A, 0x83, - 0x00, // Usage Maximum (83) (System Wake Up) - 0x16, 0x01, - 0x00, // Logical Minimum (1) - 0x26, 0x03, - 0x00, // Logical Maximum (3) - 0x95, 0x01, // Report Count (1) - 0x75, 0x10, // Report Size (16) - 0x81, 0x00, // Input (Data, Array, Absolute) - 0xC0, // End Collection + 0x19, 0x01, // Usage Minimum (Pointer) + 0x2A, 0xB7, 0x00, // Usage Maximum (System Display LCD Autoscale) + 0x15, 0x01, // Logical Minimum + 0x26, 0xB7, 0x00, // Logical Maximum + 0x95, 0x01, // Report Count (1) + 0x75, 0x10, // Report Size (16) + 0x81, 0x00, // Input (Data, Array, Absolute) + 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, REPORT_ID_CONSUMER, // Report ID - 0x1A, 0x01, - 0x00, // Usage Minimum (Consumer Control) - 0x2A, 0x9C, - 0x02, // Usage Maximum (AC Distribute Vertically) - 0x16, 0x01, - 0x00, // Logical Minimum - 0x26, 0x9C, - 0x02, // Logical Maximum - 0x95, 0x01, // Report Count (1) - 0x75, 0x10, // Report Size (16) - 0x81, 0x00, // Input (Data, Array, Absolute) - 0xC0 // End Collection + 0x19, 0x01, // Usage Minimum (Consumer Control) + 0x2A, 0xA0, 0x02, // Usage Maximum (AC Desktop Show All Applications) + 0x15, 0x01, // Logical Minimum + 0x26, 0xA0, 0x02, // Logical Maximum + 0x95, 0x01, // Report Count (1) + 0x75, 0x10, // Report Size (16) + 0x81, 0x00, // Input (Data, Array, Absolute) + 0xC0 // End Collection + //clang-format on }}; static bool udi_hid_exk_setreport(void); diff --git a/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h b/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h index 2f8a39bdd8..fb97f63cef 100644 --- a/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h +++ b/tmk_core/protocol/arm_atsam/usb/usb_protocol_hid.h @@ -186,9 +186,10 @@ COMPILER_PACK_RESET() #define USB_HID_COUNTRY_UK 32 // UK #define USB_HID_COUNTRY_US 33 // US #define USB_HID_COUNTRY_YUGOSLAVIA 34 // Yugoslavia -#define USB_HID_COUNTRY_TURKISH_F 35 // Turkish-F - //! @} - //! @} +#define USB_HID_COUNTRY_TURKISH_F \ + 35 // Turkish-F + //! @} + //! @} //! @} //! \name HID KEYS values diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index 5c27a8c6a0..6cd88be577 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -167,6 +167,7 @@ int main(void) { keyboard_setup(); /* Init USB */ + usb_event_queue_init(); init_usb_driver(&USB_DRIVER); #ifdef MIDI_ENABLE @@ -225,6 +226,8 @@ int main(void) { /* Main loop */ while (true) { + usb_event_queue_task(); + #if !defined(NO_USB_STARTUP_CHECK) if (USB_DRIVER.state == USB_SUSPENDED) { print("[s]"); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index 67ae8520fd..990dc1b91c 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -27,6 +27,7 @@ #include <ch.h> #include <hal.h> +#include <string.h> #include "usb_main.h" @@ -50,6 +51,7 @@ extern keymap_config_t keymap_config; #ifdef WEBUSB_ENABLE # include "webusb.h" #endif + #ifdef JOYSTICK_ENABLE # include "joystick.h" #endif @@ -168,6 +170,7 @@ static const USBEndpointConfig shared_ep_config = { }; #endif + #ifdef WEBUSB_ENABLE /** Microsoft OS 2.0 Descriptor. This is used by Windows to select the USB driver for the device. * @@ -397,6 +400,69 @@ static usb_driver_configs_t drivers = { * --------------------------------------------------------- */ +#define USB_EVENT_QUEUE_SIZE 16 +usbevent_t event_queue[USB_EVENT_QUEUE_SIZE]; +uint8_t event_queue_head; +uint8_t event_queue_tail; + +void usb_event_queue_init(void) { + // Initialise the event queue + memset(&event_queue, 0, sizeof(event_queue)); + event_queue_head = 0; + event_queue_tail = 0; +} + +static inline bool usb_event_queue_enqueue(usbevent_t event) { + uint8_t next = (event_queue_head + 1) % USB_EVENT_QUEUE_SIZE; + if (next == event_queue_tail) { + return false; + } + event_queue[event_queue_head] = event; + event_queue_head = next; + return true; +} + +static inline bool usb_event_queue_dequeue(usbevent_t *event) { + if (event_queue_head == event_queue_tail) { + return false; + } + *event = event_queue[event_queue_tail]; + event_queue_tail = (event_queue_tail + 1) % USB_EVENT_QUEUE_SIZE; + return true; +} + +static inline void usb_event_suspend_handler(void) { +#ifdef SLEEP_LED_ENABLE + sleep_led_enable(); +#endif /* SLEEP_LED_ENABLE */ +} + +static inline void usb_event_wakeup_handler(void) { + suspend_wakeup_init(); +#ifdef SLEEP_LED_ENABLE + sleep_led_disable(); + // NOTE: converters may not accept this + led_set(host_keyboard_leds()); +#endif /* SLEEP_LED_ENABLE */ +} + +void usb_event_queue_task(void) { + usbevent_t event; + while (usb_event_queue_dequeue(&event)) { + switch (event) { + case USB_EVENT_SUSPEND: + usb_event_suspend_handler(); + break; + case USB_EVENT_WAKEUP: + usb_event_wakeup_handler(); + break; + default: + // Nothing to do, we don't handle it. + break; + } + } +} + /* Handles the USB driver global events * TODO: maybe disable some things when connection is lost? */ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { @@ -431,9 +497,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { osalSysUnlockFromISR(); return; case USB_EVENT_SUSPEND: -#ifdef SLEEP_LED_ENABLE - sleep_led_enable(); -#endif /* SLEEP_LED_ENABLE */ + usb_event_queue_enqueue(USB_EVENT_SUSPEND); /* Falls into.*/ case USB_EVENT_UNCONFIGURED: /* Falls into.*/ @@ -454,12 +518,7 @@ static void usb_event_cb(USBDriver *usbp, usbevent_t event) { qmkusbWakeupHookI(&drivers.array[i].driver); chSysUnlockFromISR(); } - suspend_wakeup_init(); -#ifdef SLEEP_LED_ENABLE - sleep_led_disable(); - // NOTE: converters may not accept this - led_set(host_keyboard_leds()); -#endif /* SLEEP_LED_ENABLE */ + usb_event_queue_enqueue(USB_EVENT_WAKEUP); return; case USB_EVENT_STALLED: @@ -575,7 +634,7 @@ static bool usb_request_hook_cb(USBDriver *usbp) { if (!keymap_config.nkro && keyboard_idle) { #else /* NKRO_ENABLE */ if (keyboard_idle) { -#endif /* NKRO_ENABLE */ +#endif /* NKRO_ENABLE */ /* arm the idle timer if boot protocol & idle */ osalSysLockFromISR(); chVTSetI(&keyboard_idle_timer, 4 * TIME_MS2I(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp); @@ -867,7 +926,7 @@ void send_mouse(report_mouse_t *report) { } #else /* MOUSE_ENABLE */ -void send_mouse(report_mouse_t *report) { (void)report; } +void send_mouse(report_mouse_t *report) { (void)report; } #endif /* MOUSE_ENABLE */ /* --------------------------------------------------------- @@ -923,9 +982,32 @@ void send_consumer(uint16_t data) { #ifdef CONSOLE_ENABLE int8_t sendchar(uint8_t c) { - // The previous implmentation had timeouts, but I think it's better to just slow down - // and make sure that everything is transferred, rather than dropping stuff - return chnWrite(&drivers.console_driver.driver, &c, 1); + static bool timed_out = false; + /* The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state. + * + * When a 5ms timeout write has timed out, hid_listen is most likely not running, or not + * listening to this keyboard, so we go into the timed_out state. In this state we assume + * that hid_listen is most likely not gonna be connected to us any time soon, so it would + * be wasteful to write follow-up characters with a 5ms timeout, it would all add up and + * unncecessarily slow down the firmware. However instead of just dropping the characters, + * we write them with a TIME_IMMEDIATE timeout, which is a zero timeout, + * and this will succeed only if hid_listen gets connected again. When a write with + * TIME_IMMEDIATE timeout succeeds, we know that hid_listen is listening to us again, and + * we can go back to the timed_out = false state, and following writes will be executed + * with a 5ms timeout. The reason we don't just send all characters with the TIME_IMMEDIATE + * timeout is that this could cause bytes to be lost even if hid_listen is running, if there + * is a lot of data being sent over the console. + * + * This logic will work correctly as long as hid_listen is able to receive at least 200 + * bytes per second. On a heavily overloaded machine that's so overloaded that it's + * unusable, and constantly swapping, hid_listen might have trouble receiving 200 bytes per + * second, so some bytes might be lost on the console. + */ + + const sysinterval_t timeout = timed_out ? TIME_IMMEDIATE : TIME_MS2I(5); + const size_t result = chnWriteTimeout(&drivers.console_driver.driver, &c, 1, timeout); + timed_out = (result == 0); + return result; } // Just a dummy function for now, this could be exposed as a weak function @@ -946,15 +1028,8 @@ void console_task(void) { } while (size > 0); } -#else /* CONSOLE_ENABLE */ -int8_t sendchar(uint8_t c) { - (void)c; - return 0; -} #endif /* CONSOLE_ENABLE */ -void _putchar(char character) { sendchar(character); } - #ifdef RAW_ENABLE void raw_hid_send(uint8_t *data, uint8_t length) { // TODO: implement variable size packet diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h index eaa08d8f79..fb33c8cd0f 100644 --- a/tmk_core/protocol/chibios/usb_main.h +++ b/tmk_core/protocol/chibios/usb_main.h @@ -38,6 +38,17 @@ void init_usb_driver(USBDriver *usbp); void restart_usb_driver(USBDriver *usbp); /* --------------- + * USB Event queue + * --------------- + */ + +/* Initialisation of the FIFO */ +void usb_event_queue_init(void); + +/* Task to dequeue and execute any handlers for the USB events on the main thread */ +void usb_event_queue_task(void); + +/* --------------- * Keyboard header * --------------- */ diff --git a/tmk_core/protocol/lufa/lufa.c b/tmk_core/protocol/lufa/lufa.c index 1d019d1695..b1af36d113 100644 --- a/tmk_core/protocol/lufa/lufa.c +++ b/tmk_core/protocol/lufa/lufa.c @@ -782,9 +782,7 @@ static void send_keyboard(report_keyboard_t *report) { uint8_t timeout = 255; #ifdef BLUETOOTH_ENABLE - uint8_t where = where_to_send(); - - if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { + if (where_to_send() == OUTPUT_BLUETOOTH) { # ifdef MODULE_ADAFRUIT_BLE adafruit_ble_send_keys(report->mods, report->keys, sizeof(report->keys)); # elif MODULE_RN42 @@ -797,9 +795,6 @@ static void send_keyboard(report_keyboard_t *report) { serial_send(report->keys[i]); } # endif - } - - if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { return; } #endif @@ -840,9 +835,7 @@ static void send_mouse(report_mouse_t *report) { uint8_t timeout = 255; # ifdef BLUETOOTH_ENABLE - uint8_t where = where_to_send(); - - if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { + if (where_to_send() == OUTPUT_BLUETOOTH) { # ifdef MODULE_ADAFRUIT_BLE // FIXME: mouse buttons adafruit_ble_send_mouse_move(report->x, report->y, report->v, report->h, report->buttons); @@ -857,9 +850,6 @@ static void send_mouse(report_mouse_t *report) { serial_send(report->h); // should try sending the wheel h here serial_send(0x00); # endif - } - - if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { return; } # endif @@ -918,9 +908,13 @@ static void send_system(uint16_t data) { static void send_consumer(uint16_t data) { #ifdef EXTRAKEY_ENABLE # ifdef BLUETOOTH_ENABLE +<<<<<<< HEAD uint8_t where = where_to_send(); if (where == OUTPUT_BLUETOOTH || where == OUTPUT_USB_AND_BT) { +======= + if (where_to_send() == OUTPUT_BLUETOOTH) { +>>>>>>> 0.12.52~1 # ifdef MODULE_ADAFRUIT_BLE adafruit_ble_send_consumer_key(data); # elif MODULE_RN42 @@ -934,9 +928,12 @@ static void send_consumer(uint16_t data) { serial_send(bitmap & 0xFF); serial_send((bitmap >> 8) & 0xFF); # endif +<<<<<<< HEAD } if (where != OUTPUT_USB && where != OUTPUT_USB_AND_BT) { +======= +>>>>>>> 0.12.52~1 return; } # endif @@ -955,9 +952,14 @@ static void send_consumer(uint16_t data) { * FIXME: Needs doc */ int8_t sendchar(uint8_t c) { +<<<<<<< HEAD // Not wait once timeouted. +======= + // Do not wait if the previous write has timed_out. +>>>>>>> 0.12.52~1 // Because sendchar() is called so many times, waiting each call causes big lag. - static bool timeouted = false; + // The `timed_out` state is an approximation of the ideal `is_listener_disconnected?` state. + static bool timed_out = false; // prevents Console_Task() from running during sendchar() runs. // or char will be lost. These two function is mutually exclusive. @@ -971,11 +973,11 @@ int8_t sendchar(uint8_t c) { goto ERROR_EXIT; } - if (timeouted && !Endpoint_IsReadWriteAllowed()) { + if (timed_out && !Endpoint_IsReadWriteAllowed()) { goto ERROR_EXIT; } - timeouted = false; + timed_out = false; uint8_t timeout = SEND_TIMEOUT; while (!Endpoint_IsReadWriteAllowed()) { @@ -986,7 +988,7 @@ int8_t sendchar(uint8_t c) { goto ERROR_EXIT; } if (!(timeout--)) { - timeouted = true; + timed_out = true; goto ERROR_EXIT; } _delay_ms(1); @@ -1136,7 +1138,6 @@ static void setup_usb(void) { // for Console_Task USB_Device_EnableSOFEvents(); - print_set_sendchar(sendchar); } /** \brief Main diff --git a/tmk_core/protocol/lufa/outputselect.h b/tmk_core/protocol/lufa/outputselect.h index 7f7ed00b95..c4548e1122 100644 --- a/tmk_core/protocol/lufa/outputselect.h +++ b/tmk_core/protocol/lufa/outputselect.h @@ -21,21 +21,11 @@ enum outputs { OUTPUT_NONE, OUTPUT_USB, - OUTPUT_BLUETOOTH, - - // backward compatibility - OUTPUT_USB_AND_BT + OUTPUT_BLUETOOTH }; -/** - * backward compatibility for BLUETOOTH_ENABLE, send to BT and USB by default - */ #ifndef OUTPUT_DEFAULT -# ifdef BLUETOOTH_ENABLE -# define OUTPUT_DEFAULT OUTPUT_USB_AND_BT -# else -# define OUTPUT_DEFAULT OUTPUT_AUTO -# endif +# define OUTPUT_DEFAULT OUTPUT_AUTO #endif void set_output(uint8_t output); diff --git a/tmk_core/protocol/m0110.c b/tmk_core/protocol/m0110.c index b02a6933d2..64f2fa50ab 100644 --- a/tmk_core/protocol/m0110.c +++ b/tmk_core/protocol/m0110.c @@ -95,11 +95,11 @@ void m0110_init(void) { uint8_t data; m0110_send(M0110_MODEL); data = m0110_recv(); - print("m0110_init model: "); phex(data); print("\n"); + print("m0110_init model: "); print_hex8(data); print("\n"); m0110_send(M0110_TEST); data = m0110_recv(); - print("m0110_init test: "); phex(data); print("\n"); + print("m0110_init test: "); print_hex8(data); print("\n"); */ } @@ -122,7 +122,7 @@ uint8_t m0110_send(uint8_t data) { return 1; ERROR: print("m0110_send err: "); - phex(m0110_error); + print_hex8(m0110_error); print("\n"); _delay_ms(500); idle(); @@ -146,7 +146,7 @@ uint8_t m0110_recv(void) { return data; ERROR: print("m0110_recv err: "); - phex(m0110_error); + print_hex8(m0110_error); print("\n"); _delay_ms(500); idle(); diff --git a/tmk_core/protocol/midi/qmk_midi.c b/tmk_core/protocol/midi/qmk_midi.c index 6f6aced725..c18dbf9930 100644 --- a/tmk_core/protocol/midi/qmk_midi.c +++ b/tmk_core/protocol/midi/qmk_midi.c @@ -5,7 +5,7 @@ #include "usb_descriptor.h" #include "process_midi.h" #if API_SYSEX_ENABLE -# include "api.h" +# include "api_sysex.h" #endif /******************************************************************************* diff --git a/tmk_core/protocol/ps2_mouse.c b/tmk_core/protocol/ps2_mouse.c index 8df465026b..5415453a05 100644 --- a/tmk_core/protocol/ps2_mouse.c +++ b/tmk_core/protocol/ps2_mouse.c @@ -190,7 +190,7 @@ static inline void ps2_mouse_clear_report(report_mouse_t *mouse_report) { static inline void ps2_mouse_print_report(report_mouse_t *mouse_report) { if (!debug_mouse) return; print("ps2_mouse: ["); - phex(mouse_report->buttons); + print_hex8(mouse_report->buttons); print("|"); print_hex8((uint8_t)mouse_report->x); print(" "); diff --git a/tmk_core/protocol/serial.h b/tmk_core/protocol/serial.h index b70d117d7c..0204b84a92 100644 --- a/tmk_core/protocol/serial.h +++ b/tmk_core/protocol/serial.h @@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE. #pragma once +#define SERIAL_UART_DATA UDR1 + /* host role */ void serial_init(void); uint8_t serial_recv(void); diff --git a/tmk_core/protocol/serial_uart.c b/tmk_core/protocol/serial_uart.c index a15124193a..d5b5657095 100644 --- a/tmk_core/protocol/serial_uart.c +++ b/tmk_core/protocol/serial_uart.c @@ -40,6 +40,22 @@ POSSIBILITY OF SUCH DAMAGE. #include <avr/interrupt.h> #include "serial.h" +#ifndef SERIAL_UART_BAUD +# define SERIAL_UART_BAUD 9600 +#endif + +#define SERIAL_UART_UBRR (F_CPU / (16UL * SERIAL_UART_BAUD) - 1) +#define SERIAL_UART_TXD_READY (UCSR1A & _BV(UDRE1)) +#define SERIAL_UART_RXD_VECT USART1_RX_vect + +#ifndef SERIAL_UART_INIT_CUSTOM +# define SERIAL_UART_INIT_CUSTOM \ + /* enable TX */ \ + UCSR1B = _BV(TXEN1); \ + /* 8-bit data */ \ + UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); +#endif + #if defined(SERIAL_UART_RTS_LO) && defined(SERIAL_UART_RTS_HI) // Buffer state // Empty: RBUF_SPACE == RBUF_SIZE(head==tail) @@ -61,7 +77,14 @@ POSSIBILITY OF SUCH DAMAGE. # define rbuf_check_rts_hi() #endif -void serial_init(void) { SERIAL_UART_INIT(); } +void serial_init(void) { + do { + // Set baud rate + UBRR1L = SERIAL_UART_UBRR; + UBRR1L = SERIAL_UART_UBRR >> 8; + SERIAL_UART_INIT_CUSTOM; + } while (0); +} // RX ring buffer #define RBUF_SIZE 256 diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c index 4a5edb1907..9277554856 100644 --- a/tmk_core/protocol/usb_descriptor.c +++ b/tmk_core/protocol/usb_descriptor.c @@ -40,7 +40,7 @@ #include "report.h" #include "usb_descriptor.h" #ifdef WEBUSB_ENABLE -#include "webusb_descriptor.h" +# include "webusb_descriptor.h" #endif #include "usb_descriptor_common.h" @@ -119,19 +119,15 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM SharedReport[] = { # endif HID_RI_USAGE(8, 0x01), // Pointer HID_RI_COLLECTION(8, 0x00), // Physical - // Buttons (5 bits) + // Buttons (8 bits) HID_RI_USAGE_PAGE(8, 0x09), // Button HID_RI_USAGE_MINIMUM(8, 0x01), // Button 1 - HID_RI_USAGE_MAXIMUM(8, 0x05), // Button 5 + HID_RI_USAGE_MAXIMUM(8, 0x08), // Button 8 HID_RI_LOGICAL_MINIMUM(8, 0x00), HID_RI_LOGICAL_MAXIMUM(8, 0x01), - HID_RI_REPORT_COUNT(8, 0x05), + HID_RI_REPORT_COUNT(8, 0x08), HID_RI_REPORT_SIZE(8, 0x01), HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE), - // Button padding (3 bits) - HID_RI_REPORT_COUNT(8, 0x01), - HID_RI_REPORT_SIZE(8, 0x03), - HID_RI_INPUT(8, HID_IOF_CONSTANT), // X/Y position (2 bytes) HID_RI_USAGE_PAGE(8, 0x01), // Generic Desktop @@ -288,8 +284,8 @@ const USB_Descriptor_HIDReport_Datatype_t PROGMEM ConsoleReport[] = { #ifdef WEBUSB_ENABLE const USB_Descriptor_BOS_t PROGMEM BOSDescriptor = BOS_DESCRIPTOR( - (MS_OS_20_PLATFORM_DESCRIPTOR(MS_OS_20_VENDOR_CODE, MS_OS_20_DESCRIPTOR_SET_TOTAL_LENGTH)) - (WEBUSB_PLATFORM_DESCRIPTOR(WEBUSB_VENDOR_CODE, WEBUSB_LANDING_PAGE_INDEX)) + (MS_OS_20_PLATFORM_DESCRIPTOR(MS_OS_20_VENDOR_CODE, MS_OS_20_DESCRIPTOR_SET_TOTAL_LENGTH)) + (WEBUSB_PLATFORM_DESCRIPTOR(WEBUSB_VENDOR_CODE, WEBUSB_LANDING_PAGE_INDEX)) ); #endif #ifdef JOYSTICK_ENABLE @@ -369,6 +365,7 @@ const USB_Descriptor_Device_t PROGMEM DeviceDescriptor = { #else .USBSpecification = VERSION_BCD(1, 1, 0), #endif + #if VIRTSER_ENABLE .Class = USB_CSCP_IADDeviceClass, .SubClass = USB_CSCP_IADDeviceSubclass, diff --git a/tmk_core/protocol/usb_descriptor.h b/tmk_core/protocol/usb_descriptor.h index e4d5435110..2ea4861f36 100644 --- a/tmk_core/protocol/usb_descriptor.h +++ b/tmk_core/protocol/usb_descriptor.h @@ -49,7 +49,7 @@ # include <hal.h> #endif #ifdef WEBUSB_ENABLE -#include "webusb_descriptor.h" +# include "webusb_descriptor.h" #endif /* @@ -271,6 +271,7 @@ enum usb_endpoints { # define WEBUSB_IN_EPADDR (ENDPOINT_DIR_IN | WEBUSB_IN_EPNUM) # define WEBUSB_OUT_EPADDR (ENDPOINT_DIR_OUT | WEBUSB_OUT_EPNUM) #endif + #ifdef JOYSTICK_ENABLE JOYSTICK_IN_EPNUM = NEXT_EPNUM, # if STM32_USB_USE_OTG1 diff --git a/tmk_core/protocol/usb_hid/test/Makefile b/tmk_core/protocol/usb_hid/test/Makefile deleted file mode 100644 index 83bf2aed67..0000000000 --- a/tmk_core/protocol/usb_hid/test/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -#---------------------------------------------------------------------------- -# On command line: -# -# make all = Make software. -# -# make clean = Clean out built project files. -# -# make coff = Convert ELF to AVR COFF. -# -# make extcoff = Convert ELF to AVR Extended COFF. -# -# make program = Download the hex file to the device. -# Please customize your programmer settings(PROGRAM_CMD) -# -# make teensy = Download the hex file to the device, using teensy_loader_cli. -# (must have teensy_loader_cli installed). -# -# make dfu = Download the hex file to the device, using dfu-programmer (must -# have dfu-programmer installed). -# -# make flip = Download the hex file to the device, using Atmel FLIP (must -# have Atmel FLIP installed). -# -# make dfu-ee = Download the eeprom file to the device, using dfu-programmer -# (must have dfu-programmer installed). -# -# make flip-ee = Download the eeprom file to the device, using Atmel FLIP -# (must have Atmel FLIP installed). -# -# make debug = Start either simulavr or avarice as specified for debugging, -# with avr-gdb or avr-insight as the front end for debugging. -# -# make filename.s = Just compile filename.c into the assembler code only. -# -# make filename.i = Create a preprocessed source file for use in submitting -# bug reports to the GCC project. -# -# To rebuild project do "make clean" then "make all". -#---------------------------------------------------------------------------- - -# Target file name (without extension). -TARGET = usb_hid_test - -TMK_DIR = ../../.. - -# Directory keyboard dependent files exist -TARGET_DIR = . - -# MCU name -MCU = atmega32u4 - - -# Processor frequency. -# This will define a symbol, F_CPU, in all source code files equal to the -# processor frequency in Hz. You can then use this symbol in your source code to -# calculate timings. Do NOT tack on a 'UL' at the end, this will be done -# automatically to create a 32-bit value in your source code. -# -# This will be an integer division of F_USB below, as it is sourced by -# F_USB after it has run through any CPU prescalers. Note that this value -# does not *change* the processor frequency - it should merely be updated to -# reflect the processor speed set externally so that the code can use accurate -# software delays. -F_CPU = 16000000 - - - -# -# LUFA specific -# -# Target architecture (see library "Board Types" documentation). -ARCH = AVR8 -# Input clock frequency. -# This will define a symbol, F_USB, in all source code files equal to the -# input clock frequency (before any prescaling is performed) in Hz. This value may -# differ from F_CPU if prescaling is used on the latter, and is required as the -# raw input clock is fed directly to the PLL sections of the AVR for high speed -# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL' -# at the end, this will be done automatically to create a 32-bit value in your -# source code. -# -# If no clock division is performed on the input clock inside the AVR (via the -# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU. -F_USB = $(F_CPU) -# Interrupt driven control endpoint task -OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT - - - -# Build Options -# comment out to disable the options. -# -# Console for debug -OPT_DEFS += -DCONSOLE_ENABLE - -# Boot Section Size in bytes -# Teensy halfKay 512 -# Atmel DFU loader 4096 -# LUFA bootloader 4096 -#OPT_DEFS += -DBOOT_SIZE=4096 - - - -SRC = test.cpp -SRC += common/debug.c -SRC += common/print.c - -CONFIG_H = config.h - - - -# Search Path -VPATH += $(TARGET_DIR) -VPATH += $(TMK_DIR) -VPATH += $(TMK_DIR)/common - - - -# program Leonardo -PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -P$(DEV) -b57600 -Uflash:w:$(TARGET).hex - - - -include $(TMK_DIR)/protocol/usb_hid.mk -include $(TMK_DIR)/protocol/lufa.mk -include $(TMK_DIR)/rules.mk diff --git a/tmk_core/protocol/usb_hid/test/config.h b/tmk_core/protocol/usb_hid/test/config.h deleted file mode 100644 index 71a6814fd1..0000000000 --- a/tmk_core/protocol/usb_hid/test/config.h +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright 2012 Jun Wako <wakojun@gmail.com> - -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 - -#define VENDOR_ID 0xFEED -#define PRODUCT_ID 0xCAFE -#define DEVICE_VER 0x0814 -#define MANUFACTURER t.m.k. -#define PRODUCT USB to USB keyboard converter - -#define DESCRIPTION Product from t.m.k. keyboard firmware project - -/* matrix size */ -#define MATRIX_ROWS 32 -#define MATRIX_COLS 8 diff --git a/tmk_core/protocol/usb_hid/test/test.cpp b/tmk_core/protocol/usb_hid/test/test.cpp deleted file mode 100644 index 4958f0c619..0000000000 --- a/tmk_core/protocol/usb_hid/test/test.cpp +++ /dev/null @@ -1,92 +0,0 @@ -#include <avr/io.h> -#include <avr/wdt.h> -#include <avr/power.h> -#include <util/delay.h> -#include <Arduino.h> - -// USB HID host -#include "Usb.h" -#include "hid.h" -#include "hidboot.h" -#include "parser.h" - -// LUFA -#include "lufa.h" - -#include "debug.h" - -#include "leonardo_led.h" - - -static USB usb_host; -static HIDBoot<HID_PROTOCOL_KEYBOARD> kbd(&usb_host); -static KBDReportParser kbd_parser; - -static void LUFA_setup(void) -{ - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - /* Disable clock division */ - clock_prescale_set(clock_div_1); - - // Leonardo needs. Without this USB device is not recognized. - USB_Disable(); - - USB_Init(); - - // for Console_Task - USB_Device_EnableSOFEvents(); -} - -static void HID_setup() -{ - // Arduino Timer startup: wiring.c - init(); - - if (usb_host.Init() == -1) { - debug("HID init: failed\n"); - LED_TX_OFF; - } - - _delay_ms(200); - - kbd.SetReportParser(0, (HIDReportParser*)&kbd_parser); -} - -int main(void) -{ - // LED for debug - LED_TX_INIT; - LED_TX_ON; - - print_enable = true; - debug_enable = true; - debug_matrix = true; - debug_keyboard = true; - debug_mouse = true; - - LUFA_setup(); - sei(); - - // wait for startup of sendchar routine - while (USB_DeviceState != DEVICE_STATE_Configured) ; - if (debug_enable) { - _delay_ms(1000); - } - - HID_setup(); - - debug("init: done\n"); - for (;;) { - usb_host.Task(); - -#if !defined(INTERRUPT_CONTROL_ENDPOINT) - // LUFA Task for control request - USB_USBTask(); -#endif - } - - return 0; -} diff --git a/tmk_core/protocol/vusb/main.c b/tmk_core/protocol/vusb/main.c index 2e8bb2fbbc..53926a7493 100644 --- a/tmk_core/protocol/vusb/main.c +++ b/tmk_core/protocol/vusb/main.c @@ -53,10 +53,10 @@ static void initForUsbConnectivity(void) { usbDeviceConnect(); } -static void usb_remote_wakeup(void) { +static void vusb_send_remote_wakeup(void) { cli(); - int8_t ddr_orig = USBDDR; + uint8_t ddr_orig = USBDDR; USBOUT |= (1 << USBMINUS); USBDDR = ddr_orig | USBMASK; USBOUT ^= USBMASK; @@ -70,16 +70,34 @@ static void usb_remote_wakeup(void) { sei(); } +bool vusb_suspended = false; + +static void vusb_suspend(void) { + vusb_suspended = true; + +#ifdef SLEEP_LED_ENABLE + sleep_led_enable(); +#endif + + suspend_power_down(); +} + +#if USB_COUNT_SOF +static void vusb_wakeup(void) { + vusb_suspended = false; + suspend_wakeup_init(); + +# ifdef SLEEP_LED_ENABLE + sleep_led_disable(); +# endif +} +#endif + /** \brief Setup USB * * FIXME: Needs doc */ -static void setup_usb(void) { - initForUsbConnectivity(); - - // for Console_Task - print_set_sendchar(sendchar); -} +static void setup_usb(void) { initForUsbConnectivity(); } /** \brief Main * @@ -87,9 +105,8 @@ static void setup_usb(void) { */ int main(void) __attribute__((weak)); int main(void) { - bool suspended = false; #if USB_COUNT_SOF - uint16_t last_timer = timer_read(); + uint16_t sof_timer = timer_read(); #endif #ifdef CLKPR @@ -112,23 +129,24 @@ int main(void) { while (1) { #if USB_COUNT_SOF if (usbSofCount != 0) { - suspended = false; usbSofCount = 0; - last_timer = timer_read(); -# ifdef SLEEP_LED_ENABLE - sleep_led_disable(); -# endif + sof_timer = timer_read(); + if (vusb_suspended) { + vusb_wakeup(); + } } else { // Suspend when no SOF in 3ms-10ms(7.1.7.4 Suspending of USB1.1) - if (timer_elapsed(last_timer) > 5) { - suspended = true; -# ifdef SLEEP_LED_ENABLE - sleep_led_enable(); -# endif + if (!vusb_suspended && timer_elapsed(sof_timer) > 5) { + vusb_suspend(); } } #endif - if (!suspended) { + if (vusb_suspended) { + vusb_suspend(); + if (suspend_wakeup_condition()) { + vusb_send_remote_wakeup(); + } + } else { usbPoll(); // TODO: configuration process is inconsistent. it sometime fails. @@ -145,6 +163,7 @@ int main(void) { raw_hid_task(); } #endif + #ifdef CONSOLE_ENABLE usbPoll(); @@ -154,10 +173,7 @@ int main(void) { #endif // Run housekeeping - housekeeping_task_kb(); - housekeeping_task_user(); - } else if (suspend_wakeup_condition()) { - usb_remote_wakeup(); + housekeeping_task(); } } } diff --git a/tmk_core/protocol/vusb/usbconfig.h b/tmk_core/protocol/vusb/usbconfig.h new file mode 100644 index 0000000000..041f7bd095 --- /dev/null +++ b/tmk_core/protocol/vusb/usbconfig.h @@ -0,0 +1,356 @@ +/* Name: usbconfig.h + * Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers + * Author: Christian Starkjohann + * Creation Date: 2005-04-01 + * Tabsize: 4 + * Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH + * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) + * This Revision: $Id: usbconfig-prototype.h 785 2010-05-30 17:57:07Z cs $ + */ + +#pragma once + +// clang-format off + +/* +General Description: +This file is an example configuration (with inline documentation) for the USB +driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is +also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may +wire the lines to any other port, as long as D+ is also wired to INT0 (or any +other hardware interrupt, as long as it is the highest level interrupt, see +section at the end of this file). +*/ + +/* ---------------------------- Hardware Config ---------------------------- */ + +#ifndef USB_CFG_IOPORTNAME +#define USB_CFG_IOPORTNAME D +#endif +/* This is the port where the USB bus is connected. When you configure it to + * "B", the registers PORTB, PINB and DDRB will be used. + */ +#ifndef USB_CFG_DMINUS_BIT +#define USB_CFG_DMINUS_BIT 3 +#endif +/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. + * This may be any bit in the port. + */ +#ifndef USB_CFG_DPLUS_BIT +#define USB_CFG_DPLUS_BIT 2 +#endif +/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. + * This may be any bit in the port. Please note that D+ must also be connected + * to interrupt pin INT0! [You can also use other interrupts, see section + * "Optional MCU Description" below, or you can connect D- to the interrupt, as + * it is required if you use the USB_COUNT_SOF feature. If you use D- for the + * interrupt, the USB interrupt will also be triggered at Start-Of-Frame + * markers every millisecond.] + */ +#define USB_CFG_CHECK_CRC 0 +/* Define this to 1 if you want that the driver checks integrity of incoming + * data packets (CRC checks). CRC checks cost quite a bit of code size and are + * currently only available for 18 MHz crystal clock. You must choose + * USB_CFG_CLOCK_KHZ = 18000 if you enable this option. + */ + +/* ----------------------- Optional Hardware Config ------------------------ */ + +/* #define USB_CFG_PULLUP_IOPORTNAME D */ +/* If you connect the 1.5k pullup resistor from D- to a port pin instead of + * V+, you can connect and disconnect the device from firmware by calling + * the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). + * This constant defines the port on which the pullup resistor is connected. + */ +/* #define USB_CFG_PULLUP_BIT 4 */ +/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined + * above) where the 1.5k pullup resistor is connected. See description + * above for details. + */ + +/* --------------------------- Functional Range ---------------------------- */ + +#define USB_CFG_HAVE_INTRIN_ENDPOINT 1 +/* Define this to 1 if you want to compile a version with two endpoints: The + * default control endpoint 0 and an interrupt-in endpoint (any other endpoint + * number). + */ +#define USB_CFG_HAVE_INTRIN_ENDPOINT3 1 +/* Define this to 1 if you want to compile a version with three endpoints: The + * default control endpoint 0, an interrupt-in endpoint 3 (or the number + * configured below) and a catch-all default interrupt-in endpoint as above. + * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. + */ +#define USB_CFG_EP3_NUMBER 3 +/* If the so-called endpoint 3 is used, it can now be configured to any other + * endpoint number (except 0) with this macro. Default if undefined is 3. + */ +#define USB_CFG_HAVE_INTRIN_ENDPOINT4 1 +/* Define this to 1 if you want to compile a version with three endpoints: The + * default control endpoint 0, an interrupt-in endpoint 4 (or the number + * configured below) and a catch-all default interrupt-in endpoint as above. + * You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature. + */ +#define USB_CFG_EP4_NUMBER 4 +/* If the so-called endpoint 4 is used, it can now be configured to any other + * endpoint number (except 0) with this macro. Default if undefined is 4. + */ +/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */ +/* The above macro defines the startup condition for data toggling on the + * interrupt/bulk endpoints 1, 3 and 4. Defaults to USBPID_DATA1. + * Since the token is toggled BEFORE sending any data, the first packet is + * sent with the oposite value of this configuration! + */ +#define USB_CFG_IMPLEMENT_HALT 0 +/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature + * for endpoint 1 (interrupt endpoint). Although you may not need this feature, + * it is required by the standard. We have made it a config option because it + * bloats the code considerably. + */ +#define USB_CFG_SUPPRESS_INTR_CODE 0 +/* Define this to 1 if you want to declare interrupt-in endpoints, but don't + * want to send any data over them. If this macro is defined to 1, functions + * usbSetInterrupt(), usbSetInterrupt3() and usbSetInterrupt4() are omitted. + * This is useful if you need the interrupt-in endpoints in order to comply + * to an interface (e.g. HID), but never want to send any data. This option + * saves a couple of bytes in flash memory and the transmit buffers in RAM. + */ +#define USB_CFG_IS_SELF_POWERED 0 +/* Define this to 1 if the device has its own power supply. Set it to 0 if the + * device is powered from the USB bus. + */ +#define USB_CFG_IMPLEMENT_FN_WRITE 1 +/* Set this to 1 if you want usbFunctionWrite() to be called for control-out + * transfers. Set it to 0 if you don't need it and want to save a couple of + * bytes. + */ +#define USB_CFG_IMPLEMENT_FN_READ 0 +/* Set this to 1 if you need to send control replies which are generated + * "on the fly" when usbFunctionRead() is called. If you only want to send + * data from a static buffer, set it to 0 and return the data from + * usbFunctionSetup(). This saves a couple of bytes. + */ +#define USB_CFG_IMPLEMENT_FN_WRITEOUT 1 +/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. + * You must implement the function usbFunctionWriteOut() which receives all + * interrupt/bulk data sent to any endpoint other than 0. The endpoint number + * can be found in 'usbRxToken'. + */ +#define USB_CFG_HAVE_FLOWCONTROL 0 +/* Define this to 1 if you want flowcontrol over USB data. See the definition + * of the macros usbDisableAllRequests() and usbEnableAllRequests() in + * usbdrv.h. + */ +#define USB_CFG_DRIVER_FLASH_PAGE 0 +/* If the device has more than 64 kBytes of flash, define this to the 64 k page + * where the driver's constants (descriptors) are located. Or in other words: + * Define this to 1 for boot loaders on the ATMega128. + */ +#define USB_CFG_LONG_TRANSFERS 0 +/* Define this to 1 if you want to send/receive blocks of more than 254 bytes + * in a single control-in or control-out transfer. Note that the capability + * for long transfers increases the driver size. + */ +/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */ +/* This macro is a hook if you want to do unconventional things. If it is + * defined, it's inserted at the beginning of received message processing. + * If you eat the received message and don't want default processing to + * proceed, do a return after doing your things. One possible application + * (besides debugging) is to flash a status LED on each packet. + */ +/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ +/* This macro is a hook if you need to know when an USB RESET occurs. It has + * one parameter which distinguishes between the start of RESET state and its + * end. + */ +/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */ +/* This macro (if defined) is executed when a USB SET_ADDRESS request was + * received. + */ +#ifndef USB_COUNT_SOF +#define USB_COUNT_SOF 1 +#endif +/* define this macro to 1 if you need the global variable "usbSofCount" which + * counts SOF packets. This feature requires that the hardware interrupt is + * connected to D- instead of D+. + */ +/* #ifdef __ASSEMBLER__ + * macro myAssemblerMacro + * in YL, TCNT0 + * sts timer0Snapshot, YL + * endm + * #endif + * #define USB_SOF_HOOK myAssemblerMacro + * This macro (if defined) is executed in the assembler module when a + * Start Of Frame condition is detected. It is recommended to define it to + * the name of an assembler macro which is defined here as well so that more + * than one assembler instruction can be used. The macro may use the register + * YL and modify SREG. If it lasts longer than a couple of cycles, USB messages + * immediately after an SOF pulse may be lost and must be retried by the host. + * What can you do with this hook? Since the SOF signal occurs exactly every + * 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in + * designs running on the internal RC oscillator. + * Please note that Start Of Frame detection works only if D- is wired to the + * interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES! + */ +#define USB_CFG_CHECK_DATA_TOGGLING 0 +/* define this macro to 1 if you want to filter out duplicate data packets + * sent by the host. Duplicates occur only as a consequence of communication + * errors, when the host does not receive an ACK. Please note that you need to + * implement the filtering yourself in usbFunctionWriteOut() and + * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable + * for each control- and out-endpoint to check for duplicate packets. + */ +#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 +/* define this macro to 1 if you want the function usbMeasureFrameLength() + * compiled in. This function can be used to calibrate the AVR's RC oscillator. + */ +#define USB_USE_FAST_CRC 0 +/* The assembler module has two implementations for the CRC algorithm. One is + * faster, the other is smaller. This CRC routine is only used for transmitted + * messages where timing is not critical. The faster routine needs 31 cycles + * per byte while the smaller one needs 61 to 69 cycles. The faster routine + * may be worth the 32 bytes bigger code size if you transmit lots of data and + * run the AVR close to its limit. + */ + +/* -------------------------- Device Description --------------------------- */ + +#define USB_CFG_VENDOR_ID +/* USB vendor ID for the device, low byte first. If you have registered your + * own Vendor ID, define it here. Otherwise you may use one of obdev's free + * shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules! + * *** IMPORTANT NOTE *** + * This template uses obdev's shared VID/PID pair for Vendor Class devices + * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand + * the implications! + */ +#define USB_CFG_DEVICE_ID +/* This is the ID of the product, low byte first. It is interpreted in the + * scope of the vendor ID. If you have registered your own VID with usb.org + * or if you have licensed a PID from somebody else, define it here. Otherwise + * you may use one of obdev's free shared VID/PID pairs. See the file + * USB-IDs-for-free.txt for details! + * *** IMPORTANT NOTE *** + * This template uses obdev's shared VID/PID pair for Vendor Class devices + * with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand + * the implications! + */ +#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0 +/* Define this to the length of the HID report descriptor, if you implement + * an HID device. Otherwise don't define it or define it to 0. + * If you use this define, you must add a PROGMEM character array named + * "usbHidReportDescriptor" to your code which contains the report descriptor. + * Don't forget to keep the array and this define in sync! + */ + +/* #define USB_PUBLIC static */ +/* Use the define above if you #include usbdrv.c instead of linking against it. + * This technique saves a couple of bytes in flash memory. + */ + +/* ------------------- Fine Control over USB Descriptors ------------------- */ +/* If you don't want to use the driver's default USB descriptors, you can + * provide our own. These can be provided as (1) fixed length static data in + * flash memory, (2) fixed length static data in RAM or (3) dynamically at + * runtime in the function usbFunctionDescriptor(). See usbdrv.h for more + * information about this function. + * Descriptor handling is configured through the descriptor's properties. If + * no properties are defined or if they are 0, the default descriptor is used. + * Possible properties are: + * + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched + * at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is + * used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if + * you want RAM pointers. + * + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found + * in static memory is in RAM, not in flash memory. + * + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), + * the driver must know the descriptor's length. The descriptor itself is + * found at the address of a well known identifier (see below). + * List of static descriptor names (must be declared PROGMEM if in flash): + * char usbDescriptorDevice[]; + * char usbDescriptorConfiguration[]; + * char usbDescriptorHidReport[]; + * char usbDescriptorString0[]; + * int usbDescriptorStringVendor[]; + * int usbDescriptorStringDevice[]; + * int usbDescriptorStringSerialNumber[]; + * Other descriptors can't be provided statically, they must be provided + * dynamically at runtime. + * + * Descriptor properties are or-ed or added together, e.g.: + * #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) + * + * The following descriptors are defined: + * USB_CFG_DESCR_PROPS_DEVICE + * USB_CFG_DESCR_PROPS_CONFIGURATION + * USB_CFG_DESCR_PROPS_STRINGS + * USB_CFG_DESCR_PROPS_STRING_0 + * USB_CFG_DESCR_PROPS_STRING_VENDOR + * USB_CFG_DESCR_PROPS_STRING_PRODUCT + * USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER + * USB_CFG_DESCR_PROPS_HID + * USB_CFG_DESCR_PROPS_HID_REPORT + * USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver) + * + * Note about string descriptors: String descriptors are not just strings, they + * are Unicode strings prefixed with a 2 byte header. Example: + * int serialNumberDescriptor[] = { + * USB_STRING_DESCRIPTOR_HEADER(6), + * 'S', 'e', 'r', 'i', 'a', 'l' + * }; + */ + +#define USB_CFG_DESCR_PROPS_DEVICE USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_CONFIGURATION USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_STRINGS USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_STRING_0 USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_STRING_VENDOR USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_STRING_PRODUCT USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_HID USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_HID_REPORT USB_PROP_IS_DYNAMIC +#define USB_CFG_DESCR_PROPS_UNKNOWN 0 + +#define usbMsgPtr_t unsigned short +/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to + * a scalar type here because gcc generates slightly shorter code for scalar + * arithmetics than for pointer arithmetics. Remove this define for backward + * type compatibility or define it to an 8 bit type if you use data in RAM only + * and all RAM is below 256 bytes (tiny memory model in IAR CC). + */ + +/* ----------------------- Optional MCU Description ------------------------ */ + +/* The following configurations have working defaults in usbdrv.h. You + * usually don't need to set them explicitly. Only if you want to run + * the driver on a device which is not yet supported or with a compiler + * which is not fully supported (such as IAR C) or if you use a differnt + * interrupt than INT0, you may have to define some of these. + */ +/* #define USB_INTR_CFG MCUCR */ +/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */ +/* #define USB_INTR_CFG_CLR 0 */ +/* #define USB_INTR_ENABLE GIMSK */ +/* #define USB_INTR_ENABLE_BIT INT0 */ +/* #define USB_INTR_PENDING GIFR */ +/* #define USB_INTR_PENDING_BIT INTF0 */ +/* #define USB_INTR_VECTOR INT0_vect */ + +/* Set INT1 for D- falling edge to count SOF */ +/* #define USB_INTR_CFG EICRA */ +#ifndef USB_INTR_CFG_SET +#define USB_INTR_CFG_SET ((1 << ISC11) | (0 << ISC10)) +#endif +/* #define USB_INTR_CFG_CLR 0 */ +/* #define USB_INTR_ENABLE EIMSK */ +#ifndef USB_INTR_ENABLE_BIT +#define USB_INTR_ENABLE_BIT INT1 +#endif +/* #define USB_INTR_PENDING EIFR */ +#ifndef USB_INTR_PENDING_BIT +#define USB_INTR_PENDING_BIT INTF1 +#endif +#ifndef USB_INTR_VECTOR +#define USB_INTR_VECTOR INT1_vect +#endif diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c index 4a13ca5847..9362fbde78 100644 --- a/tmk_core/protocol/vusb/vusb.c +++ b/tmk_core/protocol/vusb/vusb.c @@ -296,7 +296,7 @@ static void send_consumer(uint16_t data) { *------------------------------------------------------------------*/ static struct { uint16_t len; - enum { NONE, BOOTLOADER, SET_LED } kind; + enum { NONE, SET_LED } kind; } last_req; usbMsgLen_t usbFunctionSetup(uchar data[8]) { @@ -323,11 +323,6 @@ usbMsgLen_t usbFunctionSetup(uchar data[8]) { dprint("SET_LED:"); last_req.kind = SET_LED; last_req.len = rq->wLength.word; -#ifdef BOOTLOADER_SIZE - } else if (rq->wValue.word == 0x0301) { - last_req.kind = BOOTLOADER; - last_req.len = rq->wLength.word; -#endif } return USB_NO_MSG; // to get data in usbFunctionWrite } else { @@ -352,11 +347,6 @@ uchar usbFunctionWrite(uchar *data, uchar len) { last_req.len = 0; return 1; break; - case BOOTLOADER: - usbDeviceDisconnect(); - bootloader_jump(); - return 1; - break; case NONE: default: return -1; @@ -454,19 +444,15 @@ const PROGMEM uchar shared_hid_report[] = { 0x85, REPORT_ID_MOUSE, // Report ID 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) - // Buttons (5 bits) + // Buttons (8 bits) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (Button 1) - 0x29, 0x05, // Usage Maximum (Button 5) + 0x29, 0x08, // Usage Maximum (Button 8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) - 0x95, 0x05, // Report Count (5) + 0x95, 0x08, // Report Count (8) 0x75, 0x01, // Report Size (1) 0x81, 0x02, // Input (Data, Variable, Absolute) - // Button padding (3 bits) - 0x95, 0x01, // Report Count (1) - 0x75, 0x03, // Report Size (3) - 0x81, 0x03, // Input (Constant) // X/Y position (2 bytes) 0x05, 0x01, // Usage Page (Generic Desktop) diff --git a/tmk_core/protocol/vusb/vusb.h b/tmk_core/protocol/vusb/vusb.h index b4c73aabae..b1ecc98f37 100644 --- a/tmk_core/protocol/vusb/vusb.h +++ b/tmk_core/protocol/vusb/vusb.h @@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #pragma once #include "host_driver.h" +#include <usbdrv/usbdrv.h> typedef struct usbDescriptorHeader { uchar bLength; @@ -119,5 +120,7 @@ typedef struct usbConfigurationDescriptor { #define USB_STRING_LEN(s) (sizeof(usbDescriptorHeader_t) + ((s) << 1)) +extern bool vusb_suspended; + host_driver_t *vusb_driver(void); void vusb_transfer_keyboard(void); diff --git a/tmk_core/protocol/xt.h b/tmk_core/protocol/xt.h index 6dc5f19d00..538ff0e459 100644 --- a/tmk_core/protocol/xt.h +++ b/tmk_core/protocol/xt.h @@ -38,33 +38,36 @@ POSSIBILITY OF SUCH DAMAGE. #pragma once -#define XT_DATA_IN() \ - do { \ - XT_DATA_DDR &= ~(1 << XT_DATA_BIT); \ - XT_DATA_PORT |= (1 << XT_DATA_BIT); \ +#include "quantum.h" + +#define XT_DATA_IN() \ + do { \ + setPinInput(XT_DATA_PIN); \ + writePinHigh(XT_DATA_PIN); \ } while (0) -#define XT_DATA_READ() (XT_DATA_PIN & (1 << XT_DATA_BIT)) +#define XT_DATA_READ() readPin(XT_DATA_PIN) -#define XT_DATA_LO() \ - do { \ - XT_DATA_PORT &= ~(1 << XT_DATA_BIT); \ - XT_DATA_DDR |= (1 << XT_DATA_BIT); \ +#define XT_DATA_LO() \ + do { \ + writePinLow(XT_DATA_PIN); \ + setPinOutput(XT_DATA_PIN); \ } while (0) -#define XT_CLOCK_IN() \ - do { \ - XT_CLOCK_DDR &= ~(1 << XT_CLOCK_BIT); \ - XT_CLOCK_PORT |= (1 << XT_CLOCK_BIT); \ +#define XT_CLOCK_IN() \ + do { \ + setPinInput(XT_CLOCK_PIN); \ + writePinHigh(XT_CLOCK_PIN); \ } while (0) -#define XT_CLOCK_READ() (XT_CLOCK_PIN & (1 << XT_CLOCK_BIT)) +#define XT_CLOCK_READ() readPin(XT_CLOCK_PIN) -#define XT_CLOCK_LO() \ - do { \ - XT_CLOCK_PORT &= ~(1 << XT_CLOCK_BIT); \ - XT_CLOCK_DDR |= (1 << XT_CLOCK_BIT); \ +#define XT_CLOCK_LO() \ + do { \ + writePinLow(XT_CLOCK_PIN); \ + setPinOutput(XT_CLOCK_PIN); \ } while (0) -void xt_host_init(void); +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 index 51e52243fd..ba9d71848f 100644 --- a/tmk_core/protocol/xt_interrupt.c +++ b/tmk_core/protocol/xt_interrupt.c @@ -38,7 +38,6 @@ POSSIBILITY OF SUCH DAMAGE. #include <stdbool.h> #include <avr/interrupt.h> -#include <util/delay.h> #include "xt.h" #include "wait.h" #include "debug.h" @@ -60,7 +59,7 @@ void xt_host_init(void) { /* soft reset: pull clock line down for 20ms */ XT_DATA_LO(); XT_CLOCK_LO(); - _delay_ms(20); + wait_ms(20); /* input mode with pullup */ XT_CLOCK_IN(); @@ -120,9 +119,10 @@ ISR(XT_INT_VECT) { * 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 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(); @@ -135,6 +135,7 @@ static inline void pbuf_enqueue(uint8_t data) { } SREG = sreg; } + static inline uint8_t pbuf_dequeue(void) { uint8_t val = 0; @@ -148,6 +149,7 @@ static inline uint8_t pbuf_dequeue(void) { return val; } + static inline bool pbuf_has_data(void) { uint8_t sreg = SREG; cli(); @@ -155,6 +157,7 @@ static inline bool pbuf_has_data(void) { SREG = sreg; return has_data; } + static inline void pbuf_clear(void) { uint8_t sreg = SREG; cli(); |