use crate::base_packet::{MCTPMessageBody, MCTPTransportHeader};
use crate::control_packet::RoutingInformationUpdateEntryType;
use crate::mctp_traits::MCTPHeader;
use smbus_pec::pec;
pub const HDR_VERSION: u8 = 0b001;
pub(crate) const MCTP_SMBUS_COMMAND_CODE: u8 = 0x0F;
bitfield! {
pub struct MCTPSMBusHeader([u8]);
u8;
pub dest_read_write, set_dest_read_write: 0, 0;
pub dest_slave_addr, set_dest_slave_addr : 7, 1;
pub command_code, set_command_code: 15, 8;
pub byte_count, set_byte_count: 23, 16;
pub source_read_write, set_source_read_write: 24, 24;
pub source_slave_addr, set_source_slave_addr: 30, 25;
}
impl MCTPSMBusHeader<[u8; 4]> {
pub fn new() -> Self {
let buf = [0; 4];
MCTPSMBusHeader(buf)
}
pub fn new_from_buf(buf: [u8; 4]) -> Self {
MCTPSMBusHeader(buf)
}
}
impl Default for MCTPSMBusHeader<[u8; 4]> {
fn default() -> Self {
Self::new()
}
}
pub(crate) struct MCTPSMBusPacket<'a, 'b> {
smbus_header: &'a mut MCTPSMBusHeader<[u8; 4]>,
base_header: &'a MCTPTransportHeader<[u8; 4]>,
data_bytes: &'a MCTPMessageBody<'a, 'b>,
}
impl<'a, 'b> MCTPSMBusPacket<'a, 'b> {
pub fn new(
smbus_header: &'a mut MCTPSMBusHeader<[u8; 4]>,
base_header: &'a MCTPTransportHeader<[u8; 4]>,
data_bytes: &'b MCTPMessageBody,
) -> Self {
let mut packet = Self {
smbus_header,
base_header,
data_bytes,
};
packet.finalise();
packet
}
fn finalise(&mut self) {
self.smbus_header.set_byte_count(self.len() as u8 - 4);
}
}
impl<'a, 'b> MCTPHeader for MCTPSMBusPacket<'a, 'b> {
fn len(&self) -> usize {
let mut size = 0;
size += 4;
size += 4;
size += self.data_bytes.len();
size += 1;
size
}
fn to_raw_bytes(&self, buf: &mut [u8]) -> usize {
let mut size = 0;
buf[0..4].copy_from_slice(&self.smbus_header.0);
size += 4;
buf[4..8].copy_from_slice(&self.base_header.0);
size += 4;
size += self.data_bytes.to_raw_bytes(&mut buf[size..]);
buf[size] = pec(&buf[0..size]);
size += 1;
size
}
}
bitfield! {
pub struct SMBusRoutingInformationUpdateEntry([u8]);
u8;
pub entry_type, set_entry_type: 3, 0;
_rsvd, _: 7, 4;
pub eid_range_size, set_eid_range_size: 15, 8;
pub first_eid, set_first_eid: 23, 16;
pub physical_address, set_physical_address: 31, 24;
}
impl SMBusRoutingInformationUpdateEntry<[u8; 4]> {
pub fn new(
entry_type: RoutingInformationUpdateEntryType,
range_size: u8,
first_eid: u8,
physical_address: u8,
) -> Self {
let buf = [0; 4];
let mut format = SMBusRoutingInformationUpdateEntry(buf);
format.set_entry_type(entry_type as u8);
format.set_eid_range_size(range_size);
format.set_first_eid(first_eid);
format.set_physical_address(physical_address);
format
}
pub fn new_from_buf(buf: [u8; 4]) -> Self {
SMBusRoutingInformationUpdateEntry(buf)
}
}