mirror of
https://github.com/qmk/qmk_firmware.git
synced 2026-07-08 01:44:40 -04:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 12139903ce | |||
| 817bbaa5f9 | |||
| 2dc5e39798 | |||
| da481f5cc4 | |||
| 7a15cd2482 | |||
| 428b1cd568 | |||
| e38f3097cb | |||
| cf93bbb78f | |||
| 9f75ab2c92 | |||
| b1093e9da5 | |||
| 5734360a86 | |||
| 0ec0cdde81 | |||
| ee9354d36e | |||
| 0cb6461c6a | |||
| dd905c9531 | |||
| 963986c475 | |||
| aae4189aa4 | |||
| 198026cf27 | |||
| fd624d016b | |||
| 6741f9dc26 | |||
| f8910d3a60 | |||
| c638100030 | |||
| 1d2f52e407 |
@@ -25,7 +25,7 @@ jobs:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ jobs:
|
||||
echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' >> /etc/sudoers
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
@@ -201,7 +201,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
@@ -258,7 +258,7 @@ jobs:
|
||||
git:
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
submodules: recursive
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
- name: Checkout QMK Firmware
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip3 install -r requirements-dev.txt
|
||||
@@ -89,7 +89,7 @@ jobs:
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
- name: Checkout QMK Firmware
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
- name: Checkout QMK Firmware
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip3 install -r requirements-dev.txt
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
git config --global --add safe.directory '*'
|
||||
|
||||
- name: Checkout QMK Firmware
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
@@ -105,7 +105,7 @@ jobs:
|
||||
|
||||
- name: Restore Cache
|
||||
id: cache
|
||||
uses: actions/cache/restore@v5
|
||||
uses: actions/cache/restore@v6
|
||||
with:
|
||||
path: ${{ env.CCACHE_CONFIGPATH }}
|
||||
key: compile-${{ inputs.keymap }}-${{ matrix.target }}
|
||||
@@ -136,7 +136,7 @@ jobs:
|
||||
fi
|
||||
|
||||
- name: Save Cache
|
||||
uses: actions/cache/save@v5
|
||||
uses: actions/cache/save@v6
|
||||
with:
|
||||
path: ${{ env.CCACHE_CONFIGPATH }}
|
||||
key: compile-${{ inputs.keymap }}-${{ matrix.target }}
|
||||
@@ -166,7 +166,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout QMK Firmware
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Download firmwares
|
||||
uses: actions/download-artifact@v8
|
||||
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
if: github.repository == 'qmk/qmk_firmware'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
- riot
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
token: ${{ secrets.QMK_BOT_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip3 install -r requirements-dev.txt
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
- name: Disable safe.directory check
|
||||
run : git config --global --add safe.directory '*'
|
||||
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Install dependencies
|
||||
run: pip3 install -r requirements-dev.txt
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
container: ghcr.io/qmk/qmk_cli
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
|
||||
@@ -111,7 +111,6 @@ secrets.tar
|
||||
# Python things
|
||||
__pycache__
|
||||
.python-version
|
||||
*.egg-info
|
||||
.venv
|
||||
|
||||
# Prerequisites for updating ChibiOS
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# responsible for determining which folder is being used and doing the
|
||||
# corresponding environment setup.
|
||||
|
||||
ifndef VERBOSE
|
||||
ifneq ($(VERBOSE),true)
|
||||
.SILENT:
|
||||
endif
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ifndef VERBOSE
|
||||
ifneq ($(VERBOSE),true)
|
||||
.SILENT:
|
||||
endif
|
||||
|
||||
|
||||
@@ -49,10 +49,6 @@ else ifeq ($(strip $(DEBUG_MATRIX_SCAN_RATE_ENABLE)), api)
|
||||
OPT_DEFS += -DDEBUG_MATRIX_SCAN_RATE
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(XAP_ENABLE)), yes)
|
||||
include $(BUILDDEFS_PATH)/xap.mk
|
||||
endif
|
||||
|
||||
AUDIO_ENABLE ?= no
|
||||
ifeq ($(strip $(AUDIO_ENABLE)), yes)
|
||||
ifeq ($(PLATFORM),CHIBIOS)
|
||||
@@ -649,22 +645,6 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(XAP_ENABLE)), yes)
|
||||
ifeq ($(strip $(VIA_ENABLE)), yes)
|
||||
$(error 'XAP_ENABLE = $(XAP_ENABLE)' deprecates 'VIA_ENABLE = $(VIA_ENABLE)'. Please set 'VIA_ENABLE = no')
|
||||
endif
|
||||
|
||||
DYNAMIC_KEYMAP_ENABLE := yes
|
||||
FNV_ENABLE := yes
|
||||
SECURE_ENABLE := yes
|
||||
BOOTMAGIC_ENABLE := yes
|
||||
|
||||
OPT_DEFS += -DXAP_ENABLE
|
||||
OPT_DEFS += -DBOOTLOADER_JUMP_SUPPORTED
|
||||
VPATH += $(QUANTUM_DIR)/xap
|
||||
SRC += $(QUANTUM_DIR)/xap/xap.c $(QUANTUM_DIR)/xap/xap_handlers.c
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(RAW_ENABLE)), yes)
|
||||
OPT_DEFS += -DRAW_ENABLE
|
||||
SRC += raw_hid.c
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
# Copyright 2022 Nick Brassel (@tzarc)
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
XAP_FILES := $(shell ls -1 data/xap/* | sort | xargs echo)
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_1)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYBOARD_PATH_1)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_2)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYBOARD_PATH_2)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_3)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYBOARD_PATH_3)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_4)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYBOARD_PATH_4)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYBOARD_PATH_5)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(KEYMAP_PATH)/xap.hjson)","")
|
||||
XAP_FILES += $(KEYMAP_PATH)/xap.hjson
|
||||
endif
|
||||
ifneq ("$(wildcard $(USER_NAME)/xap.hjson)","")
|
||||
XAP_FILES += $(USER_NAME)/xap.hjson
|
||||
endif
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/config_blob_gz.h: $(INFO_JSON_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) xap-generate-qmk-blob-h -o "$(INTERMEDIATE_OUTPUT)/src/config_blob_gz.h" -kb $(KEYBOARD) -km $(KEYMAP))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/xap_generated.inl: $(XAP_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) xap-generate-qmk-inc -o "$(INTERMEDIATE_OUTPUT)/src/xap_generated.inl" -kb $(KEYBOARD) -km $(KEYMAP))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
$(INTERMEDIATE_OUTPUT)/src/xap_generated.h: $(XAP_FILES)
|
||||
@$(SILENT) || printf "$(MSG_GENERATING) $@" | $(AWK_CMD)
|
||||
$(eval CMD=$(QMK_BIN) xap-generate-qmk-h -o "$(INTERMEDIATE_OUTPUT)/src/xap_generated.h" -kb $(KEYBOARD) -km $(KEYMAP))
|
||||
@$(BUILD_CMD)
|
||||
|
||||
generated-files: $(INTERMEDIATE_OUTPUT)/src/config_blob_gz.h $(INTERMEDIATE_OUTPUT)/src/xap_generated.inl $(INTERMEDIATE_OUTPUT)/src/xap_generated.h
|
||||
|
||||
VPATH += $(INTERMEDIATE_OUTPUT)/src
|
||||
@@ -1,82 +0,0 @@
|
||||
{
|
||||
"groups": {
|
||||
"reactive": {
|
||||
"define": "LED_MATRIX_KEYREACTIVE_ENABLED"
|
||||
}
|
||||
},
|
||||
"effects": {
|
||||
"0x00": {
|
||||
"key": "SOLID"
|
||||
},
|
||||
"0x01": {
|
||||
"key": "ALPHAS_MODS"
|
||||
},
|
||||
"0x02": {
|
||||
"key": "BREATHING"
|
||||
},
|
||||
"0x03": {
|
||||
"key": "BAND"
|
||||
},
|
||||
"0x04": {
|
||||
"key": "BAND_PINWHEEL"
|
||||
},
|
||||
"0x05": {
|
||||
"key": "BAND_SPIRAL"
|
||||
},
|
||||
"0x06": {
|
||||
"key": "CYCLE_LEFT_RIGHT"
|
||||
},
|
||||
"0x07": {
|
||||
"key": "CYCLE_UP_DOWN"
|
||||
},
|
||||
"0x08": {
|
||||
"key": "CYCLE_OUT_IN"
|
||||
},
|
||||
"0x09": {
|
||||
"key": "DUAL_BEACON"
|
||||
},
|
||||
"0x0A": {
|
||||
"key": "WAVE_LEFT_RIGHT"
|
||||
},
|
||||
"0x0B": {
|
||||
"key": "WAVE_UP_DOWN"
|
||||
},
|
||||
|
||||
"0x0C": {
|
||||
"key": "SOLID_REACTIVE_SIMPLE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x0D": {
|
||||
"key": "SOLID_REACTIVE_WIDE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x0E": {
|
||||
"key": "SOLID_REACTIVE_MULTIWIDE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x0F": {
|
||||
"key": "SOLID_REACTIVE_CROSS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x10": {
|
||||
"key": "SOLID_REACTIVE_MULTICROSS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x11": {
|
||||
"key": "SOLID_REACTIVE_NEXUS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x12": {
|
||||
"key": "SOLID_REACTIVE_MULTINEXUS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x13": {
|
||||
"key": "SOLID_SPLASH",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x14": {
|
||||
"key": "SOLID_MULTISPLASH",
|
||||
"group": "reactive"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
{
|
||||
"groups": {
|
||||
"framebuffer": {
|
||||
"define": "RGB_MATRIX_FRAMEBUFFER_EFFECTS"
|
||||
},
|
||||
"reactive": {
|
||||
"define": "RGB_MATRIX_KEYREACTIVE_ENABLED"
|
||||
}
|
||||
},
|
||||
"effects": {
|
||||
"0x00": {
|
||||
"key": "SOLID_COLOR"
|
||||
},
|
||||
"0x01": {
|
||||
"key": "ALPHAS_MODS"
|
||||
},
|
||||
"0x02": {
|
||||
"key": "GRADIENT_UP_DOWN"
|
||||
},
|
||||
"0x03": {
|
||||
"key": "GRADIENT_LEFT_RIGHT"
|
||||
},
|
||||
"0x04": {
|
||||
"key": "BREATHING"
|
||||
},
|
||||
"0x05": {
|
||||
"key": "BAND_SAT"
|
||||
},
|
||||
"0x06": {
|
||||
"key": "BAND_VAL"
|
||||
},
|
||||
"0x07": {
|
||||
"key": "BAND_PINWHEEL_SAT"
|
||||
},
|
||||
"0x08": {
|
||||
"key": "BAND_PINWHEEL_VAL"
|
||||
},
|
||||
"0x09": {
|
||||
"key": "BAND_SPIRAL_SAT"
|
||||
},
|
||||
"0x0A": {
|
||||
"key": "BAND_SPIRAL_VAL"
|
||||
},
|
||||
"0x0B": {
|
||||
"key": "CYCLE_ALL"
|
||||
},
|
||||
"0x0C": {
|
||||
"key": "CYCLE_LEFT_RIGHT"
|
||||
},
|
||||
"0x0D": {
|
||||
"key": "CYCLE_UP_DOWN"
|
||||
},
|
||||
"0x0E": {
|
||||
"key": "CYCLE_OUT_IN"
|
||||
},
|
||||
"0x0F": {
|
||||
"key": "CYCLE_OUT_IN_DUAL"
|
||||
},
|
||||
"0x10": {
|
||||
"key": "RAINBOW_MOVING_CHEVRON"
|
||||
},
|
||||
"0x11": {
|
||||
"key": "CYCLE_PINWHEEL"
|
||||
},
|
||||
"0x12": {
|
||||
"key": "CYCLE_SPIRAL"
|
||||
},
|
||||
"0x13": {
|
||||
"key": "DUAL_BEACON"
|
||||
},
|
||||
"0x14": {
|
||||
"key": "RAINBOW_BEACON"
|
||||
},
|
||||
"0x15": {
|
||||
"key": "RAINBOW_PINWHEELS"
|
||||
},
|
||||
"0x16": {
|
||||
"key": "RAINDROPS"
|
||||
},
|
||||
"0x17": {
|
||||
"key": "JELLYBEAN_RAINDROPS"
|
||||
},
|
||||
"0x18": {
|
||||
"key": "HUE_BREATHING"
|
||||
},
|
||||
"0x19": {
|
||||
"key": "HUE_PENDULUM"
|
||||
},
|
||||
"0x1A": {
|
||||
"key": "HUE_WAVE"
|
||||
},
|
||||
"0x1B": {
|
||||
"key": "PIXEL_FRACTAL"
|
||||
},
|
||||
"0x1C": {
|
||||
"key": "PIXEL_FLOW"
|
||||
},
|
||||
"0x1D": {
|
||||
"key": "PIXEL_RAIN"
|
||||
},
|
||||
|
||||
"0x1E": {
|
||||
"key": "TYPING_HEATMAP",
|
||||
"group": "framebuffer"
|
||||
},
|
||||
"0x1F": {
|
||||
"key": "DIGITAL_RAIN",
|
||||
"group": "framebuffer"
|
||||
},
|
||||
|
||||
"0x20": {
|
||||
"key": "SOLID_REACTIVE_SIMPLE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x21": {
|
||||
"key": "SOLID_REACTIVE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x22": {
|
||||
"key": "SOLID_REACTIVE_WIDE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x23": {
|
||||
"key": "SOLID_REACTIVE_MULTIWIDE",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x24": {
|
||||
"key": "SOLID_REACTIVE_CROSS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x25": {
|
||||
"key": "SOLID_REACTIVE_MULTICROSS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x26": {
|
||||
"key": "SOLID_REACTIVE_NEXUS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x27": {
|
||||
"key": "SOLID_REACTIVE_MULTINEXUS",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x28": {
|
||||
"key": "SPLASH",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x29": {
|
||||
"key": "MULTISPLASH",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x2A": {
|
||||
"key": "SOLID_SPLASH",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x2B": {
|
||||
"key": "SOLID_MULTISPLASH",
|
||||
"group": "reactive"
|
||||
},
|
||||
"0x2C": {
|
||||
"key": "FLOWER_BLOOMING"
|
||||
},
|
||||
"0x2D": {
|
||||
"key": "STARLIGHT"
|
||||
},
|
||||
"0x2E": {
|
||||
"key": "STARLIGHT_DUAL_SAT"
|
||||
},
|
||||
"0x2F": {
|
||||
"key": "STARLIGHT_DUAL_HUE"
|
||||
},
|
||||
"0x30": {
|
||||
"key": "RIVERFLOW"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
{
|
||||
"effects": {
|
||||
"0x00": {
|
||||
"key": "STATIC_LIGHT"
|
||||
},
|
||||
"0x01": {
|
||||
"key": "BREATHING"
|
||||
},
|
||||
"0x02": {
|
||||
"key": "BREATHING_2"
|
||||
},
|
||||
"0x03": {
|
||||
"key": "BREATHING_3"
|
||||
},
|
||||
"0x04": {
|
||||
"key": "BREATHING_4"
|
||||
},
|
||||
"0x05": {
|
||||
"key": "RAINBOW_MOOD"
|
||||
},
|
||||
"0x06": {
|
||||
"key": "RAINBOW_MOOD_2"
|
||||
},
|
||||
"0x07": {
|
||||
"key": "RAINBOW_MOOD_3"
|
||||
},
|
||||
"0x08": {
|
||||
"key": "RAINBOW_SWIRL"
|
||||
},
|
||||
"0x09": {
|
||||
"key": "RAINBOW_SWIRL_2"
|
||||
},
|
||||
"0x0A": {
|
||||
"key": "RAINBOW_SWIRL_3"
|
||||
},
|
||||
"0x0B": {
|
||||
"key": "RAINBOW_SWIRL_4"
|
||||
},
|
||||
"0x0C": {
|
||||
"key": "RAINBOW_SWIRL_5"
|
||||
},
|
||||
"0x0D": {
|
||||
"key": "RAINBOW_SWIRL_6"
|
||||
},
|
||||
"0x0E": {
|
||||
"key": "SNAKE"
|
||||
},
|
||||
"0x0F": {
|
||||
"key": "SNAKE_2"
|
||||
},
|
||||
"0x10": {
|
||||
"key": "SNAKE_3"
|
||||
},
|
||||
"0x11": {
|
||||
"key": "SNAKE_4"
|
||||
},
|
||||
"0x12": {
|
||||
"key": "SNAKE_5"
|
||||
},
|
||||
"0x13": {
|
||||
"key": "SNAKE_6"
|
||||
},
|
||||
"0x14": {
|
||||
"key": "KNIGHT"
|
||||
},
|
||||
"0x15": {
|
||||
"key": "KNIGHT_2"
|
||||
},
|
||||
"0x16": {
|
||||
"key": "KNIGHT_3"
|
||||
},
|
||||
"0x17": {
|
||||
"key": "CHRISTMAS"
|
||||
},
|
||||
"0x18": {
|
||||
"key": "STATIC_GRADIENT"
|
||||
},
|
||||
"0x19": {
|
||||
"key": "STATIC_GRADIENT_2"
|
||||
},
|
||||
"0x1A": {
|
||||
"key": "STATIC_GRADIENT_3"
|
||||
},
|
||||
"0x1B": {
|
||||
"key": "STATIC_GRADIENT_4"
|
||||
},
|
||||
"0x1C": {
|
||||
"key": "STATIC_GRADIENT_5"
|
||||
},
|
||||
"0x1D": {
|
||||
"key": "STATIC_GRADIENT_6"
|
||||
},
|
||||
"0x1E": {
|
||||
"key": "STATIC_GRADIENT_7"
|
||||
},
|
||||
"0x1F": {
|
||||
"key": "STATIC_GRADIENT_8"
|
||||
},
|
||||
"0x20": {
|
||||
"key": "STATIC_GRADIENT_9"
|
||||
},
|
||||
"0x21": {
|
||||
"key": "STATIC_GRADIENT_10"
|
||||
},
|
||||
"0x22": {
|
||||
"key": "RGB_TEST"
|
||||
},
|
||||
"0x23": {
|
||||
"key": "ALTERNATING"
|
||||
},
|
||||
"0x24": {
|
||||
"key": "TWINKLE"
|
||||
},
|
||||
"0x25": {
|
||||
"key": "TWINKLE_2"
|
||||
},
|
||||
"0x26": {
|
||||
"key": "TWINKLE_3"
|
||||
},
|
||||
"0x27": {
|
||||
"key": "TWINKLE_4"
|
||||
},
|
||||
"0x28": {
|
||||
"key": "TWINKLE_5"
|
||||
},
|
||||
"0x29": {
|
||||
"key": "TWINKLE_6"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1741,7 +1741,10 @@
|
||||
"target": "ducky/one2mini/1861st"
|
||||
},
|
||||
"ducky/one2sf": {
|
||||
"target": "ducky/one2sf/1967st"
|
||||
"target": "ducky/one2sf/1967st/ansi"
|
||||
},
|
||||
"ducky/one2sf/1967st": {
|
||||
"target": "ducky/one2sf/1967st/ansi"
|
||||
},
|
||||
"dumbpad": {
|
||||
"target": "dumbpad/v0x"
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"secure": {
|
||||
"unlock_sequence": [ [0,0] ],
|
||||
"unlock_timeout": 5000,
|
||||
"idle_timeout": 60000
|
||||
}
|
||||
}
|
||||
@@ -16,18 +16,6 @@
|
||||
"type": "object",
|
||||
"additionalProperties": {"type": "boolean"}
|
||||
},
|
||||
"build_target": {
|
||||
"oneOf": [
|
||||
{"$ref": "#/keyboard_keymap_tuple"},
|
||||
{"$ref": "#/json_file_path"}
|
||||
]
|
||||
},
|
||||
"define": {
|
||||
"type": "string",
|
||||
"minLength": 2,
|
||||
"maxLength": 50,
|
||||
"pattern": "^[A-Z_]*$"
|
||||
},
|
||||
"filename": {
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
@@ -199,10 +187,6 @@
|
||||
"minLength": 1,
|
||||
"maxLength": 250
|
||||
},
|
||||
"text_unsigned_int": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-8]+$"
|
||||
},
|
||||
"unsigned_decimal": {
|
||||
"type": "number",
|
||||
"minimum": 0
|
||||
|
||||
@@ -1,255 +0,0 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"$id": "qmk.xap.v1",
|
||||
"title": "XAP Spec",
|
||||
"definitions": {
|
||||
"data_type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"enum": [
|
||||
"bool",
|
||||
"u8",
|
||||
"u16",
|
||||
"u32",
|
||||
"u64",
|
||||
"struct",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"pattern": "^u\\d{1,2}\\[\\d{1,2}\\]*$"
|
||||
}
|
||||
]
|
||||
},
|
||||
"router_type": {
|
||||
"enum": [
|
||||
"command",
|
||||
"router"
|
||||
]
|
||||
},
|
||||
"permission": {
|
||||
"enum": [
|
||||
"secure"
|
||||
]
|
||||
},
|
||||
"struct": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"name",
|
||||
"type"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"route": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "qmk.definitions.v1#/hex_number_2d"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"required": [
|
||||
"type",
|
||||
"define"
|
||||
],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"type": {
|
||||
"$ref": "#/definitions/router_type"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"define": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"permissions": {
|
||||
"$ref": "#/definitions/permission"
|
||||
},
|
||||
"enable_if_preprocessor": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_type": {
|
||||
"$ref": "#/definitions/data_type"
|
||||
},
|
||||
"request_struct_length": {
|
||||
"type": "number"
|
||||
},
|
||||
"request_purpose": {
|
||||
"type": "string"
|
||||
},
|
||||
"return_type": {
|
||||
"$ref": "#/definitions/data_type"
|
||||
},
|
||||
"request_struct_members": {
|
||||
"$ref": "#definitions/struct"
|
||||
},
|
||||
"return_struct_length": {
|
||||
"type": "number"
|
||||
},
|
||||
"return_constant": {
|
||||
"type": [
|
||||
"array",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"return_struct_members": {
|
||||
"$ref": "#definitions/struct"
|
||||
},
|
||||
"return_purpose": {
|
||||
"type": "string"
|
||||
},
|
||||
"return_execute": {
|
||||
"type": "string"
|
||||
},
|
||||
"routes": {
|
||||
"$ref": "#/definitions/route"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"version": {
|
||||
"$ref": "qmk.definitions.v1#/bcd_version"
|
||||
},
|
||||
"define": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"documentation": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"term_definitions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type_docs": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type_definitions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/data_type"
|
||||
},
|
||||
"struct_length": {
|
||||
"type": "number"
|
||||
},
|
||||
"struct_members": {
|
||||
"$ref": "#definitions/struct"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"response_flags": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"define_prefix": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"bits": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "qmk.definitions.v1#/text_unsigned_int"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"define": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"broadcast_messages": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"define_prefix": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"messages": {
|
||||
"type": "object",
|
||||
"propertyNames": {
|
||||
"$ref": "qmk.definitions.v1#/hex_number_2d"
|
||||
},
|
||||
"additionalProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"define": {
|
||||
"$ref": "qmk.definitions.v1#/define"
|
||||
},
|
||||
"description": {
|
||||
"type": "string"
|
||||
},
|
||||
"return_type": {
|
||||
"$ref": "#/definitions/data_type"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"routes": {
|
||||
"$ref": "#/definitions/route"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_SH_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_SH_LIKE }}
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
# version: 0.0.1
|
||||
class RgblightModes(IntEnum):
|
||||
{% for id, effect in specs.rgblight.effects | dictsort %}
|
||||
{{ effect.key }} = {{ id }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
# version: 0.0.1
|
||||
class RgbMatrixModes(IntEnum):
|
||||
{% for id, effect in specs.rgb_matrix.effects | dictsort %}
|
||||
{{ effect.key }} = {{ id }}
|
||||
{% endfor %}
|
||||
|
||||
# noqa: W391
|
||||
@@ -1,22 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_SH_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_SH_LIKE }}
|
||||
class XAPRouteError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class XAPRoutes():
|
||||
{% for id, route in xap.routes | dictsort %}
|
||||
{% if route.routes %}
|
||||
# {{route.define}}
|
||||
{% for subid, subroute in route.routes | dictsort %}
|
||||
{{route.define}}_{{subroute.define}} = b'\x{{ '%02d' % id|int(base=16) }}\x{{ '%02d' % subid|int(base=16) }}'
|
||||
{% if subroute.routes %}
|
||||
{% for subsubid, subsubroute in subroute.routes | dictsort %}
|
||||
{{route.define}}_{{subroute.define}}_{{subsubroute.define}} = b'\x{{ '%02d' % id|int(base=16) }}\x{{ '%02d' % subid|int(base=16) }}\x{{ '%02d' % subsubid|int(base=16) }}'
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# noqa: W391
|
||||
@@ -1,68 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_SH_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_SH_LIKE }}
|
||||
from collections import namedtuple
|
||||
from enum import IntFlag, IntEnum
|
||||
from struct import Struct
|
||||
|
||||
|
||||
{% macro gen_struct(name, members, fmt) -%}
|
||||
class {{ name }}(namedtuple('{{ name }}', '{{ members }}')):
|
||||
fmt = Struct('{{ fmt }}')
|
||||
|
||||
def __new__(cls, *args):
|
||||
return super().__new__(cls, *args)
|
||||
|
||||
@classmethod
|
||||
def from_bytes(cls, data):
|
||||
return cls._make(cls.fmt.unpack(data))
|
||||
|
||||
def to_bytes(self):
|
||||
return self.fmt.pack(*list(self))
|
||||
|
||||
|
||||
{% endmacro -%}
|
||||
|
||||
{% set type_definitions = [
|
||||
{'name':'XAPRequest', 'members': 'token length data', 'fmt':'<HB61s'},
|
||||
{'name':'XAPResponse', 'members': 'token flags length data', 'fmt':'<HBB60s'},
|
||||
{'name':'XAPBroadcast', 'members': 'token event length data', 'fmt':'<HBB60s'},
|
||||
{'name':'XAPConfigBacklight', 'members': 'enable mode val', 'fmt':'<BBB'},
|
||||
{'name':'XAPConfigRgblight', 'members': 'enable mode hue sat val speed', 'fmt':'<BBBBBB'},
|
||||
{'name':'XAPConfigRgbMatrix', 'members': 'enable mode hue sat val speed flags', 'fmt':'<BBBBBBB'}
|
||||
] %}
|
||||
{% for item in type_definitions -%}{{ gen_struct(item.name, item.members, item.fmt) }}{% endfor -%}
|
||||
|
||||
# Spec structs
|
||||
{% for item in xap.routes.values() recursive %}
|
||||
{%- if item.routes -%}
|
||||
{{ loop(item.routes.values()) }}
|
||||
{%- endif -%}
|
||||
{%- if item.request_struct_members %}
|
||||
# TODO: gen inbound object for {{ item.define | to_snake }}
|
||||
{% endif -%}
|
||||
{%- if item.return_struct_members %}
|
||||
# TODO: gen outbound object for {{ item.define | to_snake }}
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
|
||||
class XAPSecureStatus(IntEnum):
|
||||
LOCKED = 0x00
|
||||
UNLOCKING = 0x01
|
||||
UNLOCKED = 0x02
|
||||
|
||||
|
||||
class XAPEventType(IntEnum):
|
||||
{% for id, message in xap.broadcast_messages.messages | dictsort %}
|
||||
{{ message.define }} = {{ id }}
|
||||
{% endfor %}
|
||||
|
||||
|
||||
class XAPFlags(IntFlag):
|
||||
{% for bitnum, bitinfo in xap.response_flags.bits | dictsort %}
|
||||
{% if bitinfo.define != "-" %}
|
||||
{{ bitinfo.define }} = 1 << {{ bitnum }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
# noqa: W391
|
||||
@@ -1,4 +0,0 @@
|
||||
{% for id, message in xap.broadcast_messages.messages | dictsort %}
|
||||
### {{ message.name }} - `{{ id }}`
|
||||
{{ message.description }}
|
||||
{% endfor %}
|
||||
@@ -1,11 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_XML_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_XML_LIKE }}
|
||||
{%- for item in xap.documentation.order %}
|
||||
{% if not item[0:1] == '!' %}
|
||||
{{ xap.documentation.get(item) }}
|
||||
|
||||
{% else %}
|
||||
{% include item[1:] %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -1,12 +0,0 @@
|
||||
|{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} Bit {{ bitnum }} |{% endfor %}
|
||||
|
||||
|{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} -- |{% endfor %}
|
||||
|
||||
|{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} `{{ bitinfo.define }}` |{% endfor %}
|
||||
|
||||
|
||||
{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %}
|
||||
{% if bitinfo.define != "-" -%}
|
||||
* Bit {{ bitnum }} (`{{ bitinfo.define }}`): {{ bitinfo.description }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -1,52 +0,0 @@
|
||||
{%- macro gen_payload(name, type, purpose, members) -%}
|
||||
{%- if type == 'struct' -%}
|
||||
__{{ name }}:__
|
||||
{%- for member in members -%}
|
||||
<br>{{ " "|safe*4 }}* {{ member.name }}: `{{ member.type }}`
|
||||
{%- endfor -%}
|
||||
{%- elif purpose -%}
|
||||
__{{ name }}:__<br>{{ " "|safe*4 }}* {{ purpose }}: `{{ type }}`
|
||||
{%- elif type -%}
|
||||
__{{ name }}:__ `{{ type }}`
|
||||
{%- endif -%}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro gen_payloads(route) -%}
|
||||
{{ gen_payload('Request', route.request_type, route.request_purpose, route.request_struct_members) }}{%- if route.return_type and route.request_type -%}<br><br>{% endif %}{{ gen_payload('Response', route.return_type, null, route.return_struct_members) }}
|
||||
{%- endmacro -%}
|
||||
|
||||
{%- macro gen_tags(route) -%}
|
||||
{% if 'secure' == route.permissions %}__Secure__{% endif %}
|
||||
{%- endmacro -%}
|
||||
|
||||
{% for id, route in xap.routes | dictsort %}
|
||||
### {{ route.name }} - `{{ id }}`
|
||||
{{ route.description }}
|
||||
|
||||
{% if route.routes %}
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
{% for subid, subroute in route.routes | dictsort %}
|
||||
{% if not subroute.routes %}
|
||||
| {{ subroute.name }} | `{{ id }} {{ subid }}` | {{ gen_tags(subroute) }} | {{ gen_payloads(subroute) }} | {{ subroute.description | newline_to_br }}|
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% for subid, subroute in route.routes | dictsort %}
|
||||
{%- if subroute.routes %}
|
||||
|
||||
#### {{ subroute.name }} - `{{ id }} {{ subid }}`
|
||||
{{ subroute.description }}
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
{% for subsubid, subsubroute in subroute.routes | dictsort %}
|
||||
{% if not subsubroute.routes %}
|
||||
| {{ subsubroute.name }} | `{{ id }} {{ subid }} {{ subsubid }}` | {{ gen_tags(subsubroute) }} | {{ gen_payloads(subsubroute) }} | {{ subsubroute.description | newline_to_br }}|
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -1,8 +0,0 @@
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
{% for type, definition in xap.term_definitions | dictsort %}
|
||||
| _{{ type }}_ | {{ definition }} |
|
||||
{% endfor %}
|
||||
{% for type, definition in xap.type_definitions | dictsort %}
|
||||
| _{{ definition.name }}_ | {{ definition.description }}{% if 'struct' == definition.type %} Takes the format:{% for item in definition.struct_members %}<br>`{{ item.type }}` - {{ item.name }}{%- endfor %}{% endif %} |
|
||||
{% endfor %}
|
||||
@@ -1,5 +0,0 @@
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
{% for type, definition in xap.type_docs | dictsort %}
|
||||
| _{{ type }}_ | {{ definition }} |
|
||||
{% endfor %}
|
||||
@@ -1,6 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_XML_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_XML_LIKE }}
|
||||
|
||||
{%- for ver in versions | reverse -%}
|
||||
* [XAP Version {{ ver }}](xap_{{ ver }}.md)
|
||||
{% endfor %}
|
||||
@@ -1,171 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_C_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_C_LIKE }}
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Versions and identifiers
|
||||
|
||||
#define XAP_BCD_VERSION UINT32_C({{ xap.version | triplet_to_bcd }})
|
||||
#define QMK_BCD_VERSION UINT32_C({{ qmk_version | triplet_to_bcd }})
|
||||
#define XAP_KEYBOARD_IDENTIFIER UINT32_C({{ keyboard | fnv1a_32 }})
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Response flag definitions
|
||||
|
||||
{% for bit,data in xap.response_flags.bits | dictsort %}
|
||||
#define {{ xap.response_flags.define_prefix }}_{{ data.define | to_snake | upper }} (UINT32_C(1) << ({{ bit }}))
|
||||
{% endfor %}
|
||||
#define {{ xap.response_flags.define_prefix }}_FAILED 0x00
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Broadcast message definitions
|
||||
|
||||
{% for message_id,data in xap.broadcast_messages.messages | dictsort %}
|
||||
#define {{ xap.broadcast_messages.define_prefix }}_{{ data.define | to_snake | upper }} {{ message_id }}
|
||||
{% if 'return_type' in data %}
|
||||
void {{ xap.broadcast_messages.define_prefix | lower }}_{{ data.define | to_snake | lower }}({{ data.return_type | type_to_c('value') }});
|
||||
{% else %}
|
||||
void {{ xap.broadcast_messages.define_prefix | lower }}_{{ data.define | to_snake | lower }}(const void *data, size_t length);
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
#define XAP_BROADCAST_TOKEN 0xFFFF
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Type definitions
|
||||
|
||||
{% for name,data in xap.type_definitions | dictsort %}
|
||||
{% if data.type != 'struct' %}
|
||||
typedef {{ data.type | type_to_c('xap_'+(name|to_snake|lower)+'_t') }};
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% for name,data in xap.type_definitions | dictsort %}
|
||||
{% if data.type == 'struct' %}
|
||||
typedef struct {
|
||||
{% for member in data.struct_members %}
|
||||
{{ member.type | type_to_c(member.name) }};
|
||||
{% endfor %}
|
||||
} __attribute__((__packed__)) xap_{{ name | to_snake | lower }}_t{{ data.type | type_to_c_after }};
|
||||
_Static_assert(sizeof(xap_{{ name | to_snake | lower }}_t) == {{ data.struct_length }}, "xap_{{ name | to_snake | lower }}_t needs to be {{ data.struct_length }} bytes in size");
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Route definitions
|
||||
|
||||
{% macro export_route_types(prefix, container) %}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
|
||||
{% if 'request_struct_members' in data %}
|
||||
typedef struct {
|
||||
{% for member in data.request_struct_members %}
|
||||
{{ member.type | type_to_c(member.name|lower) }};
|
||||
{% endfor %}
|
||||
} __attribute__((__packed__)) {{ this_prefix_lc | to_snake | lower }}_arg_t;
|
||||
_Static_assert(sizeof({{ this_prefix_lc | to_snake | lower }}_arg_t) == {{ data.request_struct_length }}, "{{ this_prefix_lc | to_snake | lower }}_arg_t needs to be {{ data.request_struct_length }} bytes in size");
|
||||
{% elif 'request_type' in data %}
|
||||
{% if '[' in data.request_type %}
|
||||
typedef struct __attribute__((__packed__)) { {{ data.request_type | type_to_c('x') }}; } {{ this_prefix_lc }}_arg_t;
|
||||
{% else %}
|
||||
typedef {{ data.request_type | type_to_c(this_prefix_lc+'_arg_t') }};
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{% if 'return_struct_members' in data %}
|
||||
typedef struct {
|
||||
{% for member in data.return_struct_members %}
|
||||
{{ member.type | type_to_c(member.name|lower) }};
|
||||
{% endfor %}
|
||||
} __attribute__((__packed__)) {{ this_prefix_lc | to_snake | lower }}_t;
|
||||
_Static_assert(sizeof({{ this_prefix_lc | to_snake | lower }}_t) == {{ data.return_struct_length }}, "{{ this_prefix_lc | to_snake | lower }}_t needs to be {{ data.return_struct_length }} bytes in size");
|
||||
{% elif 'return_type' in data %}
|
||||
{% if '[' in data.return_type %}
|
||||
typedef struct __attribute__((__packed__)) { {{ data.return_type | type_to_c('x') }}; } {{ this_prefix_lc }}_t;
|
||||
{% else %}
|
||||
typedef {{ data.return_type | type_to_c(this_prefix_lc+'_t') }};
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
{{ export_route_types(this_prefix_lc, data) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_types('xap_route', xap) }}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Capabilities IDs
|
||||
|
||||
{% macro export_route_ids(prefix, container) %}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
#define {{ this_prefix_uc }} {{ route }}
|
||||
{{ export_route_ids(this_prefix_uc, data) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_ids('XAP_ROUTE', xap) }}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Capabilities Masks
|
||||
|
||||
{% macro export_route_masks(prefix, container, preprocessor_condition) %}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
{% if 'enable_if_preprocessor' in data %}
|
||||
{% if preprocessor_condition == 'TRUE' %}
|
||||
{% set condition = "(" + data.enable_if_preprocessor + ")" %}
|
||||
{% else %}
|
||||
{% set condition = "(" + preprocessor_condition + " && (" + data.enable_if_preprocessor + "))" %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% set condition = preprocessor_condition %}
|
||||
{% endif %}
|
||||
{% if condition == 'TRUE' %}
|
||||
#define {{ this_prefix_uc }}_MASK (UINT32_C(1) << ({{ this_prefix_uc }}))
|
||||
{% else %}
|
||||
#if ({{ condition }})
|
||||
#define {{ this_prefix_uc }}_MASK (UINT32_C(1) << ({{ this_prefix_uc }}))
|
||||
#else // ({{ condition }})
|
||||
#define {{ this_prefix_uc }}_MASK 0
|
||||
#endif // ({{ condition }})
|
||||
{% endif %}
|
||||
{{ export_route_masks(this_prefix_uc, data, condition) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_masks('XAP_ROUTE', xap, 'TRUE') }}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Capabilities Values
|
||||
|
||||
{% macro export_route_capabilities(prefix, container) %}
|
||||
{% if 'routes' in container %}
|
||||
#define {{ prefix }}_CAPABILITIES (0 \
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
| ({{ this_prefix_uc }}_MASK) \
|
||||
{% endfor %}
|
||||
)
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{{ export_route_capabilities(this_prefix_uc, data) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_capabilities('XAP_ROUTE', xap) }}
|
||||
@@ -1,166 +0,0 @@
|
||||
{{ constants.GPL2_HEADER_C_LIKE }}
|
||||
{{ constants.GENERATED_HEADER_C_LIKE }}
|
||||
|
||||
{% macro route_conditions(route_stack) %}
|
||||
{% set conditions = [] %}
|
||||
{% for data in route_stack %}
|
||||
{% if 'enable_if_preprocessor' in data %}
|
||||
{{ conditions.append(data.enable_if_preprocessor) or '' }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if conditions %}
|
||||
#if ({{ conditions | join(' && ') }})
|
||||
{% endif %}
|
||||
{{ caller() }}
|
||||
{%- if conditions %}
|
||||
#endif // ({{ conditions | join(' && ') }})
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Broadcast
|
||||
|
||||
{% for message_id,data in xap.broadcast_messages.messages | dictsort %}
|
||||
{% if 'return_type' in data %}
|
||||
void {{ xap.broadcast_messages.define_prefix | lower }}_{{ data.define | to_snake | lower }}({{ data.return_type | type_to_c('value') }}) { xap_broadcast({{ message_id }}, &value, sizeof(value)); }
|
||||
{% else %}
|
||||
void {{ xap.broadcast_messages.define_prefix | lower }}_{{ data.define | to_snake | lower }}(const void *data, size_t length) { xap_broadcast({{ message_id }}, data, length); }
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Decl
|
||||
|
||||
{% macro export_route_declaration(prefix, container) %}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
{% if 'return_execute' in data %}
|
||||
|
||||
{% if 'request_struct_members' in data %}
|
||||
{% set arg_type = ( this_prefix_lc | to_snake | lower ) + '_arg_t' %}
|
||||
{% set arg_var = arg_type + ' arg' %}
|
||||
{% elif 'request_type' in data %}
|
||||
{% set arg_type = data.request_type | type_to_c() %}
|
||||
{% set arg_var = data.request_type | type_to_c('arg') %}
|
||||
{% endif %}
|
||||
|
||||
__attribute__((weak)) bool xap_execute_{{ data.return_execute }}(xap_token_t token{% if arg_type %}, {{ (arg_type + '* arg') if 'xap_route' in arg_type else arg_var }}{% endif %}) { return false; }
|
||||
__attribute__((weak)) bool xap_respond_{{ data.return_execute }}(xap_token_t token, const uint8_t *data, size_t data_len) {
|
||||
{% if arg_type %}
|
||||
if (data_len != sizeof({{ arg_type }})) {
|
||||
return false;
|
||||
}
|
||||
{{ arg_var }};
|
||||
memcpy(&arg, data, sizeof({{ arg_type }}));
|
||||
{% endif %}
|
||||
|
||||
return xap_execute_{{ data.return_execute }}(token{% if arg_type %}, {{ '&' if 'xap_route' in arg_type else '' }}arg{% endif %});
|
||||
}
|
||||
{% endif %}
|
||||
{{ export_route_declaration(this_prefix_lc, data) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_declaration('xap_route', xap) }}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Data
|
||||
|
||||
{% macro export_route_data(prefix, container, route_stack) %}
|
||||
{% set this_route_stack = route_stack.copy() %}
|
||||
{{ this_route_stack.append(container) or '' }}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
{% if 'return_constant' in data %}
|
||||
{% if data.return_type == 'struct' %}
|
||||
{% call route_conditions(this_route_stack) %}
|
||||
static const {{ this_prefix_lc }}_t {{ this_prefix_lc }}_data PROGMEM = {
|
||||
{% for member in data.return_constant %}
|
||||
{{ member }},
|
||||
{% endfor %}
|
||||
};
|
||||
{% endcall %}
|
||||
{% elif data.return_type == 'string' %}
|
||||
{% call route_conditions(this_route_stack) %}
|
||||
static const char {{ this_prefix_lc }}_str[] PROGMEM = {{ data.return_constant }};
|
||||
{% endcall %}
|
||||
{% else %}
|
||||
{% call route_conditions(this_route_stack) %}
|
||||
static const {{ data.return_type | type_to_c_before }} {{ this_prefix_lc }}_data PROGMEM = {{ data.return_constant }};
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{{ export_route_data(this_prefix_lc, data, this_route_stack) }}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ export_route_data('XAP_ROUTE', xap, []) }}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Routes
|
||||
|
||||
{% macro append_routing_table(prefix, container, route_stack) %}
|
||||
{% set this_route_stack = route_stack.copy() %}
|
||||
{{ this_route_stack.append(container) or '' }}
|
||||
{% if 'routes' in container %}
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||
{{ append_routing_table(this_prefix_lc, data, this_route_stack) }}
|
||||
{% endfor %}
|
||||
{% call route_conditions(this_route_stack) %}
|
||||
static const xap_route_t {{ prefix | lower}}_table[] PROGMEM = {
|
||||
{% for route, data in container.routes | dictsort %}
|
||||
{% set inner_route_stack = this_route_stack.copy() %}
|
||||
{{ inner_route_stack.append(data) or '' }}
|
||||
{% if 'permissions' in data %}
|
||||
{% set secure_status = 'ROUTE_PERMISSIONS_SECURE' %}
|
||||
{% else %}
|
||||
{% set secure_status = 'ROUTE_PERMISSIONS_INSECURE' %}
|
||||
{% endif %}
|
||||
{% call route_conditions(inner_route_stack) %}
|
||||
[{{ prefix | upper }}_{{ data.define }}] = {
|
||||
{% if 'routes' in data %}
|
||||
.flags = {
|
||||
.type = XAP_ROUTE,
|
||||
.secure = {{ secure_status }},
|
||||
},
|
||||
.child_routes = {{ prefix | lower }}_{{ data.define | lower }}_table,
|
||||
.child_routes_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_table)/sizeof(xap_route_t),
|
||||
{% elif 'return_execute' in data %}
|
||||
.flags = {
|
||||
.type = XAP_EXECUTE,
|
||||
.secure = {{ secure_status }},
|
||||
},
|
||||
.handler = xap_respond_{{ data.return_execute | lower }},
|
||||
{% elif 'return_constant' in data and data.return_type == 'string' %}
|
||||
.flags = {
|
||||
.type = XAP_CONST_MEM,
|
||||
.secure = {{ secure_status }},
|
||||
},
|
||||
.const_data = {{ prefix | lower }}_{{ data.define | lower }}_str,
|
||||
.const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_str) - 1,
|
||||
{% elif 'return_constant' in data %}
|
||||
.flags = {
|
||||
.type = XAP_CONST_MEM,
|
||||
.secure = {{ secure_status }},
|
||||
},
|
||||
.const_data = &{{ prefix | lower }}_{{ data.define | lower }}_data,
|
||||
.const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_data),
|
||||
{% endif %}
|
||||
},
|
||||
{% endcall %}
|
||||
{% endfor %}
|
||||
};
|
||||
{% endcall %}
|
||||
{% endif %}
|
||||
{% endmacro %}
|
||||
|
||||
{{ append_routing_table("xap_route", xap, []) }}
|
||||
@@ -1,237 +0,0 @@
|
||||
{
|
||||
version: 0.0.1
|
||||
|
||||
// Needed for table generation
|
||||
define: XAP_ROUTE
|
||||
|
||||
// Documentation section is used purely for `qmk xap-generate-docs`.
|
||||
documentation: {
|
||||
order: [
|
||||
page_header
|
||||
type_docs
|
||||
!type_docs.md.j2
|
||||
term_definitions
|
||||
!term_definitions.md.j2
|
||||
request_response
|
||||
reserved_tokens
|
||||
response_flags
|
||||
!response_flags.md.j2
|
||||
example_conversation
|
||||
routes
|
||||
!routes.md.j2
|
||||
]
|
||||
|
||||
page_header:
|
||||
'''
|
||||
# QMK Firmware XAP Specs
|
||||
|
||||
This document describes the requirements of the QMK XAP ("extensible application protocol") API.
|
||||
'''
|
||||
|
||||
type_docs:
|
||||
'''
|
||||
## Types
|
||||
|
||||
**All integral types are little-endian.**
|
||||
'''
|
||||
|
||||
term_definitions:
|
||||
'''
|
||||
## Definitions
|
||||
|
||||
This list defines the terms used across the entire set of XAP protocol documentation.
|
||||
'''
|
||||
|
||||
request_response:
|
||||
'''
|
||||
## Requests and Responses
|
||||
|
||||
Communication generally follows a request/response pattern.
|
||||
|
||||
Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response.
|
||||
This allows response messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously.
|
||||
Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.
|
||||
To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
|
||||
This token is followed by a `u8` signifying the length of data in the request.
|
||||
'''
|
||||
|
||||
// This documentation section reserved for next version
|
||||
reserved_tokens: ''
|
||||
|
||||
response_flags:
|
||||
'''
|
||||
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
|
||||
'''
|
||||
|
||||
example_conversation:
|
||||
'''
|
||||
### Example "conversation":
|
||||
|
||||
**Request** -- version query:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Payload Length | Route | Route |
|
||||
| **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` |
|
||||
|
||||
**Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` |
|
||||
'''
|
||||
|
||||
routes:
|
||||
'''
|
||||
## Routes
|
||||
|
||||
Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01).
|
||||
This is the primary method for determining if a subsystem has been enabled in the running firmware.
|
||||
'''
|
||||
}
|
||||
|
||||
type_docs: {
|
||||
u8:
|
||||
'''
|
||||
An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_.
|
||||
'''
|
||||
u16:
|
||||
'''
|
||||
An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_.
|
||||
'''
|
||||
u32:
|
||||
'''
|
||||
An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_.
|
||||
'''
|
||||
"type[n]":
|
||||
'''
|
||||
An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets.
|
||||
'''
|
||||
}
|
||||
|
||||
term_definitions: {
|
||||
Subsystem:
|
||||
'''
|
||||
A high-level area of functionality within XAP.
|
||||
'''
|
||||
Route:
|
||||
'''
|
||||
A sequence of _IDs_ describing the route to invoke a _handler_.
|
||||
'''
|
||||
Handler:
|
||||
'''
|
||||
A piece of code that is executed when a specific _route_ is received.
|
||||
'''
|
||||
Response:
|
||||
'''
|
||||
The data sent back to the host during execution of a _handler_.
|
||||
'''
|
||||
Payload:
|
||||
'''
|
||||
Any received data appended to the _route_, which gets delivered to the _handler_ when received.
|
||||
'''
|
||||
}
|
||||
|
||||
type_definitions: {
|
||||
identifier: {
|
||||
name: ID
|
||||
description: A single octet / 8-bit byte, representing Subsystem or Route index.
|
||||
type: u8
|
||||
}
|
||||
|
||||
response_flags: {
|
||||
name: Response Flags
|
||||
description: An `u8` containing the status of the request.
|
||||
type: u8
|
||||
}
|
||||
|
||||
token: {
|
||||
name: Token
|
||||
description: A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
type: u16
|
||||
}
|
||||
|
||||
request_header: {
|
||||
name: Request Header
|
||||
description: Packet format for inbound data.
|
||||
type: struct
|
||||
struct_length: 3
|
||||
struct_members: [
|
||||
{
|
||||
type: token
|
||||
name: token
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: length
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
response_header: {
|
||||
name: Response Header
|
||||
description: Packet format for outbound data.
|
||||
type: struct
|
||||
struct_length: 4
|
||||
struct_members: [
|
||||
{
|
||||
type: token
|
||||
name: token
|
||||
},
|
||||
{
|
||||
type: response_flags
|
||||
name: flags
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: length
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
response_flags: {
|
||||
define_prefix: XAP_RESPONSE_FLAG
|
||||
bits: {
|
||||
0: {
|
||||
name: Success
|
||||
define: SUCCESS
|
||||
description:
|
||||
'''
|
||||
When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
routes: {
|
||||
0x00: {
|
||||
type: router
|
||||
name: XAP
|
||||
define: XAP
|
||||
description:
|
||||
'''
|
||||
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
|
||||
'''
|
||||
routes: {
|
||||
0x00: {
|
||||
type: command
|
||||
name: Version Query
|
||||
define: VERSION_QUERY
|
||||
description:
|
||||
'''
|
||||
XAP protocol version query.
|
||||
|
||||
* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`
|
||||
* e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: bcd-version
|
||||
return_constant: XAP_BCD_VERSION
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,385 +0,0 @@
|
||||
{
|
||||
version: 0.1.0
|
||||
|
||||
documentation: {
|
||||
order: [
|
||||
broadcast_messages
|
||||
!broadcast_messages.md.j2
|
||||
]
|
||||
|
||||
reserved_tokens:
|
||||
'''
|
||||
Two token values are reserved: `0xFFFE` and `0xFFFF`:
|
||||
* `0xFFFE`: A message sent by a host application may use this token if no response is to be sent -- a "fire and forget" message.
|
||||
* `0xFFFF`: Signifies a "broadcast" message sent by the firmware without prompting from the host application. Broadcast messages are defined later in this document.
|
||||
|
||||
Any request will generate at least one corresponding response, with the exception of messages using reserved tokens. Maximum total message length is 128 bytes due to RAM constraints.
|
||||
'''
|
||||
|
||||
broadcast_messages:
|
||||
'''
|
||||
## Broadcast messages
|
||||
|
||||
Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, then the response _payload_ length, and finally the corresponding _payload_.
|
||||
'''
|
||||
}
|
||||
|
||||
response_flags: {
|
||||
bits: {
|
||||
1: {
|
||||
name: Secure Failure
|
||||
define: SECURE_FAILURE
|
||||
description:
|
||||
'''
|
||||
When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed.
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type_docs: {
|
||||
bool:
|
||||
'''
|
||||
Data type that contains values 0 and 1. Implemented as an alias of `u8`.
|
||||
'''
|
||||
u64:
|
||||
'''
|
||||
An unsigned 64-bit integral, commonly seen as `uint64_t` from _stdint.h_.
|
||||
'''
|
||||
"struct{}":
|
||||
'''
|
||||
A structure of data, packing different objects together. Data is "compacted" -- there are no padding bytes between fields. Equivalent to a packed C-style `struct`. The order in which they're defined matches the order of the data in the response packet.
|
||||
'''
|
||||
}
|
||||
|
||||
term_definitions: {
|
||||
Capability:
|
||||
'''
|
||||
A way to determine if certain functionality is enabled in the firmware. Any _subsystem_ that provides build-time restriction of functionality must provide a _route_ for a _capabilities query_.
|
||||
'''
|
||||
"Secure Route":
|
||||
'''
|
||||
A _route_ which has potentially destructive consequences, necessitating prior approval by the user before executing.
|
||||
'''
|
||||
"Unlock sequence":
|
||||
'''
|
||||
A physical sequence initiated by the user to enable execution of _secure routes_.
|
||||
'''
|
||||
}
|
||||
|
||||
type_definitions: {
|
||||
broadcast_header: {
|
||||
name: Broadcast Header
|
||||
description: Packet format for broadcast messages.
|
||||
type: struct
|
||||
struct_length: 4
|
||||
struct_members: [
|
||||
{
|
||||
type: token
|
||||
name: token
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: type
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: length
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
broadcast_messages: {
|
||||
define_prefix: XAP_BROADCAST
|
||||
messages: {
|
||||
0x00: {
|
||||
name: Log message
|
||||
define: LOG_MESSAGE
|
||||
description:
|
||||
'''
|
||||
Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled.
|
||||
|
||||
Log message payloads include `u8[Length]` containing the text, where the length of the text is the _broadcast_header.length_ field.
|
||||
|
||||
**Example Log Broadcast** -- log message "Hello QMK!"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) |
|
||||
'''
|
||||
}
|
||||
0x01: {
|
||||
name: Secure Status
|
||||
define: SECURE_STATUS
|
||||
description:
|
||||
'''
|
||||
Secure status has changed. Payloads include a `u8` matching a 'Secure Status' request.
|
||||
|
||||
**Example Secure Status Broadcast** -- secure "Unlocking"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Secure Status |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x01` | `0x01` | `0x01` |
|
||||
'''
|
||||
return_type: u8
|
||||
}
|
||||
0x02: {
|
||||
name: Keyboard
|
||||
define: KB
|
||||
description:
|
||||
'''
|
||||
Reserved for vendor-specific functionality. No messages are defined by XAP.
|
||||
'''
|
||||
},
|
||||
|
||||
0x03: {
|
||||
name: User
|
||||
define: USER
|
||||
description:
|
||||
'''
|
||||
Reserved for user-specific functionality. No messages are defined by XAP.
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
routes: {
|
||||
0x00: {
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_XAP_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Enabled subsystem query
|
||||
define: SUBSYSTEM_QUERY
|
||||
description:
|
||||
'''
|
||||
XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_CAPABILITIES
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Secure Status
|
||||
define: SECURE_STATUS
|
||||
description:
|
||||
'''
|
||||
Query secure route status
|
||||
|
||||
* 0 means secure routes are disabled
|
||||
* 1 means unlock sequence initiated but incomplete
|
||||
* 2 means secure routes are allowed
|
||||
* any other value should be interpreted as disabled
|
||||
'''
|
||||
return_type: u8
|
||||
return_execute: secure_status
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Secure Unlock
|
||||
define: SECURE_UNLOCK
|
||||
description: Initiate secure route unlock sequence
|
||||
return_execute: secure_unlock
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Secure Lock
|
||||
define: SECURE_LOCK
|
||||
description: Disable secure routes
|
||||
return_execute: secure_lock
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
0x01: {
|
||||
type: router
|
||||
name: QMK
|
||||
define: QMK
|
||||
description:
|
||||
'''
|
||||
This subsystem is always present, and provides the ability to address QMK-specific functionality.
|
||||
'''
|
||||
routes: {
|
||||
0x00: {
|
||||
type: command
|
||||
name: Version Query
|
||||
define: VERSION_QUERY
|
||||
description:
|
||||
'''
|
||||
QMK protocol version query.
|
||||
|
||||
* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`
|
||||
* e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: bcd-version
|
||||
return_constant: QMK_BCD_VERSION
|
||||
}
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_QMK_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Board identifiers
|
||||
define: BOARD_IDENTIFIERS
|
||||
description:
|
||||
'''
|
||||
Retrieves the set of identifying information for the board.
|
||||
'''
|
||||
return_type: struct
|
||||
return_struct_length: 10
|
||||
return_struct_members: [
|
||||
{
|
||||
type: u16
|
||||
name: Vendor ID
|
||||
},
|
||||
{
|
||||
type: u16
|
||||
name: Product ID
|
||||
},
|
||||
{
|
||||
type: u16
|
||||
name: Product Version
|
||||
},
|
||||
{
|
||||
type: u32
|
||||
name: QMK Unique Identifier
|
||||
}
|
||||
]
|
||||
return_constant: [
|
||||
VENDOR_ID
|
||||
PRODUCT_ID
|
||||
DEVICE_VER
|
||||
XAP_KEYBOARD_IDENTIFIER
|
||||
]
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Board Manufacturer
|
||||
define: BOARD_MANUFACTURER
|
||||
description: Retrieves the name of the manufacturer
|
||||
return_type: string
|
||||
return_constant: QSTR(MANUFACTURER)
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Product Name
|
||||
define: PRODUCT_NAME
|
||||
description: Retrieves the product name
|
||||
return_type: string
|
||||
return_constant: QSTR(PRODUCT)
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Config Blob Length
|
||||
define: CONFIG_BLOB_LEN
|
||||
description: Retrieves the length of the configuration data bundled within the firmware
|
||||
return_type: u16
|
||||
return_constant: CONFIG_BLOB_GZ_LEN
|
||||
}
|
||||
0x06: {
|
||||
type: command
|
||||
name: Config Blob Chunk
|
||||
define: CONFIG_BLOB_CHUNK
|
||||
description: Retrieves a chunk of the configuration data bundled within the firmware
|
||||
request_type: u16
|
||||
request_purpose: offset
|
||||
return_type: u8[32]
|
||||
return_execute: get_config_blob_chunk
|
||||
}
|
||||
0x07: {
|
||||
type: command
|
||||
name: Jump to bootloader
|
||||
define: BOOTLOADER_JUMP
|
||||
permissions: secure
|
||||
enable_if_preprocessor: defined(BOOTLOADER_JUMP_SUPPORTED)
|
||||
description:
|
||||
'''
|
||||
Jump to bootloader
|
||||
|
||||
May not be present - if QMK capabilities query returns “true”, then jump to bootloader is supported
|
||||
|
||||
* 0 means secure routes are disabled, and should be considered as a failure
|
||||
* 1 means successful, board will jump to bootloader
|
||||
'''
|
||||
return_type: u8
|
||||
return_execute: request_bootloader_jump
|
||||
}
|
||||
0x08: {
|
||||
type: command
|
||||
name: Hardware Identifier
|
||||
define: HARDWARE_ID
|
||||
description: Retrieves a unique identifier for the board.
|
||||
return_type: u32[4]
|
||||
return_execute: get_hardware_id
|
||||
}
|
||||
0x09: {
|
||||
type: command
|
||||
name: Reinitialize EEPROM
|
||||
define: EEPROM_RESET
|
||||
permissions: secure
|
||||
enable_if_preprocessor: !defined(NO_RESET)
|
||||
description:
|
||||
'''
|
||||
Reinitializes the keyboard's EEPROM (persistent memory)
|
||||
|
||||
May not be present - if QMK capabilities query returns “true”, then reinitialize is supported
|
||||
|
||||
* 0 means secure routes are disabled, and should be considered as a failure
|
||||
* 1 means successful, board will reinitialize and then reboot
|
||||
'''
|
||||
return_type: u8
|
||||
return_execute: request_eeprom_reset
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
0x02: {
|
||||
type: router
|
||||
name: Keyboard
|
||||
define: KB
|
||||
description:
|
||||
'''
|
||||
This subsystem is always present, and reserved for vendor-specific functionality. No routes are defined by XAP.
|
||||
'''
|
||||
routes: {
|
||||
}
|
||||
},
|
||||
|
||||
0x03: {
|
||||
type: router
|
||||
name: User
|
||||
define: USER
|
||||
description:
|
||||
'''
|
||||
This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP.
|
||||
'''
|
||||
routes: {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
{
|
||||
version: 0.2.0
|
||||
|
||||
routes: {
|
||||
0x04: {
|
||||
type: router
|
||||
name: Keymap
|
||||
define: KEYMAP
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for query of currently configured keycodes.
|
||||
'''
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
Keymap subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_KEYMAP_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Get Layer Count
|
||||
define: GET_LAYER_COUNT
|
||||
description: Query maximum number of layers that can be addressed within the keymap.
|
||||
return_type: u8
|
||||
return_execute: keymap_get_layer_count
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Get Keycode
|
||||
define: GET_KEYMAP_KEYCODE
|
||||
description: Query the Keycode at the requested location.
|
||||
request_type: struct
|
||||
request_struct_length: 3
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: Layer
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Row
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Column
|
||||
}
|
||||
]
|
||||
return_type: u16
|
||||
return_execute: get_keymap_keycode
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Get Encoder Keycode
|
||||
define: GET_ENCODER_KEYCODE
|
||||
description: Query the Keycode at the requested location.
|
||||
enable_if_preprocessor: defined(ENCODER_MAP_ENABLE)
|
||||
request_type: struct
|
||||
request_struct_length: 3
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: Layer
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Encoder
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Clockwise
|
||||
}
|
||||
]
|
||||
return_type: u16
|
||||
return_execute: get_encoder_keycode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x05: {
|
||||
type: router
|
||||
name: Remapping
|
||||
define: REMAPPING
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for live reassignment of keycodes without rebuilding the firmware.
|
||||
'''
|
||||
enable_if_preprocessor: defined(DYNAMIC_KEYMAP_ENABLE)
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
Remapping subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_REMAPPING_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Get Layer Count
|
||||
define: GET_DYNAMIC_LAYER_COUNT
|
||||
description: Query maximum number of layers that can be addressed within the keymap.
|
||||
return_type: u8
|
||||
return_constant: DYNAMIC_KEYMAP_LAYER_COUNT
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Set Keycode
|
||||
define: SET_KEYMAP_KEYCODE
|
||||
description: Modify the Keycode at the requested location.
|
||||
permissions: secure
|
||||
request_type: struct
|
||||
request_struct_length: 5
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: Layer
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Row
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Column
|
||||
},
|
||||
{
|
||||
type: u16
|
||||
name: Keycode
|
||||
}
|
||||
]
|
||||
return_execute: dynamic_keymap_set_keycode
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Set Encoder Keycode
|
||||
define: SET_ENCODER_KEYCODE
|
||||
permissions: secure
|
||||
description: Modify the Keycode at the requested location.
|
||||
enable_if_preprocessor: defined(ENCODER_MAP_ENABLE)
|
||||
request_type: struct
|
||||
request_struct_length: 5
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: Layer
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Encoder
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: Clockwise
|
||||
},
|
||||
{
|
||||
type: u16
|
||||
name: Keycode
|
||||
}
|
||||
]
|
||||
return_execute: dynamic_encoder_set_keycode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x06: {
|
||||
type: router
|
||||
name: Lighting
|
||||
define: LIGHTING
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for control over the lighting subsystem.
|
||||
'''
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
Lighting subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_LIGHTING_CAPABILITIES
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,396 +0,0 @@
|
||||
{
|
||||
version: 0.3.0
|
||||
|
||||
routes: {
|
||||
|
||||
0x06: {
|
||||
routes: {
|
||||
|
||||
0x02: {
|
||||
type: router
|
||||
name: backlight
|
||||
define: BACKLIGHT
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for control over the backlight subsystem.
|
||||
'''
|
||||
enable_if_preprocessor: defined(BACKLIGHT_ENABLE)
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
backlight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_LIGHTING_BACKLIGHT_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Get Enabled Effects
|
||||
define: GET_ENABLED_EFFECTS
|
||||
description: Each bit should be considered as a "usable" effect id
|
||||
return_type: u8
|
||||
return_constant: ENABLED_BACKLIGHT_EFFECTS
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Get Config
|
||||
define: GET_CONFIG
|
||||
description: Query the current config.
|
||||
return_type: struct
|
||||
return_struct_length: 3
|
||||
return_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
]
|
||||
return_execute: get_backlight_config
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Set Config
|
||||
define: SET_CONFIG
|
||||
description: Set the current config.
|
||||
request_type: struct
|
||||
request_struct_length: 3
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
]
|
||||
return_execute: set_backlight_config
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Save Config
|
||||
define: SAVE_CONFIG
|
||||
description: Save the current config.
|
||||
return_execute: save_backlight_config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x03: {
|
||||
type: router
|
||||
name: rgblight
|
||||
define: RGBLIGHT
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for control over the rgblight subsystem.
|
||||
'''
|
||||
enable_if_preprocessor: defined(RGBLIGHT_ENABLE)
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
rgblight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_LIGHTING_RGBLIGHT_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Get Enabled Effects
|
||||
define: GET_ENABLED_EFFECTS
|
||||
description: Each bit should be considered as a "usable" effect id
|
||||
return_type: u64
|
||||
return_constant: ENABLED_RGBLIGHT_EFFECTS
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Get Config
|
||||
define: GET_CONFIG
|
||||
description: Query the current config.
|
||||
return_type: struct
|
||||
return_struct_length: 6
|
||||
return_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: hue
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: sat
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: speed
|
||||
},
|
||||
]
|
||||
return_execute: get_rgblight_config
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Set Config
|
||||
define: SET_CONFIG
|
||||
description: Set the current config.
|
||||
request_type: struct
|
||||
request_struct_length: 6
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: hue
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: sat
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: speed
|
||||
},
|
||||
]
|
||||
return_execute: set_rgblight_config
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Save Config
|
||||
define: SAVE_CONFIG
|
||||
description: Save the current config.
|
||||
return_execute: save_rgblight_config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x04: {
|
||||
type: router
|
||||
name: rgbmatrix
|
||||
define: RGB_MATRIX
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for control over the rgb matrix subsystem.
|
||||
'''
|
||||
enable_if_preprocessor: defined(RGB_MATRIX_ENABLE)
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
rgb matrix subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_LIGHTING_RGB_MATRIX_CAPABILITIES
|
||||
}
|
||||
0x02: {
|
||||
type: command
|
||||
name: Get Enabled Effects
|
||||
define: GET_ENABLED_EFFECTS
|
||||
description: Each bit should be considered as a "usable" effect id
|
||||
return_type: u64
|
||||
return_constant: ENABLED_RGB_MATRIX_EFFECTS
|
||||
}
|
||||
0x03: {
|
||||
type: command
|
||||
name: Get Config
|
||||
define: GET_CONFIG
|
||||
description: Query the current config.
|
||||
return_type: struct
|
||||
return_struct_length: 7
|
||||
return_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: hue
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: sat
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: speed
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: flags
|
||||
},
|
||||
]
|
||||
return_execute: get_rgb_matrix_config
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Set Config
|
||||
define: SET_CONFIG
|
||||
description: Set the current config.
|
||||
request_type: struct
|
||||
request_struct_length: 7
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: mode
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: hue
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: sat
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: val
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: speed
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: flags
|
||||
},
|
||||
]
|
||||
return_execute: set_rgb_matrix_config
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Save Config
|
||||
define: SAVE_CONFIG
|
||||
description: Save the current config.
|
||||
return_execute: save_rgb_matrix_config
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
0x07: {
|
||||
type: router
|
||||
name: Audio
|
||||
define: AUDIO
|
||||
description:
|
||||
'''
|
||||
This subsystem allows for control over the audio subsystem.
|
||||
'''
|
||||
enable_if_preprocessor: defined(AUDIO_ENABLE)
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY
|
||||
description:
|
||||
'''
|
||||
Audio subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_AUDIO_CAPABILITIES
|
||||
}
|
||||
|
||||
0x03: {
|
||||
type: command
|
||||
name: Get Config
|
||||
define: GET_CONFIG
|
||||
description: Query the current config.
|
||||
return_type: struct
|
||||
return_struct_length: 2
|
||||
return_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: clicky_enable
|
||||
},
|
||||
]
|
||||
return_execute: get_audio_config
|
||||
}
|
||||
0x04: {
|
||||
type: command
|
||||
name: Set Config
|
||||
define: SET_CONFIG
|
||||
description: Set the current config.
|
||||
request_type: struct
|
||||
request_struct_length: 2
|
||||
request_struct_members: [
|
||||
{
|
||||
type: u8
|
||||
name: enable
|
||||
},
|
||||
{
|
||||
type: u8
|
||||
name: clicky_enable
|
||||
},
|
||||
]
|
||||
return_execute: set_audio_config
|
||||
}
|
||||
0x05: {
|
||||
type: command
|
||||
name: Save Config
|
||||
define: SAVE_CONFIG
|
||||
description: Save the current config.
|
||||
return_execute: save_audio_config
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -144,8 +144,7 @@
|
||||
{ "text": "Tri Layer", "link": "/features/tri_layer" },
|
||||
{ "text": "Unicode", "link": "/features/unicode" },
|
||||
{ "text": "Userspace", "link": "/feature_userspace" },
|
||||
{ "text": "WPM Calculation", "link": "/features/wpm" },
|
||||
{ "text": "XAP", "link": "/xap" }
|
||||
{ "text": "WPM Calculation", "link": "/features/wpm" }
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -340,6 +340,10 @@ There are a few different ways to set handedness for split keyboards (listed in
|
||||
* `#define SPLIT_TRANSACTION_IDS_USER .....`
|
||||
* Allows for custom data sync with the slave when using the QMK-provided split transport. See [custom data sync between sides](features/split_keyboard#custom-data-sync) for more information.
|
||||
|
||||
* `#define SYSTEM_CONTROL_USAGE_MINIMUM 0x0081`
|
||||
* `#define SYSTEM_CONTROL_USAGE_MAXIMUM 0x008F`
|
||||
* Sets the usage range reported by the System Control collection that `EXTRAKEY_ENABLE` adds. The default range covers the System Control usages QMK can send and stops below the Generic Desktop D-pad usages (`0x90` and up). Raising the maximum into that range makes some hosts detect the keyboard as a gamepad, so only widen it if you need the extra usages and know your host handles them. The minimum must not be greater than the maximum.
|
||||
|
||||
# The `rules.mk` File
|
||||
|
||||
This is a [make](https://www.gnu.org/software/make/manual/make.html) file that is included by the top-level `Makefile`. It is used to set some information about the MCU that we will be compiling for as well as enabling and disabling certain features.
|
||||
|
||||
+20
-5
@@ -191,7 +191,9 @@ void eeconfig_init_user_datablock(void);
|
||||
|
||||
:::::
|
||||
|
||||
### Example
|
||||
### Examples
|
||||
|
||||
#### Basic
|
||||
|
||||
This is an example of how to add settings, and read and write it. We're using the user keymap for the example here.
|
||||
|
||||
@@ -215,10 +217,6 @@ typedef struct my_config_t {
|
||||
static my_config_t config;
|
||||
|
||||
void keyboard_post_init_user(void) {
|
||||
if (!eeconfig_is_user_datablock_valid()) {
|
||||
eeconfig_init_user_datablock();
|
||||
}
|
||||
|
||||
eeconfig_read_user_datablock(&config, 0, sizeof(my_config_t));
|
||||
}
|
||||
|
||||
@@ -240,3 +238,20 @@ void housekeeping_task_user(void) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Default Values
|
||||
|
||||
Extending the above example, a default value for the datablock can be configured as follows:
|
||||
|
||||
```c
|
||||
void eeconfig_init_user_datablock(void) {
|
||||
my_config_t default_config = {
|
||||
.data = 42,
|
||||
};
|
||||
eeconfig_update_user_datablock(&default_config, 0, sizeof(my_config_t));
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
For large datablocks, you might need to manually update in chunks to avoid memory issues.
|
||||
:::
|
||||
|
||||
@@ -16,7 +16,8 @@ These functions allow you to activate layers in various ways. Note that layers a
|
||||
* `OSL(layer)` - momentarily activates *layer* until the next key is pressed. See [One Shot Keys](one_shot_keys) for details and additional functionality.
|
||||
* `TG(layer)` - toggles *layer*, activating it if it's inactive and vice versa
|
||||
* `TO(layer)` - activates *layer* and de-activates all other layers (except your default layer). This function is special, because instead of just adding/removing one layer to your active layer stack, it will completely replace your current active layers, uniquely allowing you to replace higher layers with a lower one. This is activated on keydown (as soon as the key is pressed).
|
||||
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
|
||||
* `TT(layer)` - Layer Tap-Toggle. If you hold the key down, *layer* is activated, and then is de-activated when you let go (like `MO`). If you repeatedly tap it, the layer will be toggled on or off (like `TG`). It needs 5 taps by default, but you can change this by defining `TAPPING_TOGGLE` -- for example, `#define TAPPING_TOGGLE 2` to toggle on just two taps.
|
||||
* Note: toggling behavior requires that [Quick Tap](tap_hold#quick-tap-term) is enabled (`QUICK_TAP_TERM` not set to `0`), or if `QUICK_TAP_TERM_PER_KEY` is defined, that `get_quick_tap_term()` returns a non-zero value for the `TT` key.
|
||||
|
||||
See also the [Layer Lock key](features/layer_lock), which locks the highest
|
||||
active layer until pressed again.
|
||||
|
||||
@@ -8,7 +8,7 @@ Replace the `KC_GRV` key in your keymap (usually to the left of the `1` key) wit
|
||||
|
||||
## What Your OS Sees
|
||||
|
||||
If Mary presses `QK_GESC` on her keyboard, the OS will see an KC_ESC character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>`</code> character.
|
||||
If Mary presses `QK_GESC` on her keyboard, the OS will see an `KC_ESC` character. Now if Mary holds Shift down and presses `QK_GESC` it will output `~`, or a shifted backtick. Now if she holds GUI/CMD/WIN, it will output a simple <code>`</code> character.
|
||||
|
||||
## Keycodes
|
||||
|
||||
|
||||
@@ -375,6 +375,10 @@ In this configuration "hold" takes place **after** tap dance timeout. To achieve
|
||||
|
||||
Tap dance can be used to emulate `MT()` and `LT()` behavior when the tapped code is not a basic keycode. This is useful to send tapped keycodes that normally require `Shift`, such as parentheses or curly braces—or other modified keycodes, such as `Control + X`.
|
||||
|
||||
::: tip
|
||||
For simply sending a non-basic keycode on tap while functioning as a modifier or layer switch on hold, a simpler (and often superior) alternative is to use a Mod-Tap or Layer-Tap key and intercept its tap function in `process_record_user()`. This avoids the complexity of Tap Dance, and allows the key to benefit from advanced Tap-Hold options. See [Intercepting Mod-Taps](../mod_tap#intercepting-mod-taps) for details.
|
||||
:::
|
||||
|
||||
Below your layers and custom keycodes, add the following:
|
||||
|
||||
```c
|
||||
|
||||
+3
-1
@@ -72,9 +72,11 @@ It can also be mitigated by increasing [`TAP_CODE_DELAY`](config_options#behavio
|
||||
|
||||
## Intercepting Mod-Taps
|
||||
|
||||
This technique works for both Mod-Tap (`MT`) and Layer-Tap (`LT`) keys.
|
||||
|
||||
### Changing tap function
|
||||
|
||||
The basic keycode limitation with Mod-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`:
|
||||
The basic keycode limitation with Mod-Tap and Layer-Tap can be worked around by intercepting it in `process_record_user`. For example, shifted keycode `KC_DQUO` cannot be used with `MT()` because it is a 16-bit keycode alias of `LSFT(KC_QUOT)`. Modifiers on `KC_DQUO` will be masked by `MT()`. But the following custom code can be used to intercept the "tap" function to manually send `KC_DQUO`:
|
||||
|
||||
```c
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
+25
-2
@@ -1,8 +1,12 @@
|
||||
# Tap-Hold Configuration Options
|
||||
|
||||
These options let you modify the behavior of the tap-hold keys, applying primarily to Mod-Tap `MT` and Layer-Tap `LT` keys. They also affect layer tap-toggle `TT`, one-shot `OSM`, `OSL`, and Swap Hands `SH_T`, `SH_TT` keys.
|
||||
|
||||
While Tap-Hold options are fantastic, they are not without their issues. We have tried to configure them with reasonable defaults, but that may still cause issues for some people.
|
||||
|
||||
These options let you modify the behavior of the tap-hold keys.
|
||||
::: info
|
||||
Besides the tapping term, tap-hold options do **not** apply to Tap Dance keys. Tap Dance implements a separate, simpler decision logic to track when keys are tapped vs. held, and it does not support advanced tap-hold configurations like Permissive Hold, Chordal Hold, etc.
|
||||
:::
|
||||
|
||||
## Tapping Term
|
||||
|
||||
@@ -148,6 +152,25 @@ uint16_t get_tapping_term(uint16_t keycode, keyrecord_t *record) {
|
||||
|
||||
The reason is that `TAPPING_TERM` is a macro that expands to a constant integer and thus cannot be changed at runtime, whereas `g_tapping_term` is a variable whose value can be changed at runtime. If you want, you can temporarily enable `DYNAMIC_TAPPING_TERM_ENABLE` to find a suitable tapping term value and then disable that feature and revert back to using the classic syntax for per-key tapping term settings. In case you need to access the tapping term from elsewhere in your code, you can use the `GET_TAPPING_TERM(keycode, record)` macro. This macro will expand to whatever is the appropriate access pattern given the current configuration.
|
||||
|
||||
## Configuring Home Row Mods
|
||||
|
||||
"Home row mods" (HRMs) is a popular layout technique where modifiers are placed as Mod-Tap keys on the home row (<kbd>A</kbd>, <kbd>S</kbd>, <kbd>D</kbd>, <kbd>F</kbd> and <kbd>J</kbd>, <kbd>K</kbd>, <kbd>L</kbd>, <kbd>;</kbd>, supposing QWERTY layout). This reduces hand movement and can increase comfort. However, because these keys are also used for fast typing, they are prone to accidental modifier triggers (when rolling keys) or accidental typed letters (when trying to use a modifier).
|
||||
|
||||
There is no single perfect configuration for home row mods, as it depends heavily on your typing speed and habits. However, a good starting point in QMK is (added in your `config.h`):
|
||||
|
||||
```c
|
||||
#define TAPPING_TERM 250
|
||||
#define PERMISSIVE_HOLD // Triggers mod if you tap another key while holding.
|
||||
#define CHORDAL_HOLD // Constrains holds to opposite-hand combinations.
|
||||
// Consider also:
|
||||
// #define FLOW_TAP_TERM 150 // Disables holds when typing quickly.
|
||||
```
|
||||
|
||||
See [Permissive Hold](#permissive-hold), [Chordal Hold](#chordal-hold), and [Flow Tap](#flow-tap) below for details on what they do and how to fine-tune them.
|
||||
|
||||
Additionally, [Speculative Hold](#speculative-hold) is useful to eliminate lag when combining a home row mod with mouse clicks (e.g., Shift + Click), as standard mod-tap keys do not send the modifier until the tap-hold decision is finalized.
|
||||
|
||||
|
||||
## Tap-Or-Hold Decision Modes
|
||||
|
||||
The code which decides between the tap and hold actions of dual-role keys supports three different modes, in increasing order of preference for the hold action:
|
||||
@@ -824,7 +847,7 @@ bool get_speculative_hold(uint16_t keycode, keyrecord_t* record) {
|
||||
}
|
||||
```
|
||||
|
||||
Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sometimes sends a lone modifier key press, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution.
|
||||
Some operating systems or applications assign actions to tapping a modifier key by itself, e.g., tapping GUI to open a start menu. Because Speculative Hold sends a lone modifier key press in some cases, it can falsely trigger these actions (known as the "flashing mods" problem). How such an input is handled depends on the OS and application, so unfortunately, there is no universal solution.
|
||||
|
||||
To mitigate this issue, you can set `DUMMY_MOD_NEUTRALIZER_KEYCODE` (and optionally `MODS_TO_NEUTRALIZE`) in your `config.h`, as described above for [Retro Tapping](#retro-tapping).
|
||||
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
# XAP
|
||||
|
||||
XAP (“extensible application protocol”) API intends to provide access to various QMK subsystems.
|
||||
|
||||
## Overview
|
||||
|
||||
```mermaid
|
||||
%%{init: {'themeVariables': { 'fontSize': '24px'}}}%%
|
||||
flowchart LR
|
||||
dev[QMK Device] <-- XAP --> host[Host Computer]
|
||||
```
|
||||
|
||||
The intention is to provide access to QMK subsystems through a versioned and documented protocol.
|
||||
|
||||
## Protocol Reference
|
||||
|
||||
[protocol_versions](xap_protocol.md ':include')
|
||||
|
||||
## Clients
|
||||
|
||||
TODO
|
||||
|
||||
## CLI
|
||||
|
||||
The QMK CLI provides a few XAP specific commands for diagnosis purposes.
|
||||
|
||||
### List Connected Devices
|
||||
Simple
|
||||
```
|
||||
$ qmk xap --list
|
||||
Ψ Available devices:
|
||||
Ψ 7844:8450 KPrepublic XD84 Pro [API:0.2.0] LOCKED
|
||||
```
|
||||
|
||||
Verbose
|
||||
```
|
||||
$ qmk --verbose xap --list
|
||||
Ψ Available devices:
|
||||
Ψ 7844:8450 KPrepublic XD84 Pro [API:0.2.0] LOCKED
|
||||
_id: 553831323538150A2113000000000000
|
||||
backlight.pin: F5
|
||||
bootloader: atmel-dfu
|
||||
community_layouts: 75_ansi, 75_iso
|
||||
debounce: 5
|
||||
diode_direction: COL2ROW
|
||||
features.audio: False
|
||||
features.backlight: True
|
||||
features.bootmagic: True
|
||||
features.command: False
|
||||
features.console: False
|
||||
features.extrakey: True
|
||||
features.mousekey: False
|
||||
features.nkro: True
|
||||
features.rgblight: True
|
||||
indicators.caps_lock: B2
|
||||
keyboard_folder: xiudi/xd84pro
|
||||
keyboard_name: XD84 Pro
|
||||
layouts: LAYOUT_75_ansi, LAYOUT_75_iso, LAYOUT_all
|
||||
maintainer: qmk
|
||||
manufacturer: KPrepublic
|
||||
matrix_pins.cols: B1, B3, B4, B5, B6, B7, C6, C7, D4, D6, D7, E6, F0, F1, F7
|
||||
matrix_pins.rows: D0, D1, D2, D3, D5, F4
|
||||
matrix_pins.unused: B0, E2
|
||||
matrix_size.cols: 15
|
||||
matrix_size.rows: 6
|
||||
mouse_key.enabled: False
|
||||
platform: unknown
|
||||
processor: atmega32u4
|
||||
processor_type: avr
|
||||
protocol: LUFA
|
||||
rgblight.animations.all: False
|
||||
rgblight.led_count: 12
|
||||
rgblight.pin: F6
|
||||
rgblight.sleep: False
|
||||
url:
|
||||
usb.device_ver: 0x0001
|
||||
usb.device_version: 0.0.1
|
||||
usb.pid: 0x8450
|
||||
usb.vid: 0x7844
|
||||
```
|
||||
|
||||
### Interactive shell
|
||||
```
|
||||
$ qmk xap -i
|
||||
Ψ Connected to:7844:8450 KPrepublic XD84 Pro
|
||||
Welcome to the XAP shell. Type help or ? to list commands.
|
||||
|
||||
Ψ> help
|
||||
|
||||
Documented commands (type help <topic>):
|
||||
========================================
|
||||
EOF about exit help keycode keymap layer listen unlock
|
||||
|
||||
Ψ>
|
||||
```
|
||||
@@ -1,108 +0,0 @@
|
||||
<!--- Copyright 2024 QMK --->
|
||||
<!--- SPDX-License-Identifier: GPL-2.0-or-later --->
|
||||
|
||||
<!---
|
||||
*******************************************************************************
|
||||
88888888888 888 d8b .d888 d8b 888 d8b
|
||||
888 888 Y8P d88P" Y8P 888 Y8P
|
||||
888 888 888 888
|
||||
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
|
||||
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
|
||||
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
|
||||
888 888 888 888 X88 888 888 888 Y8b. 888 X88
|
||||
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
|
||||
888 888
|
||||
888 888
|
||||
888 888
|
||||
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
|
||||
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
|
||||
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
|
||||
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
|
||||
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
|
||||
888
|
||||
Y8b d88P
|
||||
"Y88P"
|
||||
*******************************************************************************
|
||||
--->
|
||||
# QMK Firmware XAP Specs
|
||||
|
||||
This document describes the requirements of the QMK XAP ("extensible application protocol") API.
|
||||
|
||||
## Types
|
||||
|
||||
**All integral types are little-endian.**
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _type[n]_ | An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets. |
|
||||
| _u16_ | An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_. |
|
||||
| _u32_ | An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_. |
|
||||
| _u8_ | An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_. |
|
||||
|
||||
## Definitions
|
||||
|
||||
This list defines the terms used across the entire set of XAP protocol documentation.
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _Handler_ | A piece of code that is executed when a specific _route_ is received. |
|
||||
| _Payload_ | Any received data appended to the _route_, which gets delivered to the _handler_ when received. |
|
||||
| _Response_ | The data sent back to the host during execution of a _handler_. |
|
||||
| _Route_ | A sequence of _IDs_ describing the route to invoke a _handler_. |
|
||||
| _Subsystem_ | A high-level area of functionality within XAP. |
|
||||
| _ID_ | A single octet / 8-bit byte, representing Subsystem or Route index. |
|
||||
| _Request Header_ | Packet format for inbound data. Takes the format:<br>`token` - token<br>`u8` - length |
|
||||
| _Response Flags_ | An `u8` containing the status of the request. |
|
||||
| _Response Header_ | Packet format for outbound data. Takes the format:<br>`token` - token<br>`response_flags` - flags<br>`u8` - length |
|
||||
| _Token_ | A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`. |
|
||||
|
||||
## Requests and Responses
|
||||
|
||||
Communication generally follows a request/response pattern.
|
||||
|
||||
Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response.
|
||||
This allows response messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously.
|
||||
Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.
|
||||
To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
|
||||
This token is followed by a `u8` signifying the length of data in the request.
|
||||
|
||||
|
||||
|
||||
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
|
||||
|
||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
||||
| -- | -- | -- | -- | -- | -- | -- | -- |
|
||||
| `-` | `-` | `-` | `-` | `-` | `-` | `-` | `SUCCESS` |
|
||||
|
||||
* Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
|
||||
|
||||
### Example "conversation":
|
||||
|
||||
**Request** -- version query:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Payload Length | Route | Route |
|
||||
| **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` |
|
||||
|
||||
**Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` |
|
||||
|
||||
## Routes
|
||||
|
||||
Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01).
|
||||
This is the primary method for determining if a subsystem has been enabled in the running firmware.
|
||||
|
||||
### XAP - `0x00`
|
||||
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x00 0x00` | | __Response:__ `u32` | XAP protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
<!--- Copyright 2024 QMK --->
|
||||
<!--- SPDX-License-Identifier: GPL-2.0-or-later --->
|
||||
|
||||
<!---
|
||||
*******************************************************************************
|
||||
88888888888 888 d8b .d888 d8b 888 d8b
|
||||
888 888 Y8P d88P" Y8P 888 Y8P
|
||||
888 888 888 888
|
||||
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
|
||||
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
|
||||
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
|
||||
888 888 888 888 X88 888 888 888 Y8b. 888 X88
|
||||
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
|
||||
888 888
|
||||
888 888
|
||||
888 888
|
||||
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
|
||||
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
|
||||
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
|
||||
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
|
||||
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
|
||||
888
|
||||
Y8b d88P
|
||||
"Y88P"
|
||||
*******************************************************************************
|
||||
--->
|
||||
# QMK Firmware XAP Specs
|
||||
|
||||
This document describes the requirements of the QMK XAP ("extensible application protocol") API.
|
||||
|
||||
## Types
|
||||
|
||||
**All integral types are little-endian.**
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _bool_ | Data type that contains values 0 and 1. Implemented as an alias of `u8`. |
|
||||
| _struct{}_ | A structure of data, packing different objects together. Data is "compacted" -- there are no padding bytes between fields. Equivalent to a packed C-style `struct`. The order in which they're defined matches the order of the data in the response packet. |
|
||||
| _type[n]_ | An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets. |
|
||||
| _u16_ | An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_. |
|
||||
| _u32_ | An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_. |
|
||||
| _u64_ | An unsigned 64-bit integral, commonly seen as `uint64_t` from _stdint.h_. |
|
||||
| _u8_ | An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_. |
|
||||
|
||||
## Definitions
|
||||
|
||||
This list defines the terms used across the entire set of XAP protocol documentation.
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _Capability_ | A way to determine if certain functionality is enabled in the firmware. Any _subsystem_ that provides build-time restriction of functionality must provide a _route_ for a _capabilities query_. |
|
||||
| _Handler_ | A piece of code that is executed when a specific _route_ is received. |
|
||||
| _Payload_ | Any received data appended to the _route_, which gets delivered to the _handler_ when received. |
|
||||
| _Response_ | The data sent back to the host during execution of a _handler_. |
|
||||
| _Route_ | A sequence of _IDs_ describing the route to invoke a _handler_. |
|
||||
| _Secure Route_ | A _route_ which has potentially destructive consequences, necessitating prior approval by the user before executing. |
|
||||
| _Subsystem_ | A high-level area of functionality within XAP. |
|
||||
| _Unlock sequence_ | A physical sequence initiated by the user to enable execution of _secure routes_. |
|
||||
| _Broadcast Header_ | Packet format for broadcast messages. Takes the format:<br>`token` - token<br>`u8` - type<br>`u8` - length |
|
||||
| _ID_ | A single octet / 8-bit byte, representing Subsystem or Route index. |
|
||||
| _Request Header_ | Packet format for inbound data. Takes the format:<br>`token` - token<br>`u8` - length |
|
||||
| _Response Flags_ | An `u8` containing the status of the request. |
|
||||
| _Response Header_ | Packet format for outbound data. Takes the format:<br>`token` - token<br>`response_flags` - flags<br>`u8` - length |
|
||||
| _Token_ | A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`. |
|
||||
|
||||
## Requests and Responses
|
||||
|
||||
Communication generally follows a request/response pattern.
|
||||
|
||||
Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response.
|
||||
This allows response messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously.
|
||||
Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.
|
||||
To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
|
||||
This token is followed by a `u8` signifying the length of data in the request.
|
||||
|
||||
Two token values are reserved: `0xFFFE` and `0xFFFF`:
|
||||
* `0xFFFE`: A message sent by a host application may use this token if no response is to be sent -- a "fire and forget" message.
|
||||
* `0xFFFF`: Signifies a "broadcast" message sent by the firmware without prompting from the host application. Broadcast messages are defined later in this document.
|
||||
|
||||
Any request will generate at least one corresponding response, with the exception of messages using reserved tokens. Maximum total message length is 128 bytes due to RAM constraints.
|
||||
|
||||
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
|
||||
|
||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
||||
| -- | -- | -- | -- | -- | -- | -- | -- |
|
||||
| `-` | `-` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` |
|
||||
|
||||
* Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed.
|
||||
* Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
|
||||
|
||||
### Example "conversation":
|
||||
|
||||
**Request** -- version query:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Payload Length | Route | Route |
|
||||
| **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` |
|
||||
|
||||
**Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` |
|
||||
|
||||
## Routes
|
||||
|
||||
Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01).
|
||||
This is the primary method for determining if a subsystem has been enabled in the running firmware.
|
||||
|
||||
### XAP - `0x00`
|
||||
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x00 0x00` | | __Response:__ `u32` | XAP protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x00 0x01` | | __Response:__ `u32` | XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Enabled subsystem query | `0x00 0x02` | | __Response:__ `u32` | XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying.|
|
||||
| Secure Status | `0x00 0x03` | | __Response:__ `u8` | Query secure route status<br><br>* 0 means secure routes are disabled<br>* 1 means unlock sequence initiated but incomplete<br>* 2 means secure routes are allowed<br>* any other value should be interpreted as disabled|
|
||||
| Secure Unlock | `0x00 0x04` | | | Initiate secure route unlock sequence|
|
||||
| Secure Lock | `0x00 0x05` | | | Disable secure routes|
|
||||
|
||||
### QMK - `0x01`
|
||||
This subsystem is always present, and provides the ability to address QMK-specific functionality.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x01 0x00` | | __Response:__ `u32` | QMK protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x01 0x01` | | __Response:__ `u32` | QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Board identifiers | `0x01 0x02` | | __Response:__<br> * Vendor ID: `u16`<br> * Product ID: `u16`<br> * Product Version: `u16`<br> * QMK Unique Identifier: `u32` | Retrieves the set of identifying information for the board.|
|
||||
| Board Manufacturer | `0x01 0x03` | | __Response:__ `string` | Retrieves the name of the manufacturer|
|
||||
| Product Name | `0x01 0x04` | | __Response:__ `string` | Retrieves the product name|
|
||||
| Config Blob Length | `0x01 0x05` | | __Response:__ `u16` | Retrieves the length of the configuration data bundled within the firmware|
|
||||
| Config Blob Chunk | `0x01 0x06` | | __Request:__ `u16`<br><br>__Response:__ `u8[32]` | Retrieves a chunk of the configuration data bundled within the firmware|
|
||||
| Jump to bootloader | `0x01 0x07` | __Secure__ | __Response:__ `u8` | Jump to bootloader<br><br>May not be present - if QMK capabilities query returns “true”, then jump to bootloader is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will jump to bootloader|
|
||||
| Hardware Identifier | `0x01 0x08` | | __Response:__ `u32[4]` | Retrieves a unique identifier for the board.|
|
||||
| Reinitialize EEPROM | `0x01 0x09` | __Secure__ | __Response:__ `u8` | Reinitializes the keyboard's EEPROM (persistent memory)<br><br>May not be present - if QMK capabilities query returns “true”, then reinitialize is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will reinitialize and then reboot|
|
||||
|
||||
### Keyboard - `0x02`
|
||||
This subsystem is always present, and reserved for vendor-specific functionality. No routes are defined by XAP.
|
||||
|
||||
### User - `0x03`
|
||||
This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP.
|
||||
|
||||
|
||||
## Broadcast messages
|
||||
|
||||
Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, then the response _payload_ length, and finally the corresponding _payload_.
|
||||
|
||||
### Log message - `0x00`
|
||||
Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled.
|
||||
|
||||
Log message payloads include `u8[Length]` containing the text, where the length of the text is the _broadcast_header.length_ field.
|
||||
|
||||
**Example Log Broadcast** -- log message "Hello QMK!"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) |
|
||||
### Secure Status - `0x01`
|
||||
Secure status has changed. Payloads include a `u8` matching a 'Secure Status' request.
|
||||
|
||||
**Example Secure Status Broadcast** -- secure "Unlocking"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Secure Status |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x01` | `0x01` | `0x01` |
|
||||
### Keyboard - `0x02`
|
||||
Reserved for vendor-specific functionality. No messages are defined by XAP.
|
||||
### User - `0x03`
|
||||
Reserved for user-specific functionality. No messages are defined by XAP.
|
||||
|
||||
@@ -1,203 +0,0 @@
|
||||
<!--- Copyright 2024 QMK --->
|
||||
<!--- SPDX-License-Identifier: GPL-2.0-or-later --->
|
||||
|
||||
<!---
|
||||
*******************************************************************************
|
||||
88888888888 888 d8b .d888 d8b 888 d8b
|
||||
888 888 Y8P d88P" Y8P 888 Y8P
|
||||
888 888 888 888
|
||||
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
|
||||
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
|
||||
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
|
||||
888 888 888 888 X88 888 888 888 Y8b. 888 X88
|
||||
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
|
||||
888 888
|
||||
888 888
|
||||
888 888
|
||||
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
|
||||
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
|
||||
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
|
||||
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
|
||||
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
|
||||
888
|
||||
Y8b d88P
|
||||
"Y88P"
|
||||
*******************************************************************************
|
||||
--->
|
||||
# QMK Firmware XAP Specs
|
||||
|
||||
This document describes the requirements of the QMK XAP ("extensible application protocol") API.
|
||||
|
||||
## Types
|
||||
|
||||
**All integral types are little-endian.**
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _bool_ | Data type that contains values 0 and 1. Implemented as an alias of `u8`. |
|
||||
| _struct{}_ | A structure of data, packing different objects together. Data is "compacted" -- there are no padding bytes between fields. Equivalent to a packed C-style `struct`. The order in which they're defined matches the order of the data in the response packet. |
|
||||
| _type[n]_ | An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets. |
|
||||
| _u16_ | An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_. |
|
||||
| _u32_ | An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_. |
|
||||
| _u64_ | An unsigned 64-bit integral, commonly seen as `uint64_t` from _stdint.h_. |
|
||||
| _u8_ | An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_. |
|
||||
|
||||
## Definitions
|
||||
|
||||
This list defines the terms used across the entire set of XAP protocol documentation.
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _Capability_ | A way to determine if certain functionality is enabled in the firmware. Any _subsystem_ that provides build-time restriction of functionality must provide a _route_ for a _capabilities query_. |
|
||||
| _Handler_ | A piece of code that is executed when a specific _route_ is received. |
|
||||
| _Payload_ | Any received data appended to the _route_, which gets delivered to the _handler_ when received. |
|
||||
| _Response_ | The data sent back to the host during execution of a _handler_. |
|
||||
| _Route_ | A sequence of _IDs_ describing the route to invoke a _handler_. |
|
||||
| _Secure Route_ | A _route_ which has potentially destructive consequences, necessitating prior approval by the user before executing. |
|
||||
| _Subsystem_ | A high-level area of functionality within XAP. |
|
||||
| _Unlock sequence_ | A physical sequence initiated by the user to enable execution of _secure routes_. |
|
||||
| _Broadcast Header_ | Packet format for broadcast messages. Takes the format:<br>`token` - token<br>`u8` - type<br>`u8` - length |
|
||||
| _ID_ | A single octet / 8-bit byte, representing Subsystem or Route index. |
|
||||
| _Request Header_ | Packet format for inbound data. Takes the format:<br>`token` - token<br>`u8` - length |
|
||||
| _Response Flags_ | An `u8` containing the status of the request. |
|
||||
| _Response Header_ | Packet format for outbound data. Takes the format:<br>`token` - token<br>`response_flags` - flags<br>`u8` - length |
|
||||
| _Token_ | A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`. |
|
||||
|
||||
## Requests and Responses
|
||||
|
||||
Communication generally follows a request/response pattern.
|
||||
|
||||
Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response.
|
||||
This allows response messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously.
|
||||
Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.
|
||||
To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
|
||||
This token is followed by a `u8` signifying the length of data in the request.
|
||||
|
||||
Two token values are reserved: `0xFFFE` and `0xFFFF`:
|
||||
* `0xFFFE`: A message sent by a host application may use this token if no response is to be sent -- a "fire and forget" message.
|
||||
* `0xFFFF`: Signifies a "broadcast" message sent by the firmware without prompting from the host application. Broadcast messages are defined later in this document.
|
||||
|
||||
Any request will generate at least one corresponding response, with the exception of messages using reserved tokens. Maximum total message length is 128 bytes due to RAM constraints.
|
||||
|
||||
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
|
||||
|
||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
||||
| -- | -- | -- | -- | -- | -- | -- | -- |
|
||||
| `-` | `-` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` |
|
||||
|
||||
* Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed.
|
||||
* Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
|
||||
|
||||
### Example "conversation":
|
||||
|
||||
**Request** -- version query:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Payload Length | Route | Route |
|
||||
| **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` |
|
||||
|
||||
**Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` |
|
||||
|
||||
## Routes
|
||||
|
||||
Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01).
|
||||
This is the primary method for determining if a subsystem has been enabled in the running firmware.
|
||||
|
||||
### XAP - `0x00`
|
||||
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x00 0x00` | | __Response:__ `u32` | XAP protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x00 0x01` | | __Response:__ `u32` | XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Enabled subsystem query | `0x00 0x02` | | __Response:__ `u32` | XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying.|
|
||||
| Secure Status | `0x00 0x03` | | __Response:__ `u8` | Query secure route status<br><br>* 0 means secure routes are disabled<br>* 1 means unlock sequence initiated but incomplete<br>* 2 means secure routes are allowed<br>* any other value should be interpreted as disabled|
|
||||
| Secure Unlock | `0x00 0x04` | | | Initiate secure route unlock sequence|
|
||||
| Secure Lock | `0x00 0x05` | | | Disable secure routes|
|
||||
|
||||
### QMK - `0x01`
|
||||
This subsystem is always present, and provides the ability to address QMK-specific functionality.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x01 0x00` | | __Response:__ `u32` | QMK protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x01 0x01` | | __Response:__ `u32` | QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Board identifiers | `0x01 0x02` | | __Response:__<br> * Vendor ID: `u16`<br> * Product ID: `u16`<br> * Product Version: `u16`<br> * QMK Unique Identifier: `u32` | Retrieves the set of identifying information for the board.|
|
||||
| Board Manufacturer | `0x01 0x03` | | __Response:__ `string` | Retrieves the name of the manufacturer|
|
||||
| Product Name | `0x01 0x04` | | __Response:__ `string` | Retrieves the product name|
|
||||
| Config Blob Length | `0x01 0x05` | | __Response:__ `u16` | Retrieves the length of the configuration data bundled within the firmware|
|
||||
| Config Blob Chunk | `0x01 0x06` | | __Request:__ `u16`<br><br>__Response:__ `u8[32]` | Retrieves a chunk of the configuration data bundled within the firmware|
|
||||
| Jump to bootloader | `0x01 0x07` | __Secure__ | __Response:__ `u8` | Jump to bootloader<br><br>May not be present - if QMK capabilities query returns “true”, then jump to bootloader is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will jump to bootloader|
|
||||
| Hardware Identifier | `0x01 0x08` | | __Response:__ `u32[4]` | Retrieves a unique identifier for the board.|
|
||||
| Reinitialize EEPROM | `0x01 0x09` | __Secure__ | __Response:__ `u8` | Reinitializes the keyboard's EEPROM (persistent memory)<br><br>May not be present - if QMK capabilities query returns “true”, then reinitialize is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will reinitialize and then reboot|
|
||||
|
||||
### Keyboard - `0x02`
|
||||
This subsystem is always present, and reserved for vendor-specific functionality. No routes are defined by XAP.
|
||||
|
||||
### User - `0x03`
|
||||
This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP.
|
||||
|
||||
### Keymap - `0x04`
|
||||
This subsystem allows for query of currently configured keycodes.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x04 0x01` | | __Response:__ `u32` | Keymap subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Layer Count | `0x04 0x02` | | __Response:__ `u8` | Query maximum number of layers that can be addressed within the keymap.|
|
||||
| Get Keycode | `0x04 0x03` | | __Request:__<br> * Layer: `u8`<br> * Row: `u8`<br> * Column: `u8`<br><br>__Response:__ `u16` | Query the Keycode at the requested location.|
|
||||
| Get Encoder Keycode | `0x04 0x04` | | __Request:__<br> * Layer: `u8`<br> * Encoder: `u8`<br> * Clockwise: `u8`<br><br>__Response:__ `u16` | Query the Keycode at the requested location.|
|
||||
|
||||
### Remapping - `0x05`
|
||||
This subsystem allows for live reassignment of keycodes without rebuilding the firmware.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x05 0x01` | | __Response:__ `u32` | Remapping subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Layer Count | `0x05 0x02` | | __Response:__ `u8` | Query maximum number of layers that can be addressed within the keymap.|
|
||||
| Set Keycode | `0x05 0x03` | __Secure__ | __Request:__<br> * Layer: `u8`<br> * Row: `u8`<br> * Column: `u8`<br> * Keycode: `u16` | Modify the Keycode at the requested location.|
|
||||
| Set Encoder Keycode | `0x05 0x04` | __Secure__ | __Request:__<br> * Layer: `u8`<br> * Encoder: `u8`<br> * Clockwise: `u8`<br> * Keycode: `u16` | Modify the Keycode at the requested location.|
|
||||
|
||||
### Lighting - `0x06`
|
||||
This subsystem allows for control over the lighting subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x06 0x01` | | __Response:__ `u32` | Lighting subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
|
||||
|
||||
## Broadcast messages
|
||||
|
||||
Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, then the response _payload_ length, and finally the corresponding _payload_.
|
||||
|
||||
### Log message - `0x00`
|
||||
Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled.
|
||||
|
||||
Log message payloads include `u8[Length]` containing the text, where the length of the text is the _broadcast_header.length_ field.
|
||||
|
||||
**Example Log Broadcast** -- log message "Hello QMK!"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) |
|
||||
### Secure Status - `0x01`
|
||||
Secure status has changed. Payloads include a `u8` matching a 'Secure Status' request.
|
||||
|
||||
**Example Secure Status Broadcast** -- secure "Unlocking"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Secure Status |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x01` | `0x01` | `0x01` |
|
||||
### Keyboard - `0x02`
|
||||
Reserved for vendor-specific functionality. No messages are defined by XAP.
|
||||
### User - `0x03`
|
||||
Reserved for user-specific functionality. No messages are defined by XAP.
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
<!--- Copyright 2024 QMK --->
|
||||
<!--- SPDX-License-Identifier: GPL-2.0-or-later --->
|
||||
|
||||
<!---
|
||||
*******************************************************************************
|
||||
88888888888 888 d8b .d888 d8b 888 d8b
|
||||
888 888 Y8P d88P" Y8P 888 Y8P
|
||||
888 888 888 888
|
||||
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
|
||||
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
|
||||
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
|
||||
888 888 888 888 X88 888 888 888 Y8b. 888 X88
|
||||
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
|
||||
888 888
|
||||
888 888
|
||||
888 888
|
||||
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
|
||||
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
|
||||
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
|
||||
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
|
||||
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
|
||||
888
|
||||
Y8b d88P
|
||||
"Y88P"
|
||||
*******************************************************************************
|
||||
--->
|
||||
# QMK Firmware XAP Specs
|
||||
|
||||
This document describes the requirements of the QMK XAP ("extensible application protocol") API.
|
||||
|
||||
## Types
|
||||
|
||||
**All integral types are little-endian.**
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _bool_ | Data type that contains values 0 and 1. Implemented as an alias of `u8`. |
|
||||
| _struct{}_ | A structure of data, packing different objects together. Data is "compacted" -- there are no padding bytes between fields. Equivalent to a packed C-style `struct`. The order in which they're defined matches the order of the data in the response packet. |
|
||||
| _type[n]_ | An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets. |
|
||||
| _u16_ | An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_. |
|
||||
| _u32_ | An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_. |
|
||||
| _u64_ | An unsigned 64-bit integral, commonly seen as `uint64_t` from _stdint.h_. |
|
||||
| _u8_ | An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_. |
|
||||
|
||||
## Definitions
|
||||
|
||||
This list defines the terms used across the entire set of XAP protocol documentation.
|
||||
|
||||
| Name | Definition |
|
||||
| -- | -- |
|
||||
| _Capability_ | A way to determine if certain functionality is enabled in the firmware. Any _subsystem_ that provides build-time restriction of functionality must provide a _route_ for a _capabilities query_. |
|
||||
| _Handler_ | A piece of code that is executed when a specific _route_ is received. |
|
||||
| _Payload_ | Any received data appended to the _route_, which gets delivered to the _handler_ when received. |
|
||||
| _Response_ | The data sent back to the host during execution of a _handler_. |
|
||||
| _Route_ | A sequence of _IDs_ describing the route to invoke a _handler_. |
|
||||
| _Secure Route_ | A _route_ which has potentially destructive consequences, necessitating prior approval by the user before executing. |
|
||||
| _Subsystem_ | A high-level area of functionality within XAP. |
|
||||
| _Unlock sequence_ | A physical sequence initiated by the user to enable execution of _secure routes_. |
|
||||
| _Broadcast Header_ | Packet format for broadcast messages. Takes the format:<br>`token` - token<br>`u8` - type<br>`u8` - length |
|
||||
| _ID_ | A single octet / 8-bit byte, representing Subsystem or Route index. |
|
||||
| _Request Header_ | Packet format for inbound data. Takes the format:<br>`token` - token<br>`u8` - length |
|
||||
| _Response Flags_ | An `u8` containing the status of the request. |
|
||||
| _Response Header_ | Packet format for outbound data. Takes the format:<br>`token` - token<br>`response_flags` - flags<br>`u8` - length |
|
||||
| _Token_ | A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`. |
|
||||
|
||||
## Requests and Responses
|
||||
|
||||
Communication generally follows a request/response pattern.
|
||||
|
||||
Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response.
|
||||
This allows response messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously.
|
||||
Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.
|
||||
To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
|
||||
|
||||
This token is followed by a `u8` signifying the length of data in the request.
|
||||
|
||||
Two token values are reserved: `0xFFFE` and `0xFFFF`:
|
||||
* `0xFFFE`: A message sent by a host application may use this token if no response is to be sent -- a "fire and forget" message.
|
||||
* `0xFFFF`: Signifies a "broadcast" message sent by the firmware without prompting from the host application. Broadcast messages are defined later in this document.
|
||||
|
||||
Any request will generate at least one corresponding response, with the exception of messages using reserved tokens. Maximum total message length is 128 bytes due to RAM constraints.
|
||||
|
||||
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
|
||||
|
||||
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|
||||
| -- | -- | -- | -- | -- | -- | -- | -- |
|
||||
| `-` | `-` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` |
|
||||
|
||||
* Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed.
|
||||
* Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
|
||||
|
||||
### Example "conversation":
|
||||
|
||||
**Request** -- version query:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Payload Length | Route | Route |
|
||||
| **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` |
|
||||
|
||||
**Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192:
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` |
|
||||
|
||||
## Routes
|
||||
|
||||
Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01).
|
||||
This is the primary method for determining if a subsystem has been enabled in the running firmware.
|
||||
|
||||
### XAP - `0x00`
|
||||
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x00 0x00` | | __Response:__ `u32` | XAP protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x00 0x01` | | __Response:__ `u32` | XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Enabled subsystem query | `0x00 0x02` | | __Response:__ `u32` | XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying.|
|
||||
| Secure Status | `0x00 0x03` | | __Response:__ `u8` | Query secure route status<br><br>* 0 means secure routes are disabled<br>* 1 means unlock sequence initiated but incomplete<br>* 2 means secure routes are allowed<br>* any other value should be interpreted as disabled|
|
||||
| Secure Unlock | `0x00 0x04` | | | Initiate secure route unlock sequence|
|
||||
| Secure Lock | `0x00 0x05` | | | Disable secure routes|
|
||||
|
||||
### QMK - `0x01`
|
||||
This subsystem is always present, and provides the ability to address QMK-specific functionality.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Version Query | `0x01 0x00` | | __Response:__ `u32` | QMK protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br> * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
|
||||
| Capabilities Query | `0x01 0x01` | | __Response:__ `u32` | QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Board identifiers | `0x01 0x02` | | __Response:__<br> * Vendor ID: `u16`<br> * Product ID: `u16`<br> * Product Version: `u16`<br> * QMK Unique Identifier: `u32` | Retrieves the set of identifying information for the board.|
|
||||
| Board Manufacturer | `0x01 0x03` | | __Response:__ `string` | Retrieves the name of the manufacturer|
|
||||
| Product Name | `0x01 0x04` | | __Response:__ `string` | Retrieves the product name|
|
||||
| Config Blob Length | `0x01 0x05` | | __Response:__ `u16` | Retrieves the length of the configuration data bundled within the firmware|
|
||||
| Config Blob Chunk | `0x01 0x06` | | __Request:__ `u16`<br><br>__Response:__ `u8[32]` | Retrieves a chunk of the configuration data bundled within the firmware|
|
||||
| Jump to bootloader | `0x01 0x07` | __Secure__ | __Response:__ `u8` | Jump to bootloader<br><br>May not be present - if QMK capabilities query returns “true”, then jump to bootloader is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will jump to bootloader|
|
||||
| Hardware Identifier | `0x01 0x08` | | __Response:__ `u32[4]` | Retrieves a unique identifier for the board.|
|
||||
| Reinitialize EEPROM | `0x01 0x09` | __Secure__ | __Response:__ `u8` | Reinitializes the keyboard's EEPROM (persistent memory)<br><br>May not be present - if QMK capabilities query returns “true”, then reinitialize is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will reinitialize and then reboot|
|
||||
|
||||
### Keyboard - `0x02`
|
||||
This subsystem is always present, and reserved for vendor-specific functionality. No routes are defined by XAP.
|
||||
|
||||
### User - `0x03`
|
||||
This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP.
|
||||
|
||||
### Keymap - `0x04`
|
||||
This subsystem allows for query of currently configured keycodes.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x04 0x01` | | __Response:__ `u32` | Keymap subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Layer Count | `0x04 0x02` | | __Response:__ `u8` | Query maximum number of layers that can be addressed within the keymap.|
|
||||
| Get Keycode | `0x04 0x03` | | __Request:__<br> * Layer: `u8`<br> * Row: `u8`<br> * Column: `u8`<br><br>__Response:__ `u16` | Query the Keycode at the requested location.|
|
||||
| Get Encoder Keycode | `0x04 0x04` | | __Request:__<br> * Layer: `u8`<br> * Encoder: `u8`<br> * Clockwise: `u8`<br><br>__Response:__ `u16` | Query the Keycode at the requested location.|
|
||||
|
||||
### Remapping - `0x05`
|
||||
This subsystem allows for live reassignment of keycodes without rebuilding the firmware.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x05 0x01` | | __Response:__ `u32` | Remapping subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Layer Count | `0x05 0x02` | | __Response:__ `u8` | Query maximum number of layers that can be addressed within the keymap.|
|
||||
| Set Keycode | `0x05 0x03` | __Secure__ | __Request:__<br> * Layer: `u8`<br> * Row: `u8`<br> * Column: `u8`<br> * Keycode: `u16` | Modify the Keycode at the requested location.|
|
||||
| Set Encoder Keycode | `0x05 0x04` | __Secure__ | __Request:__<br> * Layer: `u8`<br> * Encoder: `u8`<br> * Clockwise: `u8`<br> * Keycode: `u16` | Modify the Keycode at the requested location.|
|
||||
|
||||
### Lighting - `0x06`
|
||||
This subsystem allows for control over the lighting subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x06 0x01` | | __Response:__ `u32` | Lighting subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
|
||||
|
||||
#### backlight - `0x06 0x02`
|
||||
This subsystem allows for control over the backlight subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x06 0x02 0x01` | | __Response:__ `u32` | backlight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Enabled Effects | `0x06 0x02 0x02` | | __Response:__ `u8` | Each bit should be considered as a "usable" effect id|
|
||||
| Get Config | `0x06 0x02 0x03` | | __Response:__<br> * enable: `u8`<br> * mode: `u8`<br> * val: `u8` | Query the current config.|
|
||||
| Set Config | `0x06 0x02 0x04` | | __Request:__<br> * enable: `u8`<br> * mode: `u8`<br> * val: `u8` | Set the current config.|
|
||||
| Save Config | `0x06 0x02 0x05` | | | Save the current config.|
|
||||
|
||||
|
||||
#### rgblight - `0x06 0x03`
|
||||
This subsystem allows for control over the rgblight subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x06 0x03 0x01` | | __Response:__ `u32` | rgblight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Enabled Effects | `0x06 0x03 0x02` | | __Response:__ `u64` | Each bit should be considered as a "usable" effect id|
|
||||
| Get Config | `0x06 0x03 0x03` | | __Response:__<br> * enable: `u8`<br> * mode: `u8`<br> * hue: `u8`<br> * sat: `u8`<br> * val: `u8`<br> * speed: `u8` | Query the current config.|
|
||||
| Set Config | `0x06 0x03 0x04` | | __Request:__<br> * enable: `u8`<br> * mode: `u8`<br> * hue: `u8`<br> * sat: `u8`<br> * val: `u8`<br> * speed: `u8` | Set the current config.|
|
||||
| Save Config | `0x06 0x03 0x05` | | | Save the current config.|
|
||||
|
||||
|
||||
#### rgbmatrix - `0x06 0x04`
|
||||
This subsystem allows for control over the rgb matrix subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x06 0x04 0x01` | | __Response:__ `u32` | rgb matrix subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Enabled Effects | `0x06 0x04 0x02` | | __Response:__ `u64` | Each bit should be considered as a "usable" effect id|
|
||||
| Get Config | `0x06 0x04 0x03` | | __Response:__<br> * enable: `u8`<br> * mode: `u8`<br> * hue: `u8`<br> * sat: `u8`<br> * val: `u8`<br> * speed: `u8`<br> * flags: `u8` | Query the current config.|
|
||||
| Set Config | `0x06 0x04 0x04` | | __Request:__<br> * enable: `u8`<br> * mode: `u8`<br> * hue: `u8`<br> * sat: `u8`<br> * val: `u8`<br> * speed: `u8`<br> * flags: `u8` | Set the current config.|
|
||||
| Save Config | `0x06 0x04 0x05` | | | Save the current config.|
|
||||
|
||||
### Audio - `0x07`
|
||||
This subsystem allows for control over the audio subsystem.
|
||||
|
||||
| Name | Route | Tags | Payloads | Description |
|
||||
| -- | -- | -- | -- | -- |
|
||||
| Capabilities Query | `0x07 0x01` | | __Response:__ `u32` | Audio subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
|
||||
| Get Config | `0x07 0x03` | | __Response:__<br> * enable: `u8`<br> * clicky_enable: `u8` | Query the current config.|
|
||||
| Set Config | `0x07 0x04` | | __Request:__<br> * enable: `u8`<br> * clicky_enable: `u8` | Set the current config.|
|
||||
| Save Config | `0x07 0x05` | | | Save the current config.|
|
||||
|
||||
|
||||
## Broadcast messages
|
||||
|
||||
Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, then the response _payload_ length, and finally the corresponding _payload_.
|
||||
|
||||
### Log message - `0x00`
|
||||
Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled.
|
||||
|
||||
Log message payloads include `u8[Length]` containing the text, where the length of the text is the _broadcast_header.length_ field.
|
||||
|
||||
**Example Log Broadcast** -- log message "Hello QMK!"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) |
|
||||
### Secure Status - `0x01`
|
||||
Secure status has changed. Payloads include a `u8` matching a 'Secure Status' request.
|
||||
|
||||
**Example Secure Status Broadcast** -- secure "Unlocking"
|
||||
|
||||
| Byte | 0 | 1 | 2 | 3 | 4 |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| **Purpose** | Token | Token | Broadcast Type | Length | Secure Status |
|
||||
| **Value** | `0xFF` | `0xFF` | `0x01` | `0x01` | `0x01` |
|
||||
### Keyboard - `0x02`
|
||||
Reserved for vendor-specific functionality. No messages are defined by XAP.
|
||||
### User - `0x03`
|
||||
Reserved for user-specific functionality. No messages are defined by XAP.
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<!--- Copyright 2024 QMK --->
|
||||
<!--- SPDX-License-Identifier: GPL-2.0-or-later --->
|
||||
|
||||
<!---
|
||||
*******************************************************************************
|
||||
88888888888 888 d8b .d888 d8b 888 d8b
|
||||
888 888 Y8P d88P" Y8P 888 Y8P
|
||||
888 888 888 888
|
||||
888 88888b. 888 .d8888b 888888 888 888 .d88b. 888 .d8888b
|
||||
888 888 "88b 888 88K 888 888 888 d8P Y8b 888 88K
|
||||
888 888 888 888 "Y8888b. 888 888 888 88888888 888 "Y8888b.
|
||||
888 888 888 888 X88 888 888 888 Y8b. 888 X88
|
||||
888 888 888 888 88888P' 888 888 888 "Y8888 888 88888P'
|
||||
888 888
|
||||
888 888
|
||||
888 888
|
||||
.d88b. .d88b. 88888b. .d88b. 888d888 8888b. 888888 .d88b. .d88888
|
||||
d88P"88b d8P Y8b 888 "88b d8P Y8b 888P" "88b 888 d8P Y8b d88" 888
|
||||
888 888 88888888 888 888 88888888 888 .d888888 888 88888888 888 888
|
||||
Y88b 888 Y8b. 888 888 Y8b. 888 888 888 Y88b. Y8b. Y88b 888
|
||||
"Y88888 "Y8888 888 888 "Y8888 888 "Y888888 "Y888 "Y8888 "Y88888
|
||||
888
|
||||
Y8b d88P
|
||||
"Y88P"
|
||||
*******************************************************************************
|
||||
--->
|
||||
* [XAP Version 0.3.0](xap_0.3.0.md)
|
||||
* [XAP Version 0.2.0](xap_0.2.0.md)
|
||||
* [XAP Version 0.1.0](xap_0.1.0.md)
|
||||
* [XAP Version 0.0.1](xap_0.0.1.md)
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"board": "GENERIC_RP_RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"diode_direction": "COL2ROW",
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"extrakey": true,
|
||||
"mousekey": true
|
||||
},
|
||||
"processor": "RP2040",
|
||||
"ps2": {
|
||||
"driver": "vendor",
|
||||
"enabled": true,
|
||||
"mouse_enabled": true
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT_iso": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
|
||||
{"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
|
||||
{"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
|
||||
{"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
|
||||
{"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
|
||||
{"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
|
||||
{"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
|
||||
{"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
|
||||
{"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
|
||||
{"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
|
||||
{"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
|
||||
{"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
|
||||
{"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
|
||||
{"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
|
||||
{"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
|
||||
{"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
|
||||
{"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
|
||||
{"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
|
||||
{"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
|
||||
{"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
|
||||
{"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
|
||||
{"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
|
||||
{"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
|
||||
{"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
|
||||
{"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
|
||||
{"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
|
||||
{"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
|
||||
{"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
|
||||
{"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
|
||||
{"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
|
||||
{"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
|
||||
{"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
|
||||
{"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
|
||||
{"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
|
||||
{"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
|
||||
{"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
|
||||
{"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
|
||||
{"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
|
||||
{"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
|
||||
{"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
|
||||
{"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
|
||||
{"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
|
||||
{"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
|
||||
{"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
|
||||
{"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
|
||||
{"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
|
||||
{"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
|
||||
{"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
|
||||
{"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
|
||||
{"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
|
||||
{"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
|
||||
{"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
|
||||
{"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
|
||||
{"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
|
||||
{"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
|
||||
{"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
|
||||
{"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
|
||||
{"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
|
||||
{"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
|
||||
{"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
|
||||
{"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
|
||||
{"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
|
||||
{"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
|
||||
{"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
|
||||
{"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
|
||||
{"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
|
||||
{"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"manufacturer": "Frank Adams",
|
||||
"keyboard_name": "converter/thinkpad_t6x/pico_t61",
|
||||
"maintainer": "Al En",
|
||||
"matrix_pins": {
|
||||
"cols": ["GP27", "GP26", "GP17", "GP14", "GP12", "GP19", "GP18", "GP15", "GP13", "GP6", "GP16", "GP5", "GP28", "GP2", "GP4", "GP3"],
|
||||
"rows": ["GP11", "GP22", "GP10", "GP21", "GP9", "GP20", "GP8", "GP7"]
|
||||
},
|
||||
"ps2": {
|
||||
"clock_pin": "GP0",
|
||||
"data_pin": "GP1"
|
||||
},
|
||||
"url": "https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard",
|
||||
"usb": {
|
||||
"device_version": "1.0.0",
|
||||
"pid": "0xBACA",
|
||||
"vid": "0xFEED"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
# converter/thinkpad_t6x/pico_t61
|
||||
|
||||

|
||||
|
||||
This is a converter PCB for Lenovo Thinkpad keyboards from T60, T400 and X200 series, based on the Raspberry Pi Pico W. The QMK implementation here is specific to the converter in the link below. Similar PCB designs to convert a Thinkpad keyboard to USB exist, but they use a different microcontroller and wiring of the keyboard connector with the MCU.
|
||||
|
||||
* Keyboard Maintainer: [Al En](https://github.com/gitaen)
|
||||
* Hardware Supported: The linked converter PCB with keyboards from various Thinkpad models
|
||||
* Hardware Availability: [Custom PCB](https://github.com/thedalles77/USB_Laptop_Keyboard_Controller/tree/master/Example_Keyboards/Pico_T61_Keyboard)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
make converter/thinkpad_t6x/pico_t61:default
|
||||
|
||||
Flashing example for this keyboard:
|
||||
|
||||
make converter/thinkpad_t6x/pico_t61:default:flash
|
||||
|
||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||
|
||||
## Bootloader
|
||||
|
||||
Enter the bootloader in 3 ways:
|
||||
|
||||
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (\`~) and plug in the keyboard
|
||||
* **Physical BOOTSEL button**: Hold down the BOOTSEL button on the Raspberry PiPico W and plug the keyboard
|
||||
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
|
||||
@@ -2,130 +2,18 @@
|
||||
"manufacturer": "strobo5",
|
||||
"keyboard_name": "converter/thinkpad_t6x/rpi_pico",
|
||||
"maintainer": "strobo5",
|
||||
"board": "GENERIC_RP_RP2040",
|
||||
"bootloader": "rp2040",
|
||||
"diode_direction": "COL2ROW",
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"extrakey": true,
|
||||
"mousekey": true
|
||||
},
|
||||
"matrix_pins": {
|
||||
"cols": ["GP7", "GP9", "GP11", "GP13", "GP17", "GP16", "GP14", "GP12", "GP15", "GP8", "GP10", "GP6", "GP4", "GP2", "GP5", "GP3"],
|
||||
"rows": ["GP20", "GP26", "GP22", "GP21", "GP18", "GP19", "GP27", "GP28"]
|
||||
},
|
||||
"processor": "RP2040",
|
||||
"ps2": {
|
||||
"clock_pin": "GP1",
|
||||
"data_pin": "GP0",
|
||||
"driver": "vendor",
|
||||
"enabled": true,
|
||||
"mouse_enabled": true
|
||||
"data_pin": "GP0"
|
||||
},
|
||||
"url": "https://github.com/strobo5/T61_PiPico_Scanner",
|
||||
"usb": {
|
||||
"device_version": "1.0.0",
|
||||
"pid": "0x0000",
|
||||
"vid": "0xFEED"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT_iso": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [5, 0], "x": 0, "y": 0, "w": 0.9, "h": 0.75},
|
||||
{"label": "Mute", "matrix": [4, 10], "x": 0.9, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "Vol -", "matrix": [3, 10], "x": 1.65, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "Vol +", "matrix": [2, 10], "x": 2.4, "y": 0, "w": 0.75, "h": 0.5},
|
||||
{"label": "ThinkVantage", "matrix": [5, 10], "x": 3.5, "y": 0, "w": 1.25, "h": 0.5},
|
||||
{"label": "PrtSc", "matrix": [1, 13], "x": 8.9, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "ScrLk", "matrix": [2, 13], "x": 9.8, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Pause", "matrix": [6, 12], "x": 10.7, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Insert", "matrix": [0, 9], "x": 12, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "Home", "matrix": [0, 12], "x": 12.9, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "PgUp", "matrix": [0, 11], "x": 13.8, "y": 0, "w": 0.9, "h": 0.65},
|
||||
{"label": "F1", "matrix": [0, 1], "x": 0, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F2", "matrix": [0, 2], "x": 0.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F3", "matrix": [3, 2], "x": 1.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F4", "matrix": [5, 2], "x": 2.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F5", "matrix": [5, 8], "x": 4, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F6", "matrix": [5, 5], "x": 4.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F7", "matrix": [3, 6], "x": 5.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F8", "matrix": [0, 6], "x": 6.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F9", "matrix": [0, 8], "x": 8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F10", "matrix": [1, 8], "x": 8.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F11", "matrix": [1, 10], "x": 9.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "F12", "matrix": [1, 9], "x": 10.7, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "Delete", "matrix": [0, 10], "x": 12, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "End", "matrix": [1, 12], "x": 12.9, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "PgDn", "matrix": [1, 11], "x": 13.8, "y": 0.75, "w": 0.9, "h": 0.65},
|
||||
{"label": "`\u00ac", "matrix": [0, 0], "x": 0, "y": 1.4},
|
||||
{"label": "1!", "matrix": [1, 0], "x": 1, "y": 1.4},
|
||||
{"label": "2\"", "matrix": [1, 1], "x": 2, "y": 1.4},
|
||||
{"label": "3\u00a3", "matrix": [1, 2], "x": 3, "y": 1.4},
|
||||
{"label": "4$", "matrix": [1, 3], "x": 4, "y": 1.4},
|
||||
{"label": "5%", "matrix": [0, 3], "x": 5, "y": 1.4},
|
||||
{"label": "6^", "matrix": [0, 4], "x": 6, "y": 1.4},
|
||||
{"label": "7&", "matrix": [1, 4], "x": 7, "y": 1.4},
|
||||
{"label": "8*", "matrix": [1, 5], "x": 8, "y": 1.4},
|
||||
{"label": "9(", "matrix": [1, 6], "x": 9, "y": 1.4},
|
||||
{"label": "0)", "matrix": [1, 7], "x": 10, "y": 1.4},
|
||||
{"label": "-_", "matrix": [0, 7], "x": 11, "y": 1.4},
|
||||
{"label": "=+", "matrix": [0, 5], "x": 12, "y": 1.4},
|
||||
{"label": "Bksp", "matrix": [3, 8], "x": 13, "y": 1.4, "w": 2},
|
||||
{"label": "Tab", "matrix": [3, 0], "x": 0, "y": 2.4, "w": 1.5},
|
||||
{"label": "Q", "matrix": [2, 0], "x": 1.5, "y": 2.4},
|
||||
{"label": "W", "matrix": [2, 1], "x": 2.5, "y": 2.4},
|
||||
{"label": "E", "matrix": [2, 2], "x": 3.5, "y": 2.4},
|
||||
{"label": "R", "matrix": [2, 3], "x": 4.5, "y": 2.4},
|
||||
{"label": "T", "matrix": [3, 3], "x": 5.5, "y": 2.4},
|
||||
{"label": "Y", "matrix": [3, 4], "x": 6.5, "y": 2.4},
|
||||
{"label": "U", "matrix": [2, 4], "x": 7.5, "y": 2.4},
|
||||
{"label": "I", "matrix": [2, 5], "x": 8.5, "y": 2.4},
|
||||
{"label": "O", "matrix": [2, 6], "x": 9.5, "y": 2.4},
|
||||
{"label": "P", "matrix": [2, 7], "x": 10.5, "y": 2.4},
|
||||
{"label": "[{", "matrix": [3, 7], "x": 11.5, "y": 2.4},
|
||||
{"label": "]}", "matrix": [3, 5], "x": 12.5, "y": 2.4},
|
||||
{"label": "Caps Lock", "matrix": [3, 1], "x": 0, "y": 3.4, "w": 1.75},
|
||||
{"label": "A", "matrix": [4, 0], "x": 1.75, "y": 3.4},
|
||||
{"label": "S", "matrix": [4, 1], "x": 2.75, "y": 3.4},
|
||||
{"label": "D", "matrix": [4, 2], "x": 3.75, "y": 3.4},
|
||||
{"label": "F", "matrix": [4, 3], "x": 4.75, "y": 3.4},
|
||||
{"label": "G", "matrix": [5, 3], "x": 5.75, "y": 3.4},
|
||||
{"label": "H", "matrix": [5, 4], "x": 6.75, "y": 3.4},
|
||||
{"label": "J", "matrix": [4, 4], "x": 7.75, "y": 3.4},
|
||||
{"label": "K", "matrix": [4, 5], "x": 8.75, "y": 3.4},
|
||||
{"label": "L", "matrix": [4, 6], "x": 9.75, "y": 3.4},
|
||||
{"label": ";:", "matrix": [4, 7], "x": 10.75, "y": 3.4},
|
||||
{"label": "'@", "matrix": [5, 7], "x": 11.75, "y": 3.4},
|
||||
{"label": "#~", "matrix": [6, 7], "x": 12.75, "y": 3.4},
|
||||
{"label": "Enter", "matrix": [6, 8], "x": 13.75, "y": 2.4, "w": 1.25, "h": 2},
|
||||
{"label": "Shift", "matrix": [3, 14], "x": 0, "y": 4.4, "w": 1.25},
|
||||
{"label": "\\|", "matrix": [5, 1], "x": 1.25, "y": 4.4},
|
||||
{"label": "Z", "matrix": [6, 0], "x": 2.25, "y": 4.4},
|
||||
{"label": "X", "matrix": [6, 1], "x": 3.25, "y": 4.4},
|
||||
{"label": "C", "matrix": [6, 2], "x": 4.25, "y": 4.4},
|
||||
{"label": "V", "matrix": [6, 3], "x": 5.25, "y": 4.4},
|
||||
{"label": "B", "matrix": [7, 3], "x": 6.25, "y": 4.4},
|
||||
{"label": "N", "matrix": [7, 4], "x": 7.25, "y": 4.4},
|
||||
{"label": "M", "matrix": [6, 4], "x": 8.25, "y": 4.4},
|
||||
{"label": ",<", "matrix": [6, 5], "x": 9.25, "y": 4.4},
|
||||
{"label": ".>", "matrix": [6, 6], "x": 10.25, "y": 4.4},
|
||||
{"label": "/?", "matrix": [7, 7], "x": 11.25, "y": 4.4},
|
||||
{"label": "Shift", "matrix": [6, 14], "x": 12.25, "y": 4.4, "w": 2.75},
|
||||
{"label": "Fn", "matrix": [4, 9], "x": 0, "y": 5.4},
|
||||
{"label": "Ctrl", "matrix": [0, 15], "x": 1, "y": 5.4, "w": 1.25},
|
||||
{"label": "Left OS", "matrix": [2, 11], "x": 2.25, "y": 5.4, "w": 0.9},
|
||||
{"label": "Alt", "matrix": [5, 13], "x": 3.15, "y": 5.4},
|
||||
{"label": "Space", "matrix": [7, 8], "x": 4.15, "y": 5.4, "w": 5},
|
||||
{"label": "AltGr", "matrix": [7, 13], "x": 9.25, "y": 5.4},
|
||||
{"label": "Menu", "matrix": [4, 11], "x": 10.25, "y": 5.4},
|
||||
{"label": "Ctrl", "matrix": [6, 15], "x": 11.25, "y": 5.4},
|
||||
{"label": "Browser Back", "matrix": [6, 11], "x": 12.25, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Up", "matrix": [5, 12], "x": 13.15, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Browser Forward", "matrix": [7, 11], "x": 14.05, "y": 5.4, "w": 0.9, "h": 0.75},
|
||||
{"label": "Left", "matrix": [7, 12], "x": 12.25, "y": 6.15, "w": 0.9, "h": 0.75},
|
||||
{"label": "Down", "matrix": [7, 10], "x": 13.15, "y": 6.15, "w": 0.9, "h": 0.75},
|
||||
{"label": "Right", "matrix": [7, 9], "x": 14.05, "y": 6.15, "w": 0.9, "h": 0.75}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// Copyright 2022 Nick Brassel (@tzarc)
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
void bootloader_jump(void) {
|
||||
// TODO: Work out how to jump to LDROM, for now just reset the board.
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"keyboard_name": "One 2 SF ANSI",
|
||||
"usb": {
|
||||
"pid": "0x07AF",
|
||||
"device_version": "0.0.1"
|
||||
},
|
||||
"layout_aliases": {
|
||||
"LAYOUT_ansi": "LAYOUT"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
|
||||
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
|
||||
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
|
||||
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
|
||||
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
|
||||
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
|
||||
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
|
||||
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
|
||||
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
|
||||
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
|
||||
|
||||
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
|
||||
|
||||
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
|
||||
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
|
||||
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
|
||||
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
|
||||
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
|
||||
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
|
||||
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
|
||||
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
|
||||
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
|
||||
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
|
||||
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
|
||||
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
|
||||
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
|
||||
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
|
||||
|
||||
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
|
||||
|
||||
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
|
||||
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
|
||||
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
|
||||
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
|
||||
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
|
||||
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
|
||||
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
|
||||
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
|
||||
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
|
||||
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
|
||||
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
|
||||
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
|
||||
{"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
|
||||
|
||||
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
|
||||
|
||||
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
|
||||
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
|
||||
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
|
||||
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
|
||||
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
|
||||
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
|
||||
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
|
||||
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
|
||||
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
|
||||
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
|
||||
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
|
||||
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
|
||||
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
|
||||
|
||||
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
|
||||
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
|
||||
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
|
||||
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
|
||||
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
|
||||
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
|
||||
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
|
||||
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
|
||||
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
|
||||
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2019 /u/KeepItUnder
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
// place overrides here
|
||||
#define GRAVE_ESC_GUI_OVERRIDE
|
||||
#define MK_3_SPEED
|
||||
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
|
||||
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
|
||||
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
|
||||
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
|
||||
+10
-27
@@ -1,34 +1,17 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
// Copyright 2019 /u/KeepItUnder
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
// LAYERS
|
||||
enum Layer {
|
||||
_QWERTY = 0, // Standard QWERTY layer
|
||||
_FUNCTION, // Function key layer
|
||||
_COLOUR // RGB key layer
|
||||
_QWERTY,
|
||||
_FUNCTION,
|
||||
_COLOUR
|
||||
};
|
||||
#define _QW _QWERTY
|
||||
#define _FN _FUNCTION
|
||||
#define _CLR _COLOUR
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
[_QWERTY] = LAYOUT_ansi(
|
||||
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
[_QWERTY] = LAYOUT(
|
||||
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_PGDN,
|
||||
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
|
||||
),
|
||||
|
||||
[_FUNCTION] = LAYOUT_ansi(
|
||||
[_FUNCTION] = LAYOUT(
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
|
||||
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
|
||||
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, KC_END,
|
||||
_______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
|
||||
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
|
||||
_______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
|
||||
),
|
||||
|
||||
[_COLOUR] = LAYOUT_ansi(
|
||||
[_COLOUR] = LAYOUT(
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
@@ -1,18 +1,5 @@
|
||||
/* Copyright 2020 QMK
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
// Copyright 2020 QMK
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -1,19 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 /u/KeepItUnder
|
||||
|
||||
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/>.
|
||||
*/
|
||||
// Copyright 2019 /u/KeepItUnder
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"manufacturer": "Ducky",
|
||||
"maintainer": "f7urry",
|
||||
"bootloader": "custom",
|
||||
"usb": {
|
||||
"vid": "0x445B"
|
||||
},
|
||||
"host": {
|
||||
"default": {
|
||||
"nkro": true
|
||||
}
|
||||
},
|
||||
"matrix_pins": {
|
||||
"cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15"],
|
||||
"rows": ["D11", "B4", "B5", "B6", "B7"]
|
||||
},
|
||||
"diode_direction": "COL2ROW",
|
||||
"features": {
|
||||
"mousekey": true,
|
||||
"extrakey": true,
|
||||
"nkro": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"keyboard_name": "One 2 SF ISO",
|
||||
"usb": {
|
||||
"pid": "0x07AE",
|
||||
"device_version": "0.0.1"
|
||||
},
|
||||
"layout_aliases": {
|
||||
"LAYOUT_iso": "LAYOUT"
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
|
||||
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
|
||||
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
|
||||
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
|
||||
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
|
||||
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
|
||||
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
|
||||
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
|
||||
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
|
||||
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
|
||||
|
||||
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
|
||||
|
||||
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
|
||||
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
|
||||
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
|
||||
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
|
||||
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
|
||||
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
|
||||
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
|
||||
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
|
||||
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
|
||||
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
|
||||
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
|
||||
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
|
||||
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
|
||||
|
||||
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
|
||||
|
||||
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
|
||||
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
|
||||
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
|
||||
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
|
||||
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
|
||||
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
|
||||
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
|
||||
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
|
||||
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
|
||||
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
|
||||
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
|
||||
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
|
||||
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
|
||||
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||
|
||||
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
|
||||
|
||||
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
|
||||
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
|
||||
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
|
||||
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
|
||||
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
|
||||
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
|
||||
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
|
||||
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
|
||||
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
|
||||
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
|
||||
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
|
||||
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
|
||||
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
|
||||
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
|
||||
|
||||
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
|
||||
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
|
||||
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
|
||||
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
|
||||
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
|
||||
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
|
||||
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
|
||||
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
|
||||
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
|
||||
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Copyright 2019 /u/KeepItUnder
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
// place overrides here
|
||||
#define GRAVE_ESC_GUI_OVERRIDE
|
||||
#define MK_3_SPEED
|
||||
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
|
||||
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
|
||||
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
|
||||
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
|
||||
+10
-27
@@ -1,34 +1,17 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
// Copyright 2019 /u/KeepItUnder
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
// LAYERS
|
||||
enum Layer {
|
||||
_QWERTY = 0, // Standard QWERTY layer
|
||||
_FUNCTION, // Function key layer
|
||||
_COLOUR // RGB key layer
|
||||
_QWERTY,
|
||||
_FUNCTION,
|
||||
_COLOUR
|
||||
};
|
||||
#define _QW _QWERTY
|
||||
#define _FN _FUNCTION
|
||||
#define _CLR _COLOUR
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
[_QWERTY] = LAYOUT_iso(
|
||||
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
[_QWERTY] = LAYOUT(
|
||||
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_PGUP,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
|
||||
@@ -36,15 +19,15 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
|
||||
),
|
||||
|
||||
[_FUNCTION] = LAYOUT_iso(
|
||||
[_FUNCTION] = LAYOUT(
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
|
||||
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUS, KC_PGUP, KC_HOME, KC_PSCR, KC_HOME,
|
||||
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RGHT, KC_PGDN, KC_END, _______, _______, KC_END,
|
||||
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
|
||||
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
|
||||
_______, _______, _______, QK_BOOT, MO(2), _______, _______, _______, _______, _______
|
||||
),
|
||||
|
||||
[_COLOUR] = LAYOUT_iso(
|
||||
[_COLOUR] = LAYOUT(
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
@@ -1,269 +0,0 @@
|
||||
{
|
||||
"keyboard_name": "One 2 SF",
|
||||
"manufacturer": "Ducky",
|
||||
"maintainer": "f7urry",
|
||||
"usb": {
|
||||
"vid": "0x445B",
|
||||
"pid": "0x07AF",
|
||||
"device_version": "0.0.1"
|
||||
},
|
||||
"host": {
|
||||
"default": {
|
||||
"nkro": true
|
||||
}
|
||||
},
|
||||
"matrix_pins": {
|
||||
"cols": ["B10", "B9", "C13", "C12", "C11", "C10", "C9", "C8", "A15", "A14", "A13", "D0", "D1", "D2", "B15", "B8"],
|
||||
"rows": ["D11", "B4", "B5", "B6", "B7"]
|
||||
},
|
||||
"diode_direction": "COL2ROW",
|
||||
"dip_switch": {
|
||||
"matrix_grid": [ [0,14], [1,14], [2,14], [3,14] ]
|
||||
},
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"mousekey": true,
|
||||
"extrakey": true,
|
||||
"nkro": true,
|
||||
"dip_switch": true
|
||||
},
|
||||
"layouts": {
|
||||
"LAYOUT_all": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
|
||||
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
|
||||
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
|
||||
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
|
||||
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
|
||||
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
|
||||
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
|
||||
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
|
||||
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
|
||||
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
|
||||
|
||||
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
|
||||
|
||||
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
|
||||
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
|
||||
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
|
||||
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
|
||||
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
|
||||
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
|
||||
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
|
||||
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
|
||||
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
|
||||
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
|
||||
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
|
||||
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
|
||||
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
|
||||
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
|
||||
|
||||
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
|
||||
|
||||
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
|
||||
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
|
||||
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
|
||||
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
|
||||
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
|
||||
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
|
||||
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
|
||||
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
|
||||
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
|
||||
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
|
||||
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
|
||||
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
|
||||
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
|
||||
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 2, "w": 1.25},
|
||||
|
||||
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
|
||||
|
||||
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
|
||||
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
|
||||
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
|
||||
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
|
||||
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
|
||||
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
|
||||
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
|
||||
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
|
||||
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
|
||||
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
|
||||
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
|
||||
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
|
||||
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
|
||||
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
|
||||
|
||||
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
|
||||
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
|
||||
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
|
||||
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
|
||||
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
|
||||
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
|
||||
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
|
||||
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
|
||||
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
|
||||
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
|
||||
]
|
||||
},
|
||||
"LAYOUT_ansi": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
|
||||
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
|
||||
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
|
||||
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
|
||||
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
|
||||
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
|
||||
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
|
||||
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
|
||||
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
|
||||
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
|
||||
|
||||
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
|
||||
|
||||
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
|
||||
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
|
||||
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
|
||||
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
|
||||
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
|
||||
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
|
||||
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
|
||||
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
|
||||
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
|
||||
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
|
||||
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
|
||||
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
|
||||
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
|
||||
{"label": "\\", "matrix": [1, 13], "x": 13.5, "y": 1, "w": 1.5},
|
||||
|
||||
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
|
||||
|
||||
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
|
||||
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
|
||||
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
|
||||
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
|
||||
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
|
||||
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
|
||||
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
|
||||
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
|
||||
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
|
||||
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
|
||||
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
|
||||
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
|
||||
{"label": "Enter", "matrix": [2, 13], "x": 12.75, "y": 2, "w": 2.25},
|
||||
|
||||
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
|
||||
|
||||
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 2.25},
|
||||
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
|
||||
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
|
||||
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
|
||||
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
|
||||
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
|
||||
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
|
||||
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
|
||||
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
|
||||
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
|
||||
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
|
||||
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
|
||||
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
|
||||
|
||||
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
|
||||
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
|
||||
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
|
||||
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
|
||||
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
|
||||
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
|
||||
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
|
||||
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
|
||||
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
|
||||
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
|
||||
]
|
||||
},
|
||||
"LAYOUT_iso": {
|
||||
"layout": [
|
||||
{"label": "Esc", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "1", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "2", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "3", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "4", "matrix": [0, 4], "x": 4, "y": 0},
|
||||
{"label": "5", "matrix": [0, 5], "x": 5, "y": 0},
|
||||
{"label": "6", "matrix": [0, 6], "x": 6, "y": 0},
|
||||
{"label": "7", "matrix": [0, 7], "x": 7, "y": 0},
|
||||
{"label": "8", "matrix": [0, 8], "x": 8, "y": 0},
|
||||
{"label": "9", "matrix": [0, 9], "x": 9, "y": 0},
|
||||
{"label": "0", "matrix": [0, 10], "x": 10, "y": 0},
|
||||
{"label": "-", "matrix": [0, 11], "x": 11, "y": 0},
|
||||
{"label": "=", "matrix": [0, 12], "x": 12, "y": 0},
|
||||
{"label": "Backspace", "matrix": [0, 13], "x": 13, "y": 0, "w": 2},
|
||||
|
||||
{"label": "Delete", "matrix": [0, 14], "x": 15.25, "y": 0},
|
||||
|
||||
{"label": "Tab", "matrix": [1, 0], "x": 0, "y": 1, "w": 1.5},
|
||||
{"label": "Q", "matrix": [1, 1], "x": 1.5, "y": 1},
|
||||
{"label": "W", "matrix": [1, 2], "x": 2.5, "y": 1},
|
||||
{"label": "E", "matrix": [1, 3], "x": 3.5, "y": 1},
|
||||
{"label": "R", "matrix": [1, 4], "x": 4.5, "y": 1},
|
||||
{"label": "T", "matrix": [1, 5], "x": 5.5, "y": 1},
|
||||
{"label": "Y", "matrix": [1, 6], "x": 6.5, "y": 1},
|
||||
{"label": "U", "matrix": [1, 7], "x": 7.5, "y": 1},
|
||||
{"label": "I", "matrix": [1, 8], "x": 8.5, "y": 1},
|
||||
{"label": "O", "matrix": [1, 9], "x": 9.5, "y": 1},
|
||||
{"label": "P", "matrix": [1, 10], "x": 10.5, "y": 1},
|
||||
{"label": "[", "matrix": [1, 11], "x": 11.5, "y": 1},
|
||||
{"label": "]", "matrix": [1, 12], "x": 12.5, "y": 1},
|
||||
|
||||
{"label": "Page Up", "matrix": [1, 14], "x": 15.25, "y": 1},
|
||||
|
||||
{"label": "Caps Lock", "matrix": [2, 0], "x": 0, "y": 2, "w": 1.75},
|
||||
{"label": "A", "matrix": [2, 1], "x": 1.75, "y": 2},
|
||||
{"label": "S", "matrix": [2, 2], "x": 2.75, "y": 2},
|
||||
{"label": "D", "matrix": [2, 3], "x": 3.75, "y": 2},
|
||||
{"label": "F", "matrix": [2, 4], "x": 4.75, "y": 2},
|
||||
{"label": "G", "matrix": [2, 5], "x": 5.75, "y": 2},
|
||||
{"label": "H", "matrix": [2, 6], "x": 6.75, "y": 2},
|
||||
{"label": "J", "matrix": [2, 7], "x": 7.75, "y": 2},
|
||||
{"label": "K", "matrix": [2, 8], "x": 8.75, "y": 2},
|
||||
{"label": "L", "matrix": [2, 9], "x": 9.75, "y": 2},
|
||||
{"label": ";", "matrix": [2, 10], "x": 10.75, "y": 2},
|
||||
{"label": "'", "matrix": [2, 11], "x": 11.75, "y": 2},
|
||||
{"label": "#", "matrix": [2, 12], "x": 12.75, "y": 2},
|
||||
{"label": "Enter", "matrix": [2, 13], "x": 13.75, "y": 1, "w": 1.25, "h": 2},
|
||||
|
||||
{"label": "Page Down", "matrix": [2, 14], "x": 15.25, "y": 2},
|
||||
|
||||
{"label": "Shift", "matrix": [3, 0], "x": 0, "y": 3, "w": 1.25},
|
||||
{"label": "\\", "matrix": [3, 1], "x": 1.25, "y": 3},
|
||||
{"label": "Z", "matrix": [3, 2], "x": 2.25, "y": 3},
|
||||
{"label": "X", "matrix": [3, 3], "x": 3.25, "y": 3},
|
||||
{"label": "C", "matrix": [3, 4], "x": 4.25, "y": 3},
|
||||
{"label": "V", "matrix": [3, 5], "x": 5.25, "y": 3},
|
||||
{"label": "B", "matrix": [3, 6], "x": 6.25, "y": 3},
|
||||
{"label": "N", "matrix": [3, 7], "x": 7.25, "y": 3},
|
||||
{"label": "M", "matrix": [3, 8], "x": 8.25, "y": 3},
|
||||
{"label": ",", "matrix": [3, 9], "x": 9.25, "y": 3},
|
||||
{"label": ".", "matrix": [3, 10], "x": 10.25, "y": 3},
|
||||
{"label": "/", "matrix": [3, 11], "x": 11.25, "y": 3},
|
||||
{"label": "Shift", "matrix": [3, 12], "x": 12.25, "y": 3, "w": 2},
|
||||
{"label": "\u2191", "matrix": [3, 13], "x": 14.25, "y": 3},
|
||||
|
||||
{"label": "Ctrl", "matrix": [4, 0], "x": 0, "y": 4, "w": 1.25},
|
||||
{"label": "GUI", "matrix": [4, 1], "x": 1.25, "y": 4, "w": 1.25},
|
||||
{"label": "Alt", "matrix": [4, 2], "x": 2.5, "y": 4, "w": 1.25},
|
||||
{"label": "Space", "matrix": [4, 5], "x": 3.75, "y": 4, "w": 6.25},
|
||||
{"label": "Alt", "matrix": [4, 9], "x": 10, "y": 4},
|
||||
{"label": "Fn", "matrix": [4, 10], "x": 11, "y": 4},
|
||||
{"label": "Ctrl", "matrix": [4, 11], "x": 12, "y": 4, "w": 1.25},
|
||||
{"label": "\u2190", "matrix": [4, 12], "x": 13.25, "y": 4},
|
||||
{"label": "\u2193", "matrix": [4, 13], "x": 14.25, "y": 4},
|
||||
{"label": "\u2192", "matrix": [4, 14], "x": 15.25, "y": 4}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
# Matrix Diagram for Ducky One 2 SF
|
||||
|
||||
```
|
||||
┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───────┐┌───┐
|
||||
│00 │01 │02 │03 │04 │05 │06 │07 │08 │09 │0A │0B │0C │0D ││0E │
|
||||
├───┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─────┤├───┤ ┌─────┐
|
||||
│10 │11 │12 │13 │14 │15 │16 │17 │18 │19 │1A │1B │1C │1D ││1E │ │ │
|
||||
├─────┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴┬──┴─────┤├───┤ ┌──┴┐2D │
|
||||
│20 │21 │22 │23 │24 │25 │26 │27 │28 │29 │2A │2B │2D ││2E │ │2C │ │
|
||||
├────┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─┬─┴─────┬──┴┼───┘ └───┴────┘
|
||||
│30 │31 │32 │33 │34 │35 │36 │37 │38 │39 │3A │3B │3C │3D │ ISO Enter
|
||||
├────┼───┴┬──┴─┬─┴───┴───┴───┴───┴───┴──┬┴──┬┴──┬┴───┬───┼───┼───┐
|
||||
│40 │41 │42 │45 │49 │4A │4B │4C │4D │4E │
|
||||
└────┴────┴────┴────────────────────────┴───┴───┴────┴───┴───┴───┘
|
||||
┌────────┐
|
||||
│30 │ 2.25u LShift
|
||||
└────────┘
|
||||
```
|
||||
@@ -43,7 +43,7 @@
|
||||
#define NUC123_USB_USE_USB0 TRUE
|
||||
#define NUC123_USB_USE_USB1 TRUE
|
||||
|
||||
#define NUC123_SERIAL_USE_UART0 TRUE
|
||||
#define NUC123_SERIAL_USE_UART0 FALSE
|
||||
#define NUC123_SERIAL_CLKSRC NUC123_SERIAL_CLKSRC_HSI
|
||||
|
||||
#define NUC123_MCUCONF
|
||||
|
||||
@@ -2,18 +2,16 @@
|
||||
|
||||
A 65% keyboard by Ducky.
|
||||
|
||||
This firmware was tested on the Ducky One 2 SF 1967ST version.
|
||||
|
||||
* Keyboard Maintainer: [f7urry](https://github.com/f7urry)
|
||||
* Hardware Supported: Ducky One 2 SF RGB (DKON1967ST), NUC123SD4AN0 + MBI5043GP
|
||||
* Only ANSI layout is supported at this time
|
||||
* ISO compiles but is **untested**
|
||||
* VIA still WIP.
|
||||
* RGB LEDs are currently disabled until the driver is merged.
|
||||
* DIP switches are disabled due to hardware incompatibilities
|
||||
|
||||
## Compiling the Firmware:
|
||||
|
||||
make ducky/one2sf/1967st:default
|
||||
make ducky/one2sf/1967st/ansi:default
|
||||
make ducky/one2sf/1967st/iso:default
|
||||
|
||||
## Accessing Bootloader Mode
|
||||
|
||||
@@ -24,11 +22,16 @@ To enter the 1967ST bootloader to flash, boot the keyboard while holding D+L.
|
||||
There are then two ways to flash the keyboard:
|
||||
|
||||
pip install --user nuvoton-isp
|
||||
nuvoisp -f ducky_one2sf_ansi.bin
|
||||
nuvoisp -f ducky_one2sf_1967st_ansi_default.bin
|
||||
|
||||
Alternatively you can use elfmimi's [nu-isp-cli](https://lib.rs/crates/nu-isp-cli) which is more complete than nuvoisp and allows flashing .hex files as well.
|
||||
|
||||
cargo install nu-isp-cli
|
||||
nu-isp-cli flash ducky_one2sf_ansi.bin
|
||||
nu-isp-cli flash ducky_one2sf_1967st_ansi_default.bin
|
||||
|
||||
or
|
||||
|
||||
make ducky/one2sf/1967st/ansi:default:flash
|
||||
make ducky/one2sf/1967st/iso:default:flash
|
||||
|
||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||
|
||||
@@ -15,3 +15,6 @@ BOARD = NUC123SD4AN0
|
||||
MCU = cortex-m0
|
||||
# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
|
||||
ARMV = 6
|
||||
|
||||
# Needs elevated access to 0416:3f00 on Linux
|
||||
PROGRAM_CMD = nu-isp-cli flash $(BUILD_DIR)/$(TARGET).bin
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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
|
||||
|
||||
// place overrides here
|
||||
#define GRAVE_ESC_GUI_OVERRIDE
|
||||
#define MK_3_SPEED
|
||||
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
|
||||
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
|
||||
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
|
||||
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
|
||||
@@ -1,55 +0,0 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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 QMK_KEYBOARD_H
|
||||
|
||||
// LAYERS
|
||||
enum Layer {
|
||||
_QWERTY = 0, // Standard QWERTY layer
|
||||
_FUNCTION, // Function key layer
|
||||
_COLOUR // RGB key layer
|
||||
};
|
||||
#define _QW _QWERTY
|
||||
#define _FN _FUNCTION
|
||||
#define _CLR _COLOUR
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
[_QWERTY] = LAYOUT_all(
|
||||
// 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
QK_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_DEL,
|
||||
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGUP,
|
||||
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NUHS, KC_ENT, KC_PGDN,
|
||||
KC_LSFT, KC_NUBS, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT
|
||||
),
|
||||
|
||||
[_FUNCTION] = LAYOUT_all(
|
||||
KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, _______,
|
||||
_______, MS_BTN1, MS_UP, MS_BTN2, MS_WHLU, _______, KC_INS, _______, KC_UP, KC_PAUSE, KC_PGUP, KC_HOME, KC_PSCR, _______, KC_HOME,
|
||||
_______, MS_LEFT, MS_DOWN, MS_RGHT, MS_WHLD, _______, KC_SCRL, KC_LEFT, KC_DOWN, KC_RIGHT, KC_PGDN, KC_END, _______, _______, KC_END,
|
||||
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, KC_MUTE, KC_VOLD, KC_VOLU, _______, _______, _______,
|
||||
_______, _______, _______, _______, MO(2), _______, _______, _______, _______, _______
|
||||
),
|
||||
|
||||
[_COLOUR] = LAYOUT_all(
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, RM_TOGG, RM_NEXT, RM_HUEU, RM_HUED, RM_SATU, RM_SATD, _______, _______, _______, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______
|
||||
),
|
||||
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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
|
||||
|
||||
// place overrides here
|
||||
#define GRAVE_ESC_GUI_OVERRIDE
|
||||
#define MK_3_SPEED
|
||||
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
|
||||
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
|
||||
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
|
||||
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
|
||||
@@ -1,25 +0,0 @@
|
||||
/* Copyright 2019 /u/KeepItUnder
|
||||
*
|
||||
* 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
|
||||
|
||||
// place overrides here
|
||||
#define GRAVE_ESC_GUI_OVERRIDE
|
||||
#define MK_3_SPEED
|
||||
#define MK_C_OFFSET_UNMOD 400 /* Cursor offset per movement (unmodified) */
|
||||
#define MK_C_INTERVAL_UNMOD 5 /* Time between cursor movements (unmodified) */
|
||||
#define MK_W_OFFSET_UNMOD 100 /* Scroll steps per scroll action (unmodified) */
|
||||
#define MK_W_INTERVAL_UNMOD 10 /* Time between scroll steps (unmodified) */
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"manufacturer": "Harry Cutts",
|
||||
"keyboard_name": "TwentyPad",
|
||||
"maintainer": "HarryCutts",
|
||||
"bootloader": "atmel-dfu",
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"extrakey": true,
|
||||
"mousekey": true
|
||||
},
|
||||
"matrix_pins": {
|
||||
"direct": [
|
||||
["B7", "D5", "B5", "F6"],
|
||||
["B3", "D3", "B4", "F7"],
|
||||
["B2", "D2", "D7", "C7"],
|
||||
["B1", "D1", "D6", "C6"],
|
||||
["B0", "D0", "D4", "B6"]
|
||||
]
|
||||
},
|
||||
"processor": "atmega32u4",
|
||||
"url": "https://github.com/HarryCutts/twentypad/",
|
||||
"usb": {
|
||||
"device_version": "1.0.0",
|
||||
"pid": "0x209D",
|
||||
"vid": "0xFEED"
|
||||
},
|
||||
"community_layouts": ["ortho_5x4"],
|
||||
"layouts": {
|
||||
"LAYOUT_ortho_5x4": {
|
||||
"layout": [
|
||||
{"label": "B7", "matrix": [0, 0], "x": 0, "y": 0},
|
||||
{"label": "D5", "matrix": [0, 1], "x": 1, "y": 0},
|
||||
{"label": "B5", "matrix": [0, 2], "x": 2, "y": 0},
|
||||
{"label": "F6", "matrix": [0, 3], "x": 3, "y": 0},
|
||||
{"label": "B3", "matrix": [1, 0], "x": 0, "y": 1},
|
||||
{"label": "D3", "matrix": [1, 1], "x": 1, "y": 1},
|
||||
{"label": "B4", "matrix": [1, 2], "x": 2, "y": 1},
|
||||
{"label": "F7", "matrix": [1, 3], "x": 3, "y": 1},
|
||||
{"label": "B2", "matrix": [2, 0], "x": 0, "y": 2},
|
||||
{"label": "D2", "matrix": [2, 1], "x": 1, "y": 2},
|
||||
{"label": "D7", "matrix": [2, 2], "x": 2, "y": 2},
|
||||
{"label": "C7", "matrix": [2, 3], "x": 3, "y": 2},
|
||||
{"label": "B1", "matrix": [3, 0], "x": 0, "y": 3},
|
||||
{"label": "D1", "matrix": [3, 1], "x": 1, "y": 3},
|
||||
{"label": "D6", "matrix": [3, 2], "x": 2, "y": 3},
|
||||
{"label": "C6", "matrix": [3, 3], "x": 3, "y": 3},
|
||||
{"label": "B0", "matrix": [4, 0], "x": 0, "y": 4},
|
||||
{"label": "D0", "matrix": [4, 1], "x": 1, "y": 4},
|
||||
{"label": "D4", "matrix": [4, 2], "x": 2, "y": 4},
|
||||
{"label": "B6", "matrix": [4, 3], "x": 3, "y": 4}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"keyboard": "handwired/twentypad",
|
||||
"keymap": "default",
|
||||
"layout": "LAYOUT_ortho_5x4",
|
||||
"layers": [
|
||||
[
|
||||
"KC_CALCULATOR", "KC_KP_SLASH", "KC_KP_ASTERISK", "KC_KP_MINUS",
|
||||
"KC_KP_7", "KC_KP_8", "KC_KP_9", "KC_KP_PLUS",
|
||||
"KC_KP_4", "KC_KP_5", "KC_KP_6", "KC_LEFT_PAREN",
|
||||
"KC_KP_1", "KC_KP_2", "KC_KP_3", "KC_RIGHT_PAREN",
|
||||
"KC_KP_0", "KC_KP_DOT", "KC_KP_EQUAL", "KC_KP_ENTER"
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# TwentyPad
|
||||
|
||||

|
||||
|
||||
A simple twenty-key macro pad, built to learn PCB design.
|
||||
|
||||
* Keyboard Maintainer: [Harry Cutts](https://github.com/HarryCutts)
|
||||
* Hardware Supported: ATMEGA32U4 on a [custom PCB](https://github.com/HarryCutts/twentypad/)
|
||||
|
||||
Make example for this keyboard (after setting up your build environment):
|
||||
|
||||
qmk compile -kb handwired/twentypad -km default
|
||||
|
||||
Flashing example for this keyboard:
|
||||
|
||||
qmk flash -kb handwired/twentypad -km default
|
||||
|
||||
See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
|
||||
|
||||
## Bootloader
|
||||
|
||||
Enter the bootloader in 3 ways:
|
||||
|
||||
* **Bootmagic reset**: Hold down the key at (0,0) in the matrix (the top left key) and plug in the keyboard
|
||||
* **Physical reset button**: Press the button marked `SWR1` in the top-left of the PCB
|
||||
* **Keycode in layout**: Press the key mapped to `QK_BOOT` if it is available
|
||||
@@ -6,8 +6,6 @@
|
||||
"diode_direction": "ROW2COL",
|
||||
"features": {
|
||||
"bootmagic": true,
|
||||
"command": false,
|
||||
"console": false,
|
||||
"extrakey": true,
|
||||
"mousekey": true,
|
||||
"nkro": true,
|
||||
|
||||
@@ -221,9 +221,5 @@ void eeconfig_init_kb_datablock(void) {
|
||||
config.idle_rgb_matrix = default_idle_rgb_matrix;
|
||||
|
||||
eeconfig_update_kb_datablock(&config, 0, EECONFIG_KB_DATA_SIZE);
|
||||
|
||||
# if (EECONFIG_USER_DATA_SIZE) > 0
|
||||
eeconfig_init_user_datablock();
|
||||
# endif // EECONFIG_USER_DATA_SIZE
|
||||
#endif // RGB_IDLE_ENABLE
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
{"matrix": [3, 3], "x": 61, "y": 63, "flags": 1},
|
||||
{"matrix": [3, 4], "x": 81, "y": 63, "flags": 1},
|
||||
{"matrix": [3, 5], "x": 101, "y": 63, "flags": 4},
|
||||
{"x": 111, "y": 63, "flags": 4},
|
||||
{"matrix": [3, 5], "x": 111, "y": 63, "flags": 4},
|
||||
{"matrix": [3, 6], "x": 122, "y": 63, "flags": 4},
|
||||
{"matrix": [3, 7], "x": 142, "y": 63, "flags": 1},
|
||||
{"matrix": [3, 8], "x": 162, "y": 63, "flags": 1},
|
||||
|
||||
@@ -86,16 +86,6 @@ void matrix_init_kb(void) {
|
||||
matrix_init_user();
|
||||
}
|
||||
|
||||
uint8_t rgb_matrix_map_row_column_to_led_kb(uint8_t row, uint8_t column, uint8_t *led_i) {
|
||||
// Spacebar has 2 leds 41 & 42, so add 42 to the array here, and 41 will be added
|
||||
// by the default lookup code that runs after this
|
||||
if (row == 3 && column == 5) {
|
||||
led_i[0] = 42;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef SWAP_HANDS_ENABLE
|
||||
__attribute__ ((weak))
|
||||
const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
|
||||
|
||||
@@ -78,9 +78,9 @@ typedef enum {
|
||||
UP_BEGIN_MID,
|
||||
STATE_MASK = 0xf, /* 0b1111 */
|
||||
EMIT_UP = 0x10,
|
||||
EMIT_UP_MID = EMIT_UP & START_MID,
|
||||
EMIT_UP_MID = EMIT_UP | START_MID,
|
||||
EMIT_DOWN = 0x80,
|
||||
EMIT_DOWN_MID = EMIT_DOWN & START_MID,
|
||||
EMIT_DOWN_MID = EMIT_DOWN | START_MID,
|
||||
EMIT_MASK = 0xf0
|
||||
} encoder_state_t;
|
||||
|
||||
|
||||
@@ -1,113 +0,0 @@
|
||||
// Copyright 2024 zvecr <git@zvecr.com>
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include QMK_KEYBOARD_H
|
||||
|
||||
enum layer_names {
|
||||
_QWERTY,
|
||||
_LOWER,
|
||||
_RAISE,
|
||||
_ADJUST,
|
||||
};
|
||||
|
||||
#define LOWER MO(_LOWER)
|
||||
#define RAISE MO(_RAISE)
|
||||
|
||||
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||||
/* Qwerty
|
||||
* ,-----------------------------------------------------------------------------------.
|
||||
* | Esc | Q | W | E | R | T | Y | U | I | O | P | Bksp |
|
||||
* |------+------+------+------+------+-------------+------+------+------+------+------|
|
||||
* | Tab | A | S | D | F | G | H | J | K | L | ; | " |
|
||||
* |------+------+------+------+------+------|------+------+------+------+------+------|
|
||||
* | Shift| Z | X | C | V | B | N | M | , | . | / |Enter |
|
||||
* |------+------+------+------+------+------+------+------+------+------+------+------|
|
||||
* | Ctrl | GUI | Alt | App |Lower | Space |Raise | Left | Down | Up |Right |
|
||||
* `-----------------------------------------------------------------------------------'
|
||||
*/
|
||||
[_QWERTY] = LAYOUT_ortho_4x12(
|
||||
KC_ESC, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC,
|
||||
KC_TAB, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
|
||||
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT,
|
||||
KC_LCTL, KC_LGUI, KC_LALT, KC_APP, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT
|
||||
),
|
||||
|
||||
/* Lower
|
||||
* ,-----------------------------------------------------------------------------------.
|
||||
* | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Del |
|
||||
* |------+------+------+------+------+-------------+------+------+------+------+------|
|
||||
* | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | |
|
||||
* |------+------+------+------+------+------|------+------+------+------+------+------|
|
||||
* | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | | | |
|
||||
* |------+------+------+------+------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | Next | Vol- | Vol+ | Play |
|
||||
* `-----------------------------------------------------------------------------------'
|
||||
*/
|
||||
[_LOWER] = LAYOUT_ortho_4x12(
|
||||
KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_DEL,
|
||||
KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE,
|
||||
_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12,S(KC_NUHS),S(KC_NUBS),_______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
|
||||
),
|
||||
|
||||
/* Raise
|
||||
* ,-----------------------------------------------------------------------------------.
|
||||
* | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Del |
|
||||
* |------+------+------+------+------+-------------+------+------+------+------+------|
|
||||
* | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ |
|
||||
* |------+------+------+------+------+------|------+------+------+------+------+------|
|
||||
* | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / | | | |
|
||||
* |------+------+------+------+------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | Next | Vol- | Vol+ | Play |
|
||||
* `-----------------------------------------------------------------------------------'
|
||||
*/
|
||||
[_RAISE] = LAYOUT_ortho_4x12(
|
||||
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_DEL,
|
||||
KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS,
|
||||
_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
|
||||
),
|
||||
|
||||
/* Adjust (Lower + Raise)
|
||||
* ,-----------------------------------------------------------------------------------.
|
||||
* | | Reset| | | | |R Tog |R Mode|R Rev |R Grad| Reset| |
|
||||
* |------+------+------+------+------+-------------+------+------+------+------+------|
|
||||
* | | | | | | |R HUI|R SAI|R VAI| | | |
|
||||
* |------+------+------+------+------+------|------+------+------+------+------+------|
|
||||
* | | | | | | |R HUD|R SAD|R VAD| | | |
|
||||
* |------+------+------+------+------+------+------+------+------+------+------+------|
|
||||
* | | | | | | | | | | | | |
|
||||
* `-----------------------------------------------------------------------------------'
|
||||
*/
|
||||
[_ADJUST] = LAYOUT_ortho_4x12(
|
||||
_______, QK_BOOT, _______, _______, _______, _______, UG_TOGG, UG_NEXT, UG_PREV, RGB_M_G, QK_BOOT, _______,
|
||||
_______, _______, _______, _______, _______, _______, UG_HUEU, UG_SATU, UG_VALU, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, UG_HUED, UG_SATD, UG_VALD, _______, _______, _______,
|
||||
_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______
|
||||
)
|
||||
|
||||
};
|
||||
|
||||
layer_state_t layer_state_set_user(layer_state_t state) {
|
||||
return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
|
||||
}
|
||||
|
||||
#if defined(ENCODER_MAP_ENABLE)
|
||||
const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
|
||||
[_QWERTY] = { ENCODER_CCW_CW(MS_WHLD, MS_WHLU), ENCODER_CCW_CW(KC_VOLD, KC_VOLU) },
|
||||
[_LOWER] = { ENCODER_CCW_CW(UG_HUED, UG_HUEU), ENCODER_CCW_CW(UG_SATD, UG_SATU) },
|
||||
[_RAISE] = { ENCODER_CCW_CW(UG_SATD, UG_SATU), ENCODER_CCW_CW(UG_SPDD, UG_SPDU) },
|
||||
[_ADJUST] = { ENCODER_CCW_CW(UG_PREV, UG_NEXT), ENCODER_CCW_CW(KC_RGHT, KC_LEFT) },
|
||||
};
|
||||
#endif
|
||||
|
||||
void housekeeping_task_user(void) {
|
||||
static uint32_t timer = 0;
|
||||
static uint8_t count = 0;
|
||||
if (timer_elapsed32(timer) > 1000) {
|
||||
timer = timer_read32();
|
||||
count++;
|
||||
|
||||
xap_broadcast(0x03, &count, 1);
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
ENCODER_MAP_ENABLE = yes
|
||||
XAP_ENABLE = yes
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY_USER
|
||||
description:
|
||||
'''
|
||||
USER subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_USER_CAPABILITIES
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
routes: {
|
||||
0x01: {
|
||||
type: command
|
||||
name: Capabilities Query
|
||||
define: CAPABILITIES_QUERY_KB
|
||||
description:
|
||||
'''
|
||||
KB subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
|
||||
'''
|
||||
return_type: u32
|
||||
return_purpose: capabilities
|
||||
return_constant: XAP_ROUTE_KB_CAPABILITIES
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,9 +113,6 @@ class BuildTarget:
|
||||
'builddefs/build_keyboard.mk',
|
||||
]
|
||||
|
||||
if not cli.config.general.verbose:
|
||||
compile_args.append('-s')
|
||||
|
||||
verbose = 'true' if cli.config.general.verbose else 'false'
|
||||
color = 'true' if cli.config.general.color else 'false'
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
"""This script handles conversion between snake and camel casing.
|
||||
"""
|
||||
import re
|
||||
|
||||
_words_expr = re.compile(r"([a-zA-Z][^A-Z0-9]*|[0-9]+)")
|
||||
_lower_snake_case_expr = re.compile(r'^[a-z][a-z0-9_]*$')
|
||||
_upper_snake_case_expr = re.compile(r'^[A-Z][A-Z0-9_]*$')
|
||||
|
||||
|
||||
def _is_snake_case(str):
|
||||
"""Checks if the supplied string is already in snake case.
|
||||
"""
|
||||
match = _lower_snake_case_expr.match(str)
|
||||
if match:
|
||||
return True
|
||||
match = _upper_snake_case_expr.match(str)
|
||||
if match:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _split_snake_case(str):
|
||||
"""Splits up a string based on underscores, if it's in snake casing.
|
||||
"""
|
||||
if _is_snake_case(str):
|
||||
return [s.lower() for s in str.split("_")]
|
||||
return str
|
||||
|
||||
|
||||
def _split_camel_case(str):
|
||||
"""Splits up a string based on capitalised camel casing.
|
||||
"""
|
||||
return _words_expr.findall(str)
|
||||
|
||||
|
||||
def _split_cased_words(str):
|
||||
return _split_snake_case(str) if _is_snake_case(str) else _split_camel_case(str)
|
||||
|
||||
|
||||
def to_snake(str):
|
||||
str = "_".join([word.strip().lower() for word in _split_cased_words(str)])
|
||||
|
||||
# Fix acronyms
|
||||
str = str.replace('i_d', 'id')
|
||||
str = str.replace('x_a_p', 'xap')
|
||||
str = str.replace('q_m_k', 'qmk')
|
||||
|
||||
return str
|
||||
|
||||
|
||||
def to_upper_snake(str):
|
||||
return to_snake(str).upper()
|
||||
|
||||
|
||||
def to_camel(str):
|
||||
def _acronym(w):
|
||||
if w.strip().lower() == 'qmk':
|
||||
return 'QMK'
|
||||
elif w.strip().lower() == 'xap':
|
||||
return 'XAP'
|
||||
elif w.strip().lower() == 'id':
|
||||
return 'ID'
|
||||
return w.title()
|
||||
|
||||
return "".join([_acronym(word) for word in _split_cased_words(str)])
|
||||
@@ -42,8 +42,7 @@ import_names = {
|
||||
'pyserial': 'serial',
|
||||
'pyusb': 'usb.core',
|
||||
'qmk-dotty-dict': 'dotty_dict',
|
||||
'pillow': 'PIL',
|
||||
'Jinja2': 'jinja2'
|
||||
'pillow': 'PIL'
|
||||
}
|
||||
|
||||
safe_commands = [
|
||||
@@ -84,7 +83,6 @@ subcommands = [
|
||||
'qmk.cli.generate.keyboard_c',
|
||||
'qmk.cli.generate.keyboard_h',
|
||||
'qmk.cli.generate.keycodes',
|
||||
'qmk.cli.generate.lighting_map',
|
||||
'qmk.cli.generate.keymap_h',
|
||||
'qmk.cli.generate.make_dependencies',
|
||||
'qmk.cli.generate.rgb_breathe_table',
|
||||
@@ -118,11 +116,6 @@ subcommands = [
|
||||
'qmk.cli.userspace.path',
|
||||
'qmk.cli.userspace.remove',
|
||||
'qmk.cli.via2json',
|
||||
'qmk.cli.xap',
|
||||
'qmk.cli.xap.generate_docs',
|
||||
'qmk.cli.xap.generate_json',
|
||||
'qmk.cli.xap.generate_python',
|
||||
'qmk.cli.xap.generate_qmk',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ py_dirs = ['lib/python', 'util/ci']
|
||||
|
||||
def yapf_run(files):
|
||||
edit = '--diff' if cli.args.dry_run else '--in-place'
|
||||
yapf_cmd = ['yapf', '-vv', '--exclude', '**/xap_client/*', '--recursive', edit, *files]
|
||||
yapf_cmd = ['yapf', '-vv', '--recursive', edit, *files]
|
||||
try:
|
||||
cli.run(yapf_cmd, check=True, capture_output=False, stdin=DEVNULL)
|
||||
cli.log.info('Successfully formatted the python code.')
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""Ensure text files have the proper line endings.
|
||||
"""
|
||||
from itertools import islice
|
||||
from subprocess import DEVNULL
|
||||
|
||||
from milc import cli
|
||||
|
||||
from qmk.path import normpath, is_relative_to
|
||||
from qmk.commands import get_chunks
|
||||
|
||||
IGNORE_SUFFIXES = [
|
||||
'hex',
|
||||
@@ -21,6 +21,13 @@ IGNORE_DIRS = [
|
||||
]
|
||||
|
||||
|
||||
def _get_chunks(it, size):
|
||||
"""Break down a collection into smaller parts
|
||||
"""
|
||||
it = iter(it)
|
||||
return iter(lambda: tuple(islice(it, size)), ())
|
||||
|
||||
|
||||
def _check_dos2unix():
|
||||
"""Check for a 'valid' dos2unix executable
|
||||
"""
|
||||
@@ -31,7 +38,7 @@ def _check_dos2unix():
|
||||
def dos2unix_run(files):
|
||||
"""Spawn multiple dos2unix subprocess avoiding too long commands on formatting everything
|
||||
"""
|
||||
for chunk in get_chunks([normpath(file).as_posix() for file in files], 10):
|
||||
for chunk in _get_chunks([normpath(file).as_posix() for file in files], 10):
|
||||
dos2unix = cli.run(['dos2unix', '--add-eol', *chunk])
|
||||
|
||||
if dos2unix.returncode:
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
"""
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import hjson
|
||||
import json
|
||||
|
||||
from milc import cli
|
||||
@@ -14,7 +13,6 @@ from qmk.json_schema import json_load
|
||||
from qmk.keymap import list_keymaps
|
||||
from qmk.keyboard import find_readme, list_keyboards, keyboard_alias_definitions
|
||||
from qmk.keycodes import load_spec, list_versions, list_languages
|
||||
from qmk.xap.common import get_xap_definition_files, update_xap_definitions
|
||||
|
||||
DATA_PATH = Path('data')
|
||||
TEMPLATE_PATH = DATA_PATH / 'templates/api/'
|
||||
@@ -91,22 +89,6 @@ def _filtered_keyboard_list():
|
||||
return keyboard_list
|
||||
|
||||
|
||||
def _resolve_xap_specs(output_folder):
|
||||
"""To make it easier for consumers, publish pre-merged spec files
|
||||
"""
|
||||
overall = None
|
||||
for file in get_xap_definition_files():
|
||||
overall = update_xap_definitions(overall, hjson.load(file.open(encoding='utf-8')))
|
||||
|
||||
# Inject dummy bits for unspecified response flags
|
||||
for n in range(0, 8):
|
||||
if str(n) not in overall['response_flags']['bits']:
|
||||
overall['response_flags']['bits'][str(n)] = {'name': '', 'description': '', 'define': '-'}
|
||||
|
||||
output_file = output_folder / (file.stem + ".json")
|
||||
output_file.write_text(json.dumps(overall, indent=4), encoding='utf-8')
|
||||
|
||||
|
||||
@cli.argument('-n', '--dry-run', arg_only=True, action='store_true', help="Don't write the data to disk.")
|
||||
@cli.argument('-f', '--filter', arg_only=True, action='append', default=[], help="Filter the list of keyboards based on partial name matches the supplied value. May be passed multiple times.")
|
||||
@cli.subcommand('Generate QMK API data', hidden=False if cli.config.user.developer else True)
|
||||
@@ -204,7 +186,6 @@ def generate_api(cli):
|
||||
|
||||
# Feature specific handling
|
||||
_resolve_keycode_specs(v1_dir)
|
||||
_resolve_xap_specs(v1_dir / 'xap')
|
||||
|
||||
# Write the global JSON files
|
||||
keyboard_all_json = json.dumps({'last_updated': current_datetime(), 'keyboards': kb_all}, separators=(',', ':'))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user