use crate::connection::{Channel, IpmiCommand, Message, NetFn, NotEnoughData};
pub struct GetChannelInfo {
channel: Channel,
}
impl GetChannelInfo {
pub fn new(channel: Channel) -> Self {
Self { channel }
}
}
impl From<GetChannelInfo> for Message {
fn from(value: GetChannelInfo) -> Self {
let channel = value.channel.value() & 0x0F;
Message::new_request(NetFn::App, 0x42, vec![channel])
}
}
impl IpmiCommand for GetChannelInfo {
type Output = ChannelInfo;
type Error = NotEnoughData;
fn parse_success_response(data: &[u8]) -> Result<Self::Output, Self::Error> {
ChannelInfo::parse(data).ok_or(NotEnoughData)
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ChannelInfo {
pub channel: Channel,
pub medium_type: ChannelMediumType,
pub protocol_type: ChannelProtocolType,
pub session_support: ChannelSessionSupport,
pub active_sessions: u8,
pub vendor_id: u32,
pub aux_info: AuxChannelInfo,
}
impl ChannelInfo {
pub fn parse(data: &[u8]) -> Option<Self> {
if data.len() < 9 {
return None;
}
let channel_raw = data[0] & 0x0F;
let channel = Channel::new(channel_raw)?;
let medium_type = ChannelMediumType::from(data[1] & 0x7F);
let protocol_type = ChannelProtocolType::from(data[2] & 0x1F);
let session_support = ChannelSessionSupport::from((data[3] >> 6) & 0x03);
let active_sessions = data[3] & 0x3F;
let vendor_id = u32::from_le_bytes([data[4], data[5], data[6], 0]);
let aux_info = AuxChannelInfo {
byte1: data[7],
byte2: data[8],
};
Some(Self {
channel,
medium_type,
protocol_type,
session_support,
active_sessions,
vendor_id,
aux_info,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct AuxChannelInfo {
pub byte1: u8,
pub byte2: u8,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelMediumType {
Reserved,
Ipmb,
IcmbV1_0,
IcmbV0_9,
Lan802_3,
AsynchSerialModem,
OtherLan,
PciSmbus,
SmbusV1_0,
SmbusV2_0,
Usb1X,
Usb2X,
SystemInterface,
Oem(u8),
ReservedValue(u8),
}
impl From<u8> for ChannelMediumType {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Reserved,
0x01 => Self::Ipmb,
0x02 => Self::IcmbV1_0,
0x03 => Self::IcmbV0_9,
0x04 => Self::Lan802_3,
0x05 => Self::AsynchSerialModem,
0x06 => Self::OtherLan,
0x07 => Self::PciSmbus,
0x08 => Self::SmbusV1_0,
0x09 => Self::SmbusV2_0,
0x0A => Self::Usb1X,
0x0B => Self::Usb2X,
0x0C => Self::SystemInterface,
0x60..=0x7F => Self::Oem(value),
_ => Self::ReservedValue(value),
}
}
}
impl core::fmt::Display for ChannelMediumType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ChannelMediumType::Reserved => write!(f, "Reserved"),
ChannelMediumType::Ipmb => write!(f, "IPMB (I2C)"),
ChannelMediumType::IcmbV1_0 => write!(f, "ICMB v1.0"),
ChannelMediumType::IcmbV0_9 => write!(f, "ICMB v0.9"),
ChannelMediumType::Lan802_3 => write!(f, "802.3 LAN"),
ChannelMediumType::AsynchSerialModem => write!(f, "Asynchronous Serial/Modem"),
ChannelMediumType::OtherLan => write!(f, "Other LAN"),
ChannelMediumType::PciSmbus => write!(f, "PCI SMBus"),
ChannelMediumType::SmbusV1_0 => write!(f, "SMBus v1.0/1.1"),
ChannelMediumType::SmbusV2_0 => write!(f, "SMBus v2.0"),
ChannelMediumType::Usb1X => write!(f, "USB 1.x (reserved)"),
ChannelMediumType::Usb2X => write!(f, "USB 2.x (reserved)"),
ChannelMediumType::SystemInterface => write!(f, "System Interface"),
ChannelMediumType::Oem(value) => write!(f, "OEM (0x{value:02X})"),
ChannelMediumType::ReservedValue(value) => write!(f, "Reserved (0x{value:02X})"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelProtocolType {
Reserved,
IpmbV1_0,
IcmbV1_0,
IpmiSmbus,
Kcs,
Smic,
Bt10,
Bt15,
TerminalMode,
Oem(u8),
ReservedValue(u8),
}
impl From<u8> for ChannelProtocolType {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Reserved,
0x01 => Self::IpmbV1_0,
0x02 => Self::IcmbV1_0,
0x04 => Self::IpmiSmbus,
0x05 => Self::Kcs,
0x06 => Self::Smic,
0x07 => Self::Bt10,
0x08 => Self::Bt15,
0x09 => Self::TerminalMode,
0x1C..=0x1F => Self::Oem(value),
_ => Self::ReservedValue(value),
}
}
}
impl core::fmt::Display for ChannelProtocolType {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ChannelProtocolType::Reserved => write!(f, "Reserved"),
ChannelProtocolType::IpmbV1_0 => write!(f, "IPMB-1.0"),
ChannelProtocolType::IcmbV1_0 => write!(f, "ICMB-1.0"),
ChannelProtocolType::IpmiSmbus => write!(f, "IPMI-SMBus"),
ChannelProtocolType::Kcs => write!(f, "KCS"),
ChannelProtocolType::Smic => write!(f, "SMIC"),
ChannelProtocolType::Bt10 => write!(f, "BT-10"),
ChannelProtocolType::Bt15 => write!(f, "BT-15"),
ChannelProtocolType::TerminalMode => write!(f, "Terminal Mode"),
ChannelProtocolType::Oem(value) => write!(f, "OEM (0x{value:02X})"),
ChannelProtocolType::ReservedValue(value) => write!(f, "Reserved (0x{value:02X})"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelSessionSupport {
Sessionless,
SingleSession,
MultiSession,
SessionBased,
Reserved(u8),
}
impl From<u8> for ChannelSessionSupport {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Sessionless,
0x01 => Self::SingleSession,
0x02 => Self::MultiSession,
0x03 => Self::SessionBased,
v => Self::Reserved(v),
}
}
}
impl core::fmt::Display for ChannelSessionSupport {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ChannelSessionSupport::Sessionless => write!(f, "Session-less"),
ChannelSessionSupport::SingleSession => write!(f, "Single-session"),
ChannelSessionSupport::MultiSession => write!(f, "Multi-session"),
ChannelSessionSupport::SessionBased => write!(f, "Session-based"),
ChannelSessionSupport::Reserved(value) => write!(f, "Reserved (0x{value:02X})"),
}
}
}