use rmk_types::constants;
use rmk_types::protocol::rynk::command::{
BootloaderJump, GetCapabilities, GetDeviceInfo, GetLockStatus, GetVersion, Lock, Reboot, StorageReset, UnlockPoll,
};
use rmk_types::protocol::rynk::{
DEVICE_INFO_STRING_SIZE, DeviceCapabilities, DeviceInfo, FirmwareVersion, LockStatus, MAX_BULK_ITEMS,
MAX_BULK_KEYS, ProtocolVersion, RYNK_MAX_PAYLOAD_SIZE, RynkError, StorageResetMode,
};
use super::super::RynkService;
use super::Handle;
use crate::host::lock::HostLock;
const RMK_VERSION: FirmwareVersion = {
const fn component(s: &str) -> u8 {
let bytes = s.as_bytes();
let mut i = 0;
let mut value = 0u8;
while i < bytes.len() {
value = value * 10 + (bytes[i] - b'0');
i += 1;
}
value
}
FirmwareVersion {
major: component(env!("CARGO_PKG_VERSION_MAJOR")),
minor: component(env!("CARGO_PKG_VERSION_MINOR")),
patch: component(env!("CARGO_PKG_VERSION_PATCH")),
}
};
impl Handle<GetVersion> for RynkService<'_> {
async fn handle(&self, _: ()) -> Result<ProtocolVersion, RynkError> {
Ok(ProtocolVersion::CURRENT)
}
}
impl Handle<GetCapabilities> for RynkService<'_> {
async fn handle(&self, _: ()) -> Result<DeviceCapabilities, RynkError> {
let (rows, cols, num_layers) = self.ctx.keymap_dimensions();
Ok(DeviceCapabilities {
num_layers: num_layers as u8,
num_rows: rows as u8,
num_cols: cols as u8,
num_encoders: self.ctx.num_encoders() as u8,
max_combos: constants::COMBO_MAX_NUM as u8,
max_combo_keys: constants::COMBO_MAX_LENGTH as u8,
macro_space_size: constants::MACRO_SPACE_SIZE as u16,
max_morse: constants::MORSE_MAX_NUM as u8,
max_patterns_per_key: constants::MAX_PATTERNS_PER_KEY as u8,
max_forks: constants::FORK_MAX_NUM as u8,
storage_enabled: cfg!(feature = "storage"),
lighting_enabled: false,
is_split: cfg!(feature = "split"),
num_split_peripherals: constants::SPLIT_PERIPHERALS_NUM as u8,
ble_enabled: cfg!(feature = "_ble"),
num_ble_profiles: constants::NUM_BLE_PROFILE as u8,
max_payload_size: RYNK_MAX_PAYLOAD_SIZE as u16,
macro_chunk_size: constants::MACRO_DATA_SIZE as u16,
max_bulk_keys: MAX_BULK_KEYS as u8,
max_bulk_items: MAX_BULK_ITEMS as u8,
bulk_transfer_supported: true,
})
}
}
impl Handle<Reboot> for RynkService<'_> {
async fn handle(&self, _: ()) -> Result<(), RynkError> {
crate::boot::reboot_keyboard();
Ok(())
}
}
impl Handle<BootloaderJump> for RynkService<'_> {
async fn handle(&self, _: ()) -> Result<(), RynkError> {
crate::boot::jump_to_bootloader();
Ok(())
}
}
impl Handle<StorageReset> for RynkService<'_> {
async fn handle(&self, mode: StorageResetMode) -> Result<(), RynkError> {
if mode != StorageResetMode::Full {
return Err(RynkError::Unimplemented);
}
self.ctx.reset_storage().await;
Ok(())
}
}
impl Handle<GetLockStatus> for HostLock<'_> {
async fn handle(&self, _: ()) -> Result<LockStatus, RynkError> {
Ok(self.status())
}
}
impl Handle<UnlockPoll> for HostLock<'_> {
async fn handle(&self, _: ()) -> Result<LockStatus, RynkError> {
Ok(self.poll())
}
}
impl Handle<Lock> for HostLock<'_> {
async fn handle(&self, _: ()) -> Result<(), RynkError> {
self.lock();
Ok(())
}
}
impl Handle<GetDeviceInfo> for RynkService<'_> {
async fn handle(&self, _: ()) -> Result<DeviceInfo, RynkError> {
Ok(DeviceInfo {
rmk_version: RMK_VERSION,
vendor_id: self.device.vid,
product_id: self.device.pid,
manufacturer: truncated(self.device.manufacturer),
product_name: truncated(self.device.product_name),
serial_number: truncated(self.device.serial_number),
})
}
}
fn truncated(s: &str) -> heapless::String<DEVICE_INFO_STRING_SIZE> {
let mut out = heapless::String::new();
for c in s.chars() {
if out.push(c).is_err() {
break;
}
}
out
}