Support RMK device config

This commit is contained in:
Jakub Hlusička 2026-02-12 22:44:13 +01:00
parent 8e304540ea
commit 5004e8dfdf
3 changed files with 79 additions and 10 deletions

View file

@ -3,8 +3,6 @@ name = "acid-firmware"
version = "0.1.0"
authors = ['Jakub "Limeth" Hlusička']
description = "Firmware for the ACID keyboard"
homepage = "https://github.com/haobogu/rmk"
repository = "https://github.com/haobogu/rmk"
edition = "2024"
[features]

View file

@ -149,16 +149,58 @@ fn generate_vial_config() {
};
let vial_cfg = json::parse(&content).unwrap();
let vial_cfg_string = json::stringify(vial_cfg.clone());
let mut keyboard_def_compressed: Vec<u8> = Vec::new();
XzEncoder::new(vial_cfg_string.as_bytes(), 6)
.read_to_end(&mut keyboard_def_compressed)
.unwrap();
let keyboard_id: Vec<u8> = vec![0xB9, 0xBC, 0x09, 0xB2, 0x9D, 0x37, 0x4C, 0xEA];
let keyboard_def_compressed: Vec<u8> = {
let vial_cfg_string = json::stringify(vial_cfg.clone());
let mut keyboard_def_compressed = Vec::new();
XzEncoder::new(vial_cfg_string.as_bytes(), 6)
.read_to_end(&mut keyboard_def_compressed)
.unwrap();
keyboard_def_compressed
};
// This is a firmware-unique randomly generated ID.
// If you fork this repo to make your own firmware, you should change this.
let keyboard_id: Vec<u8> = vec![0x9a, 0x8a, 0x08, 0xae, 0x87, 0xcd, 0xc7, 0xb9];
let keyboard_name: &str = {
let JsonValue::Object(vial_cfg) = &vial_cfg else {
panic!("The root element in `vial.json` is not an object.");
};
vial_cfg
.get("name")
.expect("No `name` in `vial.json`.")
.as_str()
.expect("`name` in `vial.json` is not a string.")
};
let vendor_id: u16 = {
let JsonValue::Object(vial_cfg) = &vial_cfg else {
panic!("The root element in `vial.json` is not an object.");
};
let vendor_id_string = vial_cfg
.get("vendorId")
.expect("No `vendorId` in `vial.json`.")
.as_str()
.expect("`vendorId` in `vial.json` is not a string.");
assert!(vendor_id_string.starts_with("0x"));
u16::from_str_radix(&vendor_id_string[2..], 16).expect("Invalid vendor ID.")
};
let product_id: u16 = {
let JsonValue::Object(vial_cfg) = &vial_cfg else {
panic!("The root element in `vial.json` is not an object.");
};
let product_id_string = vial_cfg
.get("productId")
.expect("No `productId` in `vial.json`.")
.as_str()
.expect("`productId` in `vial.json` is not a string.");
assert!(product_id_string.starts_with("0x"));
u16::from_str_radix(&product_id_string[2..], 16).expect("Invalid product ID.")
};
let const_declarations = [
const_declaration!(pub VIAL_KEYBOARD_DEF = keyboard_def_compressed),
const_declaration!(pub VIAL_KEYBOARD_ID = keyboard_id),
const_declaration!(pub VIAL_KEYBOARD_NAME = keyboard_name),
const_declaration!(pub VIAL_VENDOR_ID = vendor_id),
const_declaration!(pub VIAL_PRODUCT_ID = product_id),
]
.map(|s| "#[allow(clippy::redundant_static_lifetimes)]\n".to_owned() + s.as_str())
.join("\n");

View file

@ -23,6 +23,7 @@ use core::sync::atomic::{AtomicBool, Ordering};
use alloc::boxed::Box;
use alloc::collections::vec_deque::VecDeque;
use alloc::format;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec;
@ -40,6 +41,7 @@ use esp_bootloader_esp_idf::partitions::PartitionTable;
use esp_hal::Blocking;
use esp_hal::clock::CpuClock;
use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig};
use esp_hal::efuse::Efuse;
use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull};
use esp_hal::i2c::master::{I2c, I2cAddress};
use esp_hal::interrupt::software::SoftwareInterruptControl;
@ -55,9 +57,12 @@ use esp_hal::timer::timg::TimerGroup;
use esp_rtos::embassy::Executor;
use esp_storage::FlashStorage;
use indoc::writedoc;
use itertools::Itertools;
use log::{error, info, warn};
use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub};
use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig};
use rmk::config::{
BehaviorConfig, DeviceConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig,
};
use rmk::controller::{Controller, EventController};
use rmk::debounce::default_debouncer::DefaultDebouncer;
use rmk::event::ControllerEvent;
@ -77,7 +82,10 @@ use crate::logging::LOG_LEVEL_FILTER;
use crate::matrix::IoeMatrix;
use crate::peripherals::st7701s::St7701s;
use crate::ui::backend::{FramebufferPtr, SlintBackend};
use crate::vial::{CustomKeycodes, VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID};
use crate::vial::{
CustomKeycodes, VIAL_KEYBOARD_DEF, VIAL_KEYBOARD_ID, VIAL_KEYBOARD_NAME, VIAL_PRODUCT_ID,
VIAL_VENDOR_ID,
};
mutually_exclusive_features::none_or_one_of!["usb-log", "alt-log", "rtt-log"];
@ -388,7 +396,28 @@ async fn main(_spawner: Spawner) {
},
..Default::default()
};
// Retrieve the hardware-unique MAC address.
let mac_address = Efuse::read_base_mac_address();
static SERIAL_NUMBER: StaticCell<Box<str>> = StaticCell::new();
let serial_number = SERIAL_NUMBER.init_with(|| {
/// A magic prefix string that is required for the device to be recognized by the Vial GUI.
const VIAL_SERIAL_PREFIX: &str = "vial:f64c2b3c";
format!(
"{VIAL_SERIAL_PREFIX}:acid:{:02x}",
mac_address.iter().format("")
)
.into_boxed_str()
});
let device_config = DeviceConfig {
vid: VIAL_VENDOR_ID,
pid: VIAL_PRODUCT_ID,
manufacturer: "",
product_name: VIAL_KEYBOARD_NAME,
serial_number,
};
info!("RMK Device Config: {device_config:#04x?}");
let rmk_config = RmkConfig {
device_config,
vial_config,
storage_config,
..Default::default()