diff --git a/common_features.mk b/common_features.mk
index ed6908f4b8..59f141f212 100644
--- a/common_features.mk
+++ b/common_features.mk
@@ -364,6 +364,17 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
OPT_DEFS += -DVIA_ENABLE
endif
+ifeq ($(strip $(VIAL_ENABLE)), yes)
+ SRC += $(QUANTUM_DIR)/vial.c
+ EXTRAINCDIRS += $(KEYMAP_OUTPUT)
+ OPT_DEFS += -DVIAL_ENABLE
+
+$(QUANTUM_DIR)/vial.c: $(KEYMAP_OUTPUT)/vial_generated_keyboard_definition.h
+
+$(KEYMAP_OUTPUT)/vial_generated_keyboard_definition.h: $(KEYMAP_PATH)/vial.json
+ python3 util/vial_generate_definition.py $(KEYMAP_PATH)/vial.json $(KEYMAP_OUTPUT)/vial_generated_keyboard_definition.h
+endif
+
ifeq ($(strip $(DYNAMIC_KEYMAP_ENABLE)), yes)
OPT_DEFS += -DDYNAMIC_KEYMAP_ENABLE
SRC += $(QUANTUM_DIR)/dynamic_keymap.c
diff --git a/quantum/via.c b/quantum/via.c
index 7c3b7f9248..263c0f4958 100644
--- a/quantum/via.c
+++ b/quantum/via.c
@@ -47,6 +47,10 @@
#include "tmk_core/common/eeprom.h"
#include "version.h" // for QMK_BUILDDATE used in EEPROM magic
+#ifdef VIAL_ENABLE
+#include "vial.h"
+#endif
+
// Forward declare some helpers.
#if defined(VIA_QMK_BACKLIGHT_ENABLE)
void via_qmk_backlight_set_value(uint8_t *data);
@@ -383,6 +387,12 @@ void raw_hid_receive(uint8_t *data, uint8_t length) {
bootloader_jump();
break;
}
+#ifdef VIAL_ENABLE
+ case 0xFE: {
+ vial_handle_cmd(data, length);
+ break;
+ }
+#endif
default: {
// The command ID is not known
// Return the unhandled state
diff --git a/quantum/vial.c b/quantum/vial.c
new file mode 100644
index 0000000000..da3946662f
--- /dev/null
+++ b/quantum/vial.c
@@ -0,0 +1,56 @@
+/* Copyright 2020 Ilya Zhuravlev
+ *
+ * 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 .
+ */
+
+#include
+#include "protocol/usb_descriptor.h"
+
+#include "vial_generated_keyboard_definition.h"
+
+enum {
+ vial_get_size = 0x01,
+ vial_get_def = 0x02,
+};
+
+void vial_handle_cmd(uint8_t *msg, uint8_t length) {
+ /* All packets must be fixed 32 bytes */
+ if (length != RAW_EPSIZE)
+ return;
+
+ /* msg[0] is 0xFE -- prefix vial magic */
+ switch (msg[1]) {
+ /* Retrieve keyboard definition size */
+ case vial_get_size: {
+ uint32_t sz = sizeof(keyboard_definition);
+ msg[0] = sz & 0xFF;
+ msg[1] = (sz >> 8) & 0xFF;
+ msg[2] = (sz >> 16) & 0xFF;
+ msg[3] = (sz >> 24) & 0xFF;
+ break;
+ }
+ /* Retrieve 32-bytes block of the definition, page ID encoded within 2 bytes */
+ case vial_get_def: {
+ uint32_t page = msg[2] + (msg[3] << 8);
+ uint32_t start = page * RAW_EPSIZE;
+ uint32_t end = start + RAW_EPSIZE;
+ if (end < start || start >= sizeof(keyboard_definition))
+ return;
+ if (end > sizeof(keyboard_definition))
+ end = sizeof(keyboard_definition);
+ memcpy(msg, &keyboard_definition[start], end - start);
+ break;
+ }
+ }
+}
diff --git a/quantum/vial.h b/quantum/vial.h
new file mode 100644
index 0000000000..5c79843c83
--- /dev/null
+++ b/quantum/vial.h
@@ -0,0 +1,19 @@
+/* Copyright 2020 Ilya Zhuravlev
+ *
+ * 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 .
+ */
+
+#pragma once
+
+void vial_handle_cmd(uint8_t *data, uint8_t length);
diff --git a/tmk_core/protocol/usb_descriptor.c b/tmk_core/protocol/usb_descriptor.c
index f5d32445de..d06db9b137 100644
--- a/tmk_core/protocol/usb_descriptor.c
+++ b/tmk_core/protocol/usb_descriptor.c
@@ -940,8 +940,12 @@ const USB_Descriptor_String_t PROGMEM ProductString = {
};
#ifndef SERIAL_NUMBER
+#ifdef VIAL_ENABLE
+# define SERIAL_NUMBER vial:f64c2b3c
+#else
# define SERIAL_NUMBER 0
#endif
+#endif
const USB_Descriptor_String_t PROGMEM SerialNumberString = {
.Header = {
diff --git a/tmk_core/protocol/vusb/vusb.c b/tmk_core/protocol/vusb/vusb.c
index 77bbbd7bd4..4989f7aa43 100644
--- a/tmk_core/protocol/vusb/vusb.c
+++ b/tmk_core/protocol/vusb/vusb.c
@@ -532,8 +532,12 @@ const PROGMEM uchar console_hid_report[] = {
#endif
#ifndef SERIAL_NUMBER
+#ifdef VIAL_ENABLE
+# define SERIAL_NUMBER vial:f64c2b3c
+#else
# define SERIAL_NUMBER 0
#endif
+#endif
#ifndef USB_MAX_POWER_CONSUMPTION
# define USB_MAX_POWER_CONSUMPTION 500
diff --git a/util/vial_generate_definition.py b/util/vial_generate_definition.py
new file mode 100755
index 0000000000..0981f096a3
--- /dev/null
+++ b/util/vial_generate_definition.py
@@ -0,0 +1,30 @@
+#!/usr/bin/env python3
+import sys
+import json
+import lzma
+
+def main():
+ if len(sys.argv) != 3:
+ print("Usage: vial_generate_defition.py path-to-vial.json path-to-output.h")
+ return 1
+
+ with open(sys.argv[1], "r") as inf:
+ data = inf.read()
+
+ # minify json
+ data = json.dumps(json.loads(data), separators=(',', ':')).strip()
+
+ # compress
+ data = lzma.compress(data.encode("utf-8"))
+
+ with open(sys.argv[2], "w") as outf:
+ outf.write("#pragma once\n")
+ outf.write("static const unsigned char keyboard_definition[] PROGMEM = {")
+ arr = ["0x{:02X}".format(b) for b in data]
+ outf.write(", ".join(arr))
+ outf.write("};\n")
+
+ return 0
+
+if __name__ == "__main__":
+ sys.exit(main())