@ -28,41 +28,36 @@
# include "raw_hid.h"
# include "dynamic_keymap.h"
# include "tmk_core/common/eeprom.h"
# include "version.h" // for QMK_BUILDDATE used in EEPROM magic
# include "version.h" // for QMK_BUILDDATE used in EEPROM magic
// Can be called in an overriding via_init_kb() to test if keyboard level code usage of
// EEPROM is invalid and use/save defaults.
bool via_eeprom_is_valid ( void )
{
char * p = QMK_BUILDDATE ; // e.g. "2019-11-05-11:29:54"
uint8_t magic0 = ( ( p [ 2 ] & 0x0F ) < < 4 ) | ( p [ 3 ] & 0x0F ) ;
uint8_t magic1 = ( ( p [ 5 ] & 0x0F ) < < 4 ) | ( p [ 6 ] & 0x0F ) ;
uint8_t magic2 = ( ( p [ 8 ] & 0x0F ) < < 4 ) | ( p [ 9 ] & 0x0F ) ;
bool via_eeprom_is_valid ( void ) {
char * p = QMK_BUILDDATE ; // e.g. "2019-11-05-11:29:54"
uint8_t magic0 = ( ( p [ 2 ] & 0x0F ) < < 4 ) | ( p [ 3 ] & 0x0F ) ;
uint8_t magic1 = ( ( p [ 5 ] & 0x0F ) < < 4 ) | ( p [ 6 ] & 0x0F ) ;
uint8_t magic2 = ( ( p [ 8 ] & 0x0F ) < < 4 ) | ( p [ 9 ] & 0x0F ) ;
return ( eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 0 ) = = magic0 & &
eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 1 ) = = magic1 & &
eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 2 ) = = magic2 ) ;
return ( eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 0 ) = = magic0 & & eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 1 ) = = magic1 & & eeprom_read_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 2 ) = = magic2 ) ;
}
// Sets VIA/keyboard level usage of EEPROM to valid/invalid
// Keyboard level code (eg. via_init_kb()) should not call this
void via_eeprom_set_valid ( bool valid )
{
char * p = QMK_BUILDDATE ; // e.g. "2019-11-05-11:29:54"
uint8_t magic0 = ( ( p [ 2 ] & 0x0F ) < < 4 ) | ( p [ 3 ] & 0x0F ) ;
uint8_t magic1 = ( ( p [ 5 ] & 0x0F ) < < 4 ) | ( p [ 6 ] & 0x0F ) ;
uint8_t magic2 = ( ( p [ 8 ] & 0x0F ) < < 4 ) | ( p [ 9 ] & 0x0F ) ;
void via_eeprom_set_valid ( bool valid ) {
char * p = QMK_BUILDDATE ; // e.g. "2019-11-05-11:29:54"
uint8_t magic0 = ( ( p [ 2 ] & 0x0F ) < < 4 ) | ( p [ 3 ] & 0x0F ) ;
uint8_t magic1 = ( ( p [ 5 ] & 0x0F ) < < 4 ) | ( p [ 6 ] & 0x0F ) ;
uint8_t magic2 = ( ( p [ 8 ] & 0x0F ) < < 4 ) | ( p [ 9 ] & 0x0F ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 0 , valid ? magic0 : 0xFF ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 1 , valid ? magic1 : 0xFF ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 2 , valid ? magic2 : 0xFF ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 0 , valid ? magic0 : 0xFF ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 1 , valid ? magic1 : 0xFF ) ;
eeprom_update_byte ( ( void * ) VIA_EEPROM_MAGIC_ADDR + 2 , valid ? magic2 : 0xFF ) ;
}
// Flag QMK and VIA/keyboard level EEPROM as invalid.
// Used in bootmagic_lite() and VIA command handler.
// Keyboard level code should not need to call this.
void via_eeprom_reset ( void )
{
void via_eeprom_reset ( void ) {
// Set the VIA specific EEPROM state as invalid.
via_eeprom_set_valid ( false ) ;
// Set the TMK/QMK EEPROM state as invalid.
@ -72,8 +67,7 @@ void via_eeprom_reset(void)
// Override bootmagic_lite() so it can flag EEPROM as invalid
// as well as jump to bootloader, thus performing a "factory reset"
// of dynamic keymaps and optionally backlight/other settings.
void bootmagic_lite ( void )
{
void bootmagic_lite ( void ) {
// The lite version of TMK's bootmagic based on Wilba.
// 100% less potential for accidentally making the
// keyboard do stupid things.
@ -106,12 +100,10 @@ void bootmagic_lite(void)
// for backlight, rotary encoders, etc.
// The override should not set via_eeprom_set_valid(true) as
// the caller also needs to check the valid state.
__attribute__ ( ( weak ) ) void via_init_kb ( void ) {
}
__attribute__ ( ( weak ) ) void via_init_kb ( void ) { }
// Called by QMK core to initialize dynamic keymaps etc.
void via_init ( void )
{
void via_init ( void ) {
// Let keyboard level test EEPROM valid state,
// but not set it valid, it is done here.
via_init_kb ( ) ;
@ -119,7 +111,7 @@ void via_init(void)
// If the EEPROM has the magic, the data is good.
// OK to load from EEPROM.
if ( via_eeprom_is_valid ( ) ) {
} else {
} else {
// This resets the layout options
via_set_layout_options ( 0 ) ;
// This resets the keymaps in EEPROM to what is in flash.
@ -133,12 +125,11 @@ void via_init(void)
// This is generalized so the layout options EEPROM usage can be
// variable, between 1 and 4 bytes.
uint32_t via_get_layout_options ( void )
{
uint32_t via_get_layout_options ( void ) {
uint32_t value = 0 ;
// Start at the most significant byte
void * source = ( void * ) ( VIA_EEPROM_LAYOUT_OPTIONS_ADDR ) ;
for ( uint8_t i = 0 ; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE ; i + + ) {
void * source = ( void * ) ( VIA_EEPROM_LAYOUT_OPTIONS_ADDR ) ;
for ( uint8_t i = 0 ; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE ; i + + ) {
value = value < < 8 ;
value | = eeprom_read_byte ( source ) ;
source + + ;
@ -146,24 +137,21 @@ uint32_t via_get_layout_options(void)
return value ;
}
void via_set_layout_options ( uint32_t value )
{
void via_set_layout_options ( uint32_t value ) {
// Start at the least significant byte
void * target = ( void * ) ( VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE - 1 ) ;
for ( uint8_t i = 0 ; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE ; i + + ) {
eeprom_update_byte ( target , value & 0xFF ) ;
void * target = ( void * ) ( VIA_EEPROM_LAYOUT_OPTIONS_ADDR + VIA_EEPROM_LAYOUT_OPTIONS_SIZE - 1 ) ;
for ( uint8_t i = 0 ; i < VIA_EEPROM_LAYOUT_OPTIONS_SIZE ; i + + ) {
eeprom_update_byte ( target , value & 0xFF ) ;
value = value > > 8 ;
target - - ;
}
}
// Called by QMK core to process VIA-specific keycodes.
bool process_record_via ( uint16_t keycode , keyrecord_t * record )
{
bool process_record_via ( uint16_t keycode , keyrecord_t * record ) {
// Handle macros
if ( record - > event . pressed ) {
if ( keycode > = MACRO00 & & keycode < = MACRO15 )
{
if ( keycode > = MACRO00 & & keycode < = MACRO15 ) {
uint8_t id = keycode - MACRO00 ;
dynamic_keymap_macro_send ( id ) ;
return false ;
@ -173,7 +161,7 @@ bool process_record_via(uint16_t keycode, keyrecord_t *record)
// TODO: ideally this would be generalized and refactored into
// QMK core as advanced keycodes, until then, the simple case
// can be available here to keyboards using VIA
switch ( keycode ) {
switch ( keycode ) {
case FN_MO13 :
if ( record - > event . pressed ) {
layer_on ( 1 ) ;
@ -203,7 +191,7 @@ bool process_record_via(uint16_t keycode, keyrecord_t *record)
// DO NOT call raw_hid_send() in the overide function.
__attribute__ ( ( weak ) ) void raw_hid_receive_kb ( uint8_t * data , uint8_t length ) {
uint8_t * command_id = & ( data [ 0 ] ) ;
* command_id = id_unhandled ;
* command_id = id_unhandled ;
}
// VIA handles received HID messages first, and will route to
@ -211,182 +199,151 @@ __attribute__((weak)) void raw_hid_receive_kb(uint8_t *data, uint8_t length) {
// This gives the keyboard code level the ability to handle the command
// specifically.
//
// raw_hid_send() is called at the end, with the same buffer, which was
// raw_hid_send() is called at the end, with the same buffer, which was
// possibly modified with returned values.
void raw_hid_receive ( uint8_t * data , uint8_t length )
{
uint8_t * command_id = & ( data [ 0 ] ) ;
void raw_hid_receive ( uint8_t * data , uint8_t length ) {
uint8_t * command_id = & ( data [ 0 ] ) ;
uint8_t * command_data = & ( data [ 1 ] ) ;
switch ( * command_id )
{
case id_get_protocol_version :
{
switch ( * command_id ) {
case id_get_protocol_version : {
command_data [ 0 ] = VIA_PROTOCOL_VERSION > > 8 ;
command_data [ 1 ] = VIA_PROTOCOL_VERSION & 0xFF ;
break ;
}
case id_get_keyboard_value :
{
switch ( command_data [ 0 ] )
{
case id_uptime :
{
uint32_t value = timer_read32 ( ) ;
command_data [ 1 ] = ( value > > 24 ) & 0xFF ;
command_data [ 2 ] = ( value > > 16 ) & 0xFF ;
command_data [ 3 ] = ( value > > 8 ) & 0xFF ;
case id_get_keyboard_value : {
switch ( command_data [ 0 ] ) {
case id_uptime : {
uint32_t value = timer_read32 ( ) ;
command_data [ 1 ] = ( value > > 24 ) & 0xFF ;
command_data [ 2 ] = ( value > > 16 ) & 0xFF ;
command_data [ 3 ] = ( value > > 8 ) & 0xFF ;
command_data [ 4 ] = value & 0xFF ;
break ;
}
case id_layout_options :
{
uint32_t value = via_get_layout_options ( ) ;
command_data [ 1 ] = ( value > > 24 ) & 0xFF ;
command_data [ 2 ] = ( value > > 16 ) & 0xFF ;
command_data [ 3 ] = ( value > > 8 ) & 0xFF ;
case id_layout_options : {
uint32_t value = via_get_layout_options ( ) ;
command_data [ 1 ] = ( value > > 24 ) & 0xFF ;
command_data [ 2 ] = ( value > > 16 ) & 0xFF ;
command_data [ 3 ] = ( value > > 8 ) & 0xFF ;
command_data [ 4 ] = value & 0xFF ;
break ;
}
case id_switch_matrix_state :
{
# if ( (MATRIX_COLS / 8+1)*MATRIX_ROWS <= 28 )
case id_switch_matrix_state : {
# if ((MATRIX_COLS / 8 + 1) * MATRIX_ROWS <= 28)
uint8_t i = 1 ;
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row + + ) {
for ( uint8_t row = 0 ; row < MATRIX_ROWS ; row + + ) {
matrix_row_t value = matrix_get_row ( row ) ;
# if (MATRIX_COLS > 24)
command_data [ i + + ] = ( value > > 24 ) & 0xFF ;
# endif
# if (MATRIX_COLS > 16)
command_data [ i + + ] = ( value > > 16 ) & 0xFF ;
# endif
# if (MATRIX_COLS > 8)
command_data [ i + + ] = ( value > > 8 ) & 0xFF ;
# endif
# if (MATRIX_COLS > 24)
command_data [ i + + ] = ( value > > 24 ) & 0xFF ;
# endif
# if (MATRIX_COLS > 16)
command_data [ i + + ] = ( value > > 16 ) & 0xFF ;
# endif
# if (MATRIX_COLS > 8)
command_data [ i + + ] = ( value > > 8 ) & 0xFF ;
# endif
command_data [ i + + ] = value & 0xFF ;
}
# endif
break ;
}
default :
{
raw_hid_receive_kb ( data , length ) ;
default : {
raw_hid_receive_kb ( data , length ) ;
break ;
}
}
break ;
}
case id_set_keyboard_value :
{
switch ( command_data [ 0 ] )
{
case id_layout_options :
{
uint32_t value = ( ( uint32_t ) command_data [ 1 ] < < 24 ) |
( ( uint32_t ) command_data [ 2 ] < < 16 ) |
( ( uint32_t ) command_data [ 3 ] < < 8 ) |
( uint32_t ) command_data [ 4 ] ;
case id_set_keyboard_value : {
switch ( command_data [ 0 ] ) {
case id_layout_options : {
uint32_t value = ( ( uint32_t ) command_data [ 1 ] < < 24 ) | ( ( uint32_t ) command_data [ 2 ] < < 16 ) | ( ( uint32_t ) command_data [ 3 ] < < 8 ) | ( uint32_t ) command_data [ 4 ] ;
via_set_layout_options ( value ) ;
break ;
}
default :
{
raw_hid_receive_kb ( data , length ) ;
default : {
raw_hid_receive_kb ( data , length ) ;
break ;
}
}
break ;
}
case id_dynamic_keymap_get_keycode :
{
uint16_t keycode = dynamic_keymap_get_keycode ( command_data [ 0 ] , command_data [ 1 ] , command_data [ 2 ] ) ;
command_data [ 3 ] = keycode > > 8 ;
command_data [ 4 ] = keycode & 0xFF ;
case id_dynamic_keymap_get_keycode : {
uint16_t keycode = dynamic_keymap_get_keycode ( command_data [ 0 ] , command_data [ 1 ] , command_data [ 2 ] ) ;
command_data [ 3 ] = keycode > > 8 ;
command_data [ 4 ] = keycode & 0xFF ;
break ;
}
case id_dynamic_keymap_set_keycode :
{
dynamic_keymap_set_keycode ( command_data [ 0 ] , command_data [ 1 ] , command_data [ 2 ] , ( command_data [ 3 ] < < 8 ) | command_data [ 4 ] ) ;
case id_dynamic_keymap_set_keycode : {
dynamic_keymap_set_keycode ( command_data [ 0 ] , command_data [ 1 ] , command_data [ 2 ] , ( command_data [ 3 ] < < 8 ) | command_data [ 4 ] ) ;
break ;
}
case id_dynamic_keymap_reset :
{
case id_dynamic_keymap_reset : {
dynamic_keymap_reset ( ) ;
break ;
}
case id_backlight_config_set_value :
case id_backlight_config_get_value :
case id_backlight_config_save :
{
case id_backlight_config_save : {
raw_hid_receive_kb ( data , length ) ;
break ;
}
case id_dynamic_keymap_macro_get_count :
{
case id_dynamic_keymap_macro_get_count : {
command_data [ 0 ] = dynamic_keymap_macro_get_count ( ) ;
break ;
}
case id_dynamic_keymap_macro_get_buffer_size :
{
uint16_t size = dynamic_keymap_macro_get_buffer_size ( ) ;
case id_dynamic_keymap_macro_get_buffer_size : {
uint16_t size = dynamic_keymap_macro_get_buffer_size ( ) ;
command_data [ 0 ] = size > > 8 ;
command_data [ 1 ] = size & 0xFF ;
break ;
}
case id_dynamic_keymap_macro_get_buffer :
{
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_macro_get_buffer ( offset , size , & command_data [ 3 ] ) ;
case id_dynamic_keymap_macro_get_buffer : {
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_macro_get_buffer ( offset , size , & command_data [ 3 ] ) ;
break ;
}
case id_dynamic_keymap_macro_set_buffer :
{
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_macro_set_buffer ( offset , size , & command_data [ 3 ] ) ;
case id_dynamic_keymap_macro_set_buffer : {
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_macro_set_buffer ( offset , size , & command_data [ 3 ] ) ;
break ;
}
case id_dynamic_keymap_macro_reset :
{
case id_dynamic_keymap_macro_reset : {
dynamic_keymap_macro_reset ( ) ;
break ;
}
case id_dynamic_keymap_get_layer_count :
{
case id_dynamic_keymap_get_layer_count : {
command_data [ 0 ] = dynamic_keymap_get_layer_count ( ) ;
break ;
}
case id_dynamic_keymap_get_buffer :
{
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_get_buffer ( offset , size , & command_data [ 3 ] ) ;
case id_dynamic_keymap_get_buffer : {
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_get_buffer ( offset , size , & command_data [ 3 ] ) ;
break ;
}
case id_dynamic_keymap_set_buffer :
{
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_set_buffer ( offset , size , & command_data [ 3 ] ) ;
case id_dynamic_keymap_set_buffer : {
uint16_t offset = ( command_data [ 0 ] < < 8 ) | command_data [ 1 ] ;
uint16_t size = command_data [ 2 ] ; // size <= 28
dynamic_keymap_set_buffer ( offset , size , & command_data [ 3 ] ) ;
break ;
}
case id_eeprom_reset :
{
case id_eeprom_reset : {
via_eeprom_reset ( ) ;
break ;
}
case id_bootloader_jump :
{
case id_bootloader_jump : {
// Need to send data back before the jump
// Informs host that the command is handled
raw_hid_send ( data , length ) ;
raw_hid_send ( data , length ) ;
// Give host time to read it
wait_ms ( 100 ) ;
bootloader_jump ( ) ;
break ;
}
default :
{
default : {
// The command ID is not known
// Return the unhandled state
* command_id = id_unhandled ;
@ -396,5 +353,5 @@ void raw_hid_receive( uint8_t *data, uint8_t length )
// Return the same buffer, optionally with values changed
// (i.e. returning state to the host, or the unhandled state).
raw_hid_send ( data , length ) ;
raw_hid_send ( data , length ) ;
}