use crate::core::{strings::*, UndefinedStruct};
use crate::SMBiosStruct;
use serde::{ser::SerializeSeq, ser::SerializeStruct, Serialize, Serializer};
use std::{convert::TryInto, fmt, ops::Deref};
pub struct SMBiosSystemSlot<'a> {
parts: &'a UndefinedStruct,
}
impl<'a> SMBiosStruct<'a> for SMBiosSystemSlot<'a> {
const STRUCT_TYPE: u8 = 9u8;
fn new(parts: &'a UndefinedStruct) -> Self {
Self { parts }
}
fn parts(&self) -> &'a UndefinedStruct {
self.parts
}
}
impl<'a> SMBiosSystemSlot<'a> {
pub fn slot_designation(&self) -> SMBiosString {
self.parts.get_field_string(0x04)
}
pub fn system_slot_type(&self) -> Option<SystemSlotTypeData> {
self.parts
.get_field_byte(0x05)
.map(|raw| SystemSlotTypeData::from(raw))
}
pub fn slot_data_bus_width(&self) -> Option<SlotWidthData> {
self.parts
.get_field_byte(0x06)
.map(|raw| SlotWidthData::from(raw))
}
pub fn current_usage(&self) -> Option<SlotCurrentUsageData> {
self.parts
.get_field_byte(0x07)
.map(|raw| SlotCurrentUsageData::from(raw))
}
pub fn slot_length(&self) -> Option<SlotLengthData> {
self.parts
.get_field_byte(0x08)
.map(|raw| SlotLengthData::from(raw))
}
pub fn slot_id(&self) -> Option<SystemSlotId> {
self.parts
.get_field_data(0x09, 0x0B)
.map(|id| SystemSlotId(id.try_into().unwrap()))
}
pub fn slot_characteristics_1(&self) -> Option<SystemSlotCharacteristics1> {
self.parts
.get_field_byte(0x0B)
.map(|raw| SystemSlotCharacteristics1::from(raw))
}
pub fn slot_characteristics_2(&self) -> Option<SystemSlotCharacteristics2> {
self.parts
.get_field_byte(0x0C)
.map(|raw| SystemSlotCharacteristics2::from(raw))
}
pub fn segment_group_number(&self) -> Option<SegmentGroupNumber> {
self.parts
.get_field_word(0x0D)
.map(|raw| SegmentGroupNumber::from(raw))
}
pub fn bus_number(&self) -> Option<BusNumber> {
self.parts
.get_field_byte(0x0F)
.map(|raw| BusNumber::from(raw))
}
pub fn device_function_number(&self) -> Option<DeviceFunctionNumber> {
self.parts
.get_field_byte(0x10)
.map(|raw| DeviceFunctionNumber::from(raw))
}
pub fn data_bus_width(&self) -> Option<u8> {
self.parts.get_field_byte(0x11)
}
pub fn peer_group_count(&self) -> Option<usize> {
self.parts
.get_field_byte(0x12)
.and_then(|count| Some(count as usize))
}
fn peer_group_size(&self) -> Option<usize> {
self.peer_group_count()
.and_then(|count| Some(count as usize * SlotPeerGroup::SIZE))
}
pub fn peer_group_iterator(&'a self) -> SlotPeerGroupIterator<'a> {
SlotPeerGroupIterator::new(self)
}
pub fn slot_information(&self) -> Option<u8> {
self.peer_group_size()
.and_then(|size| self.parts.get_field_byte(size + 0x13))
}
pub fn slot_physical_width(&self) -> Option<SlotWidthData> {
self.peer_group_size().and_then(|size| {
self.parts
.get_field_byte(size + 0x14)
.map(|raw| SlotWidthData::from(raw))
})
}
pub fn slot_pitch(&self) -> Option<u16> {
self.peer_group_size()
.and_then(|size| self.parts.get_field_word(size + 0x15))
}
pub fn slot_height(&self) -> Option<SlotHeightData> {
self.peer_group_size().and_then(|size| {
self.parts
.get_field_byte(size + 0x17)
.map(|raw| SlotHeightData::from(raw))
})
}
}
impl fmt::Debug for SMBiosSystemSlot<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SMBiosSystemSlot<'_>>())
.field("header", &self.parts.header)
.field("slot_designation", &self.slot_designation())
.field("system_slot_type", &self.system_slot_type())
.field("slot_data_bus_width", &self.slot_data_bus_width())
.field("current_usage", &self.current_usage())
.field("slot_length", &self.slot_length())
.field("slot_id", &self.slot_id())
.field("slot_characteristics_1", &self.slot_characteristics_1())
.field("slot_characteristics_2", &self.slot_characteristics_2())
.field("segment_group_number", &self.segment_group_number())
.field("bus_number", &self.bus_number())
.field("device_function_number", &self.device_function_number())
.field("data_bus_width", &self.data_bus_width())
.field("peer_group_count", &self.peer_group_count())
.field("peer_group_iterator", &self.peer_group_iterator())
.field("slot_information", &self.slot_information())
.field("slot_physical_width", &self.slot_physical_width())
.field("slot_pitch", &self.slot_pitch())
.finish()
}
}
impl Serialize for SMBiosSystemSlot<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SMBiosSystemSlot", 18)?;
state.serialize_field("header", &self.parts.header)?;
state.serialize_field("slot_designation", &self.slot_designation())?;
state.serialize_field("system_slot_type", &self.system_slot_type())?;
state.serialize_field("slot_data_bus_width", &self.slot_data_bus_width())?;
state.serialize_field("current_usage", &self.current_usage())?;
state.serialize_field("slot_length", &self.slot_length())?;
state.serialize_field("slot_id", &self.slot_id())?;
state.serialize_field("slot_characteristics_1", &self.slot_characteristics_1())?;
state.serialize_field("slot_characteristics_2", &self.slot_characteristics_2())?;
state.serialize_field("segment_group_number", &self.segment_group_number())?;
state.serialize_field("bus_number", &self.bus_number())?;
state.serialize_field("device_function_number", &self.device_function_number())?;
state.serialize_field("data_bus_width", &self.data_bus_width())?;
state.serialize_field("peer_group_count", &self.peer_group_count())?;
state.serialize_field("peer_group_iterator", &self.peer_group_iterator())?;
state.serialize_field("slot_information", &self.slot_information())?;
state.serialize_field("slot_physical_width", &self.slot_physical_width())?;
state.serialize_field("slot_pitch", &self.slot_pitch())?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
pub struct SystemSlotId(pub [u8; 2]);
impl Deref for SystemSlotId {
type Target = [u8; 2];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl SystemSlotId {
pub fn byte_0(&self) -> u8 {
self.0[0]
}
pub fn byte_1(&self) -> u8 {
self.0[1]
}
}
pub struct SystemSlotTypeData {
pub raw: u8,
pub value: SystemSlotType,
}
impl Deref for SystemSlotTypeData {
type Target = SystemSlotType;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<u8> for SystemSlotTypeData {
fn from(raw: u8) -> Self {
use M2SlotType::*;
use MXMSlotType::*;
use PciExpressGeneration::*;
use PciExpressSlotWidth::*;
use SystemSlotType::*;
SystemSlotTypeData {
value: match raw {
0x01 => Other,
0x02 => Unknown,
0x03 => Isa,
0x04 => Mca,
0x05 => Eisa,
0x06 => Pci,
0x07 => Pcmcia,
0x08 => VlVesa,
0x09 => Proprietary,
0x0A => ProcessorCardSlot,
0x0B => ProprietaryMemoryCardSlot,
0x0C => IORiserCardSlot,
0x0D => NuBus,
0x0E => Pci66MhzCapable,
0x0F => Agp(AgpSlotWidth::X1),
0x10 => Agp(AgpSlotWidth::X2),
0x11 => Agp(AgpSlotWidth::X4),
0x12 => PciX,
0x13 => Agp(AgpSlotWidth::X8),
0x14 => M2(M2Socket1DP),
0x15 => M2(M2Socket1SD),
0x16 => M2(M2Socket2),
0x17 => M2(M2Socket3),
0x18 => Mxm(MxmTypeI),
0x19 => Mxm(MxmTypeII),
0x1A => Mxm(MxmTypeIIIStandard),
0x1B => Mxm(MxmTypeIIIHE),
0x1C => Mxm(MxmTypeIV),
0x1D => Mxm(Mxm3TypeA),
0x1E => Mxm(Mxm3TypeB),
0x1F => PciExpress(PCIExpressGen2, Sff8639),
0x20 => PciExpress(PCIExpressGen3, Sff8639),
0x21 => PciExpress(Undefined, PciExpressMini52WithKeepouts),
0x22 => PciExpress(Undefined, PciExpressMini52WithoutKeepouts),
0x23 => PciExpress(Undefined, PciExpressMini76),
0x24 => PciExpress(PCIExpressGen4, Sff8639),
0x25 => PciExpress(PCIExpressGen5, Sff8639),
0x26 => OcpNic30SmallFormFactor,
0x27 => OcpNic30LargeFormFactor,
0x28 => OcpNicPriorTo30,
0x30 => CxlFlexbus1,
0xA0 => PC98C20,
0xA1 => PC98C24,
0xA2 => PC98E,
0xA3 => PC98LocalBus,
0xA4 => PC98Card,
0xA5 => PciExpress(PCIExpressGen1, UndefinedSlotWidth),
0xA6 => PciExpress(PCIExpressGen1, X1),
0xA7 => PciExpress(PCIExpressGen1, X2),
0xA8 => PciExpress(PCIExpressGen1, X4),
0xA9 => PciExpress(PCIExpressGen1, X8),
0xAA => PciExpress(PCIExpressGen1, X16),
0xAB => PciExpress(PCIExpressGen2, UndefinedSlotWidth),
0xAC => PciExpress(PCIExpressGen2, X1),
0xAD => PciExpress(PCIExpressGen2, X2),
0xAE => PciExpress(PCIExpressGen2, X4),
0xAF => PciExpress(PCIExpressGen2, X8),
0xB0 => PciExpress(PCIExpressGen2, X16),
0xB1 => PciExpress(PCIExpressGen3, UndefinedSlotWidth),
0xB2 => PciExpress(PCIExpressGen3, X1),
0xB3 => PciExpress(PCIExpressGen3, X2),
0xB4 => PciExpress(PCIExpressGen3, X4),
0xB5 => PciExpress(PCIExpressGen3, X8),
0xB6 => PciExpress(PCIExpressGen3, X16),
0xB8 => PciExpress(PCIExpressGen4, UndefinedSlotWidth),
0xB9 => PciExpress(PCIExpressGen4, X1),
0xBA => PciExpress(PCIExpressGen4, X2),
0xBB => PciExpress(PCIExpressGen4, X4),
0xBC => PciExpress(PCIExpressGen4, X8),
0xBD => PciExpress(PCIExpressGen4, X16),
0xBE => PciExpress(PCIExpressGen5, UndefinedSlotWidth),
0xBF => PciExpress(PCIExpressGen5, X1),
0xC0 => PciExpress(PCIExpressGen5, X2),
0xC1 => PciExpress(PCIExpressGen5, X4),
0xC2 => PciExpress(PCIExpressGen5, X8),
0xC3 => PciExpress(PCIExpressGen5, X16),
0xC4 => PciExpress(PCIExpressGen6, UndefinedSlotWidth),
0xC5 => EnterpriseAndDataCenter1UE1,
0xC6 => EnterpriseAndDataCenter3InE3,
_ => None,
},
raw,
}
}
}
impl fmt::Debug for SystemSlotTypeData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SystemSlotTypeData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Serialize for SystemSlotTypeData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SystemSlotTypeData", 2)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
impl fmt::Display for SystemSlotTypeData {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.value {
SystemSlotType::None => write!(f, "{}", &self.raw),
_ => write!(f, "{:?}", &self.value),
}
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SystemSlotType {
Other,
Unknown,
Isa,
Mca,
Eisa,
Pci,
Pcmcia,
VlVesa,
Proprietary,
ProcessorCardSlot,
ProprietaryMemoryCardSlot,
IORiserCardSlot,
NuBus,
Pci66MhzCapable,
Agp(AgpSlotWidth),
Mxm(MXMSlotType),
PciX,
M2(M2SlotType),
OcpNic30SmallFormFactor,
OcpNic30LargeFormFactor,
OcpNicPriorTo30,
CxlFlexbus1,
PC98C20,
PC98C24,
PC98E,
PC98LocalBus,
PC98Card,
PciExpress(PciExpressGeneration, PciExpressSlotWidth),
EnterpriseAndDataCenter1UE1,
EnterpriseAndDataCenter3InE3,
None,
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum PciExpressGeneration {
PCIExpressGen1,
PCIExpressGen2,
PCIExpressGen3,
PCIExpressGen4,
PCIExpressGen5,
PCIExpressGen6,
Undefined,
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum PciExpressSlotWidth {
UndefinedSlotWidth,
X1,
X2,
X4,
X8,
X16,
Sff8639,
PciExpressMini52WithKeepouts,
PciExpressMini52WithoutKeepouts,
PciExpressMini76,
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum AgpSlotWidth {
X1,
X2,
X4,
X8,
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum MXMSlotType {
MxmTypeI,
MxmTypeII,
MxmTypeIIIStandard,
MxmTypeIIIHE,
MxmTypeIV,
Mxm3TypeA,
Mxm3TypeB,
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum M2SlotType {
M2Socket1DP,
M2Socket1SD,
M2Socket2,
M2Socket3,
}
pub struct SlotWidthData {
pub raw: u8,
pub value: SlotWidth,
}
impl Deref for SlotWidthData {
type Target = SlotWidth;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<u8> for SlotWidthData {
fn from(raw: u8) -> Self {
SlotWidthData {
value: match raw {
0x01 => SlotWidth::Other,
0x02 => SlotWidth::Unknown,
0x03 => SlotWidth::Bit8,
0x04 => SlotWidth::Bit16,
0x05 => SlotWidth::Bit32,
0x06 => SlotWidth::Bit64,
0x07 => SlotWidth::Bit128,
0x08 => SlotWidth::X1,
0x09 => SlotWidth::X2,
0x0A => SlotWidth::X4,
0x0B => SlotWidth::X8,
0x0C => SlotWidth::X12,
0x0D => SlotWidth::X16,
0x0E => SlotWidth::X32,
_ => SlotWidth::None,
},
raw,
}
}
}
impl fmt::Debug for SlotWidthData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SlotWidthData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Serialize for SlotWidthData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SlotWidthData", 2)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SlotWidth {
Other,
Unknown,
Bit8,
Bit16,
Bit32,
Bit64,
Bit128,
X1,
X2,
X4,
X8,
X12,
X16,
X32,
None,
}
pub struct SlotHeightData {
pub raw: u8,
pub value: SlotHeight,
}
impl Deref for SlotHeightData {
type Target = SlotHeight;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<u8> for SlotHeightData {
fn from(raw: u8) -> Self {
SlotHeightData {
value: match raw {
0x00 => SlotHeight::NotApplicable,
0x01 => SlotHeight::Other,
0x02 => SlotHeight::Unknown,
0x03 => SlotHeight::FullHeight,
0x04 => SlotHeight::LowProfile,
_ => SlotHeight::None,
},
raw,
}
}
}
impl fmt::Debug for SlotHeightData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SlotHeightData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Serialize for SlotHeightData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SlotHeightData", 2)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SlotHeight {
NotApplicable,
Other,
Unknown,
FullHeight,
LowProfile,
None,
}
pub struct SlotCurrentUsageData {
pub raw: u8,
pub value: SlotCurrentUsage,
}
impl Deref for SlotCurrentUsageData {
type Target = SlotCurrentUsage;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<u8> for SlotCurrentUsageData {
fn from(raw: u8) -> Self {
SlotCurrentUsageData {
value: match raw {
0x01 => SlotCurrentUsage::Other,
0x02 => SlotCurrentUsage::Unknown,
0x03 => SlotCurrentUsage::Available,
0x04 => SlotCurrentUsage::InUse,
0x05 => SlotCurrentUsage::Unavailable,
_ => SlotCurrentUsage::None,
},
raw,
}
}
}
impl fmt::Debug for SlotCurrentUsageData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SlotCurrentUsageData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Serialize for SlotCurrentUsageData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SlotCurrentUsageData", 2)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SlotCurrentUsage {
Other,
Unknown,
Available,
InUse,
Unavailable,
None,
}
pub struct SlotLengthData {
pub raw: u8,
pub value: SlotLength,
}
impl Deref for SlotLengthData {
type Target = SlotLength;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl From<u8> for SlotLengthData {
fn from(raw: u8) -> Self {
use SlotLength::*;
SlotLengthData {
value: match raw {
0x01 => Other,
0x02 => Unknown,
0x03 => ShortLength,
0x04 => LongLength,
0x05 => DriveFormFactor25,
0x06 => DriveFormFactor35,
_ => None,
},
raw,
}
}
}
impl fmt::Debug for SlotLengthData {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SlotLengthData>())
.field("raw", &self.raw)
.field("value", &self.value)
.finish()
}
}
impl Serialize for SlotLengthData {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SlotLengthData", 2)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("value", &self.value)?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SlotLength {
Other,
Unknown,
ShortLength,
LongLength,
DriveFormFactor25,
DriveFormFactor35,
None,
}
#[derive(PartialEq, Eq)]
pub struct SystemSlotCharacteristics1 {
pub raw: u8,
}
impl Deref for SystemSlotCharacteristics1 {
type Target = u8;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u8> for SystemSlotCharacteristics1 {
fn from(raw: u8) -> Self {
SystemSlotCharacteristics1 { raw }
}
}
impl SystemSlotCharacteristics1 {
pub fn unknown(&self) -> bool {
self.raw & 0x01 == 0x01
}
pub fn provides5_volts(&self) -> bool {
self.raw & 0x02 == 0x02
}
pub fn provides33_volts(&self) -> bool {
self.raw & 0x04 == 0x04
}
pub fn shared(&self) -> bool {
self.raw & 0x08 == 0x08
}
pub fn supports_pc_card16(&self) -> bool {
self.raw & 0x10 == 0x10
}
pub fn supports_card_bus(&self) -> bool {
self.raw & 0x20 == 0x20
}
pub fn supports_zoom_video(&self) -> bool {
self.raw & 0x40 == 0x40
}
pub fn supports_modem_ring_resume(&self) -> bool {
self.raw & 0x80 == 0x80
}
}
impl fmt::Debug for SystemSlotCharacteristics1 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics1>())
.field("raw", &self.raw)
.field("unknown", &self.unknown())
.field("provides5_volts", &self.provides5_volts())
.field("provides33_volts", &self.provides33_volts())
.field("shared", &self.shared())
.field("supports_pc_card16", &self.supports_pc_card16())
.field("supports_card_bus", &self.supports_card_bus())
.field("supports_zoom_video", &self.supports_zoom_video())
.field(
"supports_modem_ring_resume",
&self.supports_modem_ring_resume(),
)
.finish()
}
}
impl Serialize for SystemSlotCharacteristics1 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SystemSlotCharacteristics1", 9)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field("unknown", &self.unknown())?;
state.serialize_field("provides5_volts", &self.provides5_volts())?;
state.serialize_field("provides33_volts", &self.provides33_volts())?;
state.serialize_field("shared", &self.shared())?;
state.serialize_field("supports_pc_card16", &self.supports_pc_card16())?;
state.serialize_field("supports_card_bus", &self.supports_card_bus())?;
state.serialize_field("supports_zoom_video", &self.supports_zoom_video())?;
state.serialize_field(
"supports_modem_ring_resume",
&self.supports_modem_ring_resume(),
)?;
state.end()
}
}
#[derive(PartialEq, Eq)]
pub struct SystemSlotCharacteristics2 {
pub raw: u8,
}
impl Deref for SystemSlotCharacteristics2 {
type Target = u8;
fn deref(&self) -> &Self::Target {
&self.raw
}
}
impl From<u8> for SystemSlotCharacteristics2 {
fn from(raw: u8) -> Self {
SystemSlotCharacteristics2 { raw }
}
}
impl SystemSlotCharacteristics2 {
pub fn supports_power_management_event(&self) -> bool {
self.raw & 0x01 == 0x01
}
pub fn supports_hot_plug_devices(&self) -> bool {
self.raw & 0x02 == 0x02
}
pub fn supports_smbus_signal(&self) -> bool {
self.raw & 0x04 == 0x04
}
pub fn supports_bifurcation(&self) -> bool {
self.raw & 0x08 == 0x08
}
pub fn supports_suprise_removal(&self) -> bool {
self.raw & 0x10 == 0x10
}
pub fn flexbus_slot_cxl10_capable(&self) -> bool {
self.raw & 0x20 == 0x20
}
pub fn flexbus_slot_cxl20_capable(&self) -> bool {
self.raw & 0x40 == 0x40
}
pub fn flexbus_slot_cxl30_capable(&self) -> bool {
self.raw & 0x80 == 0x80
}
}
impl fmt::Debug for SystemSlotCharacteristics2 {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics2>())
.field("raw", &self.raw)
.field(
"supports_power_management_event",
&self.supports_power_management_event(),
)
.field(
"supports_hot_plug_devices",
&self.supports_hot_plug_devices(),
)
.field("supports_smbus_signal", &self.supports_smbus_signal())
.field("supports_bifurcation", &self.supports_bifurcation())
.field("supports_suprise_removal", &self.supports_suprise_removal())
.field(
"flexbus_slot_cxl10_capable",
&self.flexbus_slot_cxl10_capable(),
)
.field(
"flexbus_slot_cxl20_capable",
&self.flexbus_slot_cxl20_capable(),
)
.field(
"flexbus_slot_cxl30_capable",
&self.flexbus_slot_cxl30_capable(),
)
.finish()
}
}
impl Serialize for SystemSlotCharacteristics2 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SystemSlotCharacteristics2", 8)?;
state.serialize_field("raw", &self.raw)?;
state.serialize_field(
"supports_power_management_event",
&self.supports_power_management_event(),
)?;
state.serialize_field(
"supports_hot_plug_devices",
&self.supports_hot_plug_devices(),
)?;
state.serialize_field("supports_smbus_signal", &self.supports_smbus_signal())?;
state.serialize_field("supports_bifurcation", &self.supports_bifurcation())?;
state.serialize_field("supports_suprise_removal", &self.supports_suprise_removal())?;
state.serialize_field(
"flexbus_slot_cxl10_capable",
&self.flexbus_slot_cxl10_capable(),
)?;
state.serialize_field(
"flexbus_slot_cxl20_capable",
&self.flexbus_slot_cxl20_capable(),
)?;
state.serialize_field(
"flexbus_slot_cxl30_capable",
&self.flexbus_slot_cxl30_capable(),
)?;
state.end()
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum SegmentGroupNumber {
SingleSegment,
Number(u16),
NotApplicable,
}
impl From<u16> for SegmentGroupNumber {
fn from(raw: u16) -> Self {
match raw {
0x00 => SegmentGroupNumber::SingleSegment,
0xFF => SegmentGroupNumber::NotApplicable,
_ => SegmentGroupNumber::Number(raw),
}
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum BusNumber {
Number(u8),
NotApplicable,
}
impl From<u8> for BusNumber {
fn from(raw: u8) -> Self {
match raw {
0xFF => BusNumber::NotApplicable,
_ => BusNumber::Number(raw),
}
}
}
#[derive(Serialize, Debug, PartialEq, Eq)]
pub enum DeviceFunctionNumber {
Number {
device: u8,
function: u8,
},
NotApplicable,
}
impl From<u8> for DeviceFunctionNumber {
fn from(raw: u8) -> Self {
match raw {
0xFF => DeviceFunctionNumber::NotApplicable,
_ => DeviceFunctionNumber::Number {
device: (raw & 0b11111000) >> 3,
function: raw & 0b00000111,
},
}
}
}
pub struct SlotPeerGroup<'a> {
system_slot: &'a SMBiosSystemSlot<'a>,
entry_offset: usize,
}
impl<'a> SlotPeerGroup<'a> {
const SIZE: usize = 5;
const SEGMENT_GROUP_NUMBER_OFFSET: usize = 0;
const BUS_NUMBER_OFFSET: usize = 2;
const DEVICE_FUNCTION_NUMBER_OFFSET: usize = 3;
const DATA_BUS_WIDTH_OFFSET: usize = 4;
fn new(system_slot: &'a SMBiosSystemSlot<'a>, entry_offset: usize) -> Self {
Self {
system_slot,
entry_offset,
}
}
pub fn segment_group_number(&self) -> Option<u16> {
self.system_slot
.parts()
.get_field_word(self.entry_offset + Self::SEGMENT_GROUP_NUMBER_OFFSET)
}
pub fn bus_number(&self) -> Option<u8> {
self.system_slot
.parts()
.get_field_byte(self.entry_offset + Self::BUS_NUMBER_OFFSET)
}
pub fn device_function_number(&self) -> Option<u8> {
self.system_slot
.parts()
.get_field_byte(self.entry_offset + Self::DEVICE_FUNCTION_NUMBER_OFFSET)
}
pub fn data_bus_width(&self) -> Option<u8> {
self.system_slot
.parts()
.get_field_byte(self.entry_offset + Self::DATA_BUS_WIDTH_OFFSET)
}
}
impl fmt::Debug for SlotPeerGroup<'_> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_struct(std::any::type_name::<SlotPeerGroup<'_>>())
.field("segment_group_number", &self.segment_group_number())
.field("bus_number", &self.bus_number())
.field("device_function_number", &self.device_function_number())
.field("data_bus_width", &self.data_bus_width())
.finish()
}
}
impl Serialize for SlotPeerGroup<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("SlotPeerGroup", 4)?;
state.serialize_field("segment_group_number", &self.segment_group_number())?;
state.serialize_field("bus_number", &self.bus_number())?;
state.serialize_field("device_function_number", &self.device_function_number())?;
state.serialize_field("data_bus_width", &self.data_bus_width())?;
state.end()
}
}
pub struct SlotPeerGroupIterator<'a> {
data: &'a SMBiosSystemSlot<'a>,
current_index: usize,
current_entry: usize,
number_of_entries: usize,
}
impl<'a> SlotPeerGroupIterator<'a> {
const PEER_GROUPS_OFFSET: usize = 0x13;
fn new(data: &'a SMBiosSystemSlot<'a>) -> Self {
SlotPeerGroupIterator {
data: data,
current_index: Self::PEER_GROUPS_OFFSET,
current_entry: 0,
number_of_entries: data.peer_group_count().unwrap_or(0),
}
}
fn reset(&mut self) {
self.current_index = Self::PEER_GROUPS_OFFSET;
self.current_entry = 0;
}
}
impl<'a> IntoIterator for &'a SlotPeerGroupIterator<'a> {
type Item = SlotPeerGroup<'a>;
type IntoIter = SlotPeerGroupIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
SlotPeerGroupIterator {
data: self.data,
current_index: SlotPeerGroupIterator::PEER_GROUPS_OFFSET,
current_entry: 0,
number_of_entries: self.data.peer_group_count().unwrap_or(0),
}
}
}
impl<'a> Iterator for SlotPeerGroupIterator<'a> {
type Item = SlotPeerGroup<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.current_entry == self.number_of_entries {
self.reset();
return None;
}
let next_index = self.current_index + SlotPeerGroup::SIZE;
match self
.data
.parts()
.get_field_data(self.current_index, next_index)
{
Some(_) => {
let result = SlotPeerGroup::new(self.data, self.current_index);
self.current_index = next_index;
self.current_entry += 1;
Some(result)
}
None => {
self.reset();
None
}
}
}
}
impl<'a> fmt::Debug for SlotPeerGroupIterator<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt.debug_list().entries(self.into_iter()).finish()
}
}
impl<'a> Serialize for SlotPeerGroupIterator<'a> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let groups: Vec<SlotPeerGroup<'_>> = self.into_iter().collect();
let mut seq = serializer.serialize_seq(Some(groups.len()))?;
for e in groups {
seq.serialize_element(&e)?;
}
seq.end()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unit_test() {
let struct_type9 = vec![
0x09, 0x11, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x05, 0x07, 0x0C, 0x01, 0x00,
0x00, 0x00, 0x08, 0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
];
let parts = UndefinedStruct::new(&struct_type9);
let test_struct = SMBiosSystemSlot::new(&parts);
assert_eq!(
test_struct.slot_designation().to_string(),
"J6B2".to_string()
);
assert_eq!(
*test_struct.system_slot_type().unwrap(),
SystemSlotType::PciExpress(
PciExpressGeneration::PCIExpressGen1,
PciExpressSlotWidth::UndefinedSlotWidth,
)
);
assert_eq!(*test_struct.slot_data_bus_width().unwrap(), SlotWidth::X16);
let slot_id = test_struct.slot_id().unwrap();
assert_eq!(slot_id.byte_0(), 5);
assert_eq!(slot_id.byte_1(), 7);
assert!(test_struct.data_bus_width().is_none());
let struct_type9 = vec![
0x09, 0x1C, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x00, 0x00, 0x0C, 0x01, 0x00,
0x00, 0x00, 0x08, 0x99, 0x01, 0x23, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0xAB, 0x09,
0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
];
let parts = UndefinedStruct::new(&struct_type9);
let test_struct = SMBiosSystemSlot::new(&parts);
assert_eq!(test_struct.data_bus_width(), Some(0x99));
assert_eq!(test_struct.peer_group_count(), Some(0x01));
let mut iterator = test_struct.peer_group_iterator().into_iter();
let first = iterator.next().unwrap();
assert_eq!(first.segment_group_number(), Some(0x0123));
assert_eq!(first.bus_number(), Some(0x04));
assert_eq!(first.device_function_number(), Some(0x05));
assert_eq!(first.data_bus_width(), Some(0x06));
assert_eq!(test_struct.slot_information(), Some(0x07));
assert_eq!(*test_struct.slot_physical_width().unwrap(), SlotWidth::X1);
assert_eq!(test_struct.slot_pitch(), Some(0x09AB));
println!("{:?}", test_struct);
}
}