use crate::mboot::tags::{
ToAddress, command::CommandTag, command_flag::CommandFlag, command_response::CmdResponseTag, status::StatusCode,
};
use super::{Packet, construct_header};
#[derive(Clone, Debug)]
pub struct CommandHeader {
pub flag: CommandFlag,
pub reserved: u8,
}
impl CommandHeader {
#[must_use]
pub fn construct_frame(&self, params: &[u32], command_code: u8) -> Vec<u8> {
let mut command_part = vec![command_code, self.flag.code(), self.reserved, params.len() as u8];
command_part.reserve(params.len() * 4);
command_part.extend(params.iter().flat_map(|num| num.to_le_bytes()));
construct_header(super::CMD, command_part)
}
}
#[derive(Clone, Debug)]
pub struct CommandPacket<'a> {
pub header: CommandHeader,
pub tag: CommandTag<'a>,
}
#[derive(Clone, Debug)]
pub struct CmdResponse {
pub header: CommandHeader,
pub status: StatusCode,
pub tag: CmdResponseTag,
}
impl Packet for CommandPacket<'_> {
fn get_code() -> u8 {
super::CMD
}
}
impl<'a> CommandPacket<'a> {
#[must_use]
pub fn new_none_flag(tag: CommandTag<'a>) -> Self {
CommandPacket {
header: CommandHeader {
flag: CommandFlag::NoData,
reserved: 0,
},
tag,
}
}
#[must_use]
pub fn new_data_phase(tag: CommandTag<'a>) -> Self {
CommandPacket {
header: CommandHeader {
flag: CommandFlag::HasDataPhase,
reserved: 0,
},
tag,
}
}
}
impl Packet for CmdResponse {
fn get_code() -> u8 {
super::CMD
}
}
#[cfg(test)]
mod tests {
use crate::mboot::{
packets::command::{CommandHeader, CommandPacket},
tags::{
ToAddress,
command::{CommandTag, CommandToParams},
command_flag::CommandFlag,
property::PropertyTagDiscriminants,
},
};
fn get_command(tag: CommandTag) -> CommandPacket {
CommandPacket {
header: CommandHeader {
flag: CommandFlag::NoData,
reserved: 0,
},
tag,
}
}
#[test]
fn test_command_construct_version() {
let cmd = get_command(CommandTag::GetProperty {
tag: PropertyTagDiscriminants::CurrentVersion,
memory_index: 0,
});
let bytes = cmd.header.construct_frame(&cmd.tag.to_params().0, cmd.tag.code());
assert_eq!(
bytes,
[
0x5a, 0xa4, 0xc, 0x0, 0x4b, 0x33, 0x7, 0x0, 0x0, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
]
);
}
#[test]
fn test_command_flash_program_once() {
let cmd = get_command(CommandTag::FlashProgramOnce {
index: 0x51,
count: 4,
data: 0x12345678,
});
let bytes = cmd.header.construct_frame(&cmd.tag.to_params().0, cmd.tag.code());
assert_eq!(
bytes,
[
90, 164, 16, 0, 27, 96, 14, 0, 0, 3, 81, 0, 0, 0, 4, 0, 0, 0, 120, 86, 52, 18
]
);
}
}