1use crate::core::{strings::*, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeSeq, ser::SerializeStruct, Serialize, Serializer};
4use std::{convert::TryInto, fmt, ops::Deref};
5
6pub struct SMBiosSystemSlot<'a> {
15 parts: &'a UndefinedStruct,
16}
17
18impl<'a> SMBiosStruct<'a> for SMBiosSystemSlot<'a> {
19 const STRUCT_TYPE: u8 = 9u8;
20
21 fn new(parts: &'a UndefinedStruct) -> Self {
22 Self { parts }
23 }
24
25 fn parts(&self) -> &'a UndefinedStruct {
26 self.parts
27 }
28}
29
30impl<'a> SMBiosSystemSlot<'a> {
31 pub fn slot_designation(&self) -> SMBiosString {
33 self.parts.get_field_string(0x04)
34 }
35
36 pub fn system_slot_type(&self) -> Option<SystemSlotTypeData> {
38 self.parts
39 .get_field_byte(0x05)
40 .map(|raw| SystemSlotTypeData::from(raw))
41 }
42
43 pub fn slot_data_bus_width(&self) -> Option<SlotWidthData> {
45 self.parts
46 .get_field_byte(0x06)
47 .map(|raw| SlotWidthData::from(raw))
48 }
49
50 pub fn current_usage(&self) -> Option<SlotCurrentUsageData> {
52 self.parts
53 .get_field_byte(0x07)
54 .map(|raw| SlotCurrentUsageData::from(raw))
55 }
56
57 pub fn slot_length(&self) -> Option<SlotLengthData> {
59 self.parts
60 .get_field_byte(0x08)
61 .map(|raw| SlotLengthData::from(raw))
62 }
63
64 pub fn slot_id(&self) -> Option<SystemSlotId> {
66 self.parts
67 .get_field_data(0x09, 0x0B)
68 .map(|id| SystemSlotId(id.try_into().unwrap()))
69 }
70
71 pub fn slot_characteristics_1(&self) -> Option<SystemSlotCharacteristics1> {
73 self.parts
74 .get_field_byte(0x0B)
75 .map(|raw| SystemSlotCharacteristics1::from(raw))
76 }
77
78 pub fn slot_characteristics_2(&self) -> Option<SystemSlotCharacteristics2> {
80 self.parts
81 .get_field_byte(0x0C)
82 .map(|raw| SystemSlotCharacteristics2::from(raw))
83 }
84
85 pub fn segment_group_number(&self) -> Option<SegmentGroupNumber> {
87 self.parts
88 .get_field_word(0x0D)
89 .map(|raw| SegmentGroupNumber::from(raw))
90 }
91
92 pub fn bus_number(&self) -> Option<BusNumber> {
94 self.parts
95 .get_field_byte(0x0F)
96 .map(|raw| BusNumber::from(raw))
97 }
98
99 pub fn device_function_number(&self) -> Option<DeviceFunctionNumber> {
101 self.parts
102 .get_field_byte(0x10)
103 .map(|raw| DeviceFunctionNumber::from(raw))
104 }
105
106 pub fn data_bus_width(&self) -> Option<u8> {
108 self.parts.get_field_byte(0x11)
109 }
110
111 pub fn peer_group_count(&self) -> Option<usize> {
113 self.parts
114 .get_field_byte(0x12)
115 .and_then(|count| Some(count as usize))
116 }
117
118 fn peer_group_size(&self) -> Option<usize> {
120 self.peer_group_count()
121 .and_then(|count| Some(count as usize * SlotPeerGroup::SIZE))
122 }
123
124 pub fn peer_group_iterator(&'a self) -> SlotPeerGroupIterator<'a> {
126 SlotPeerGroupIterator::new(self)
127 }
128
129 pub fn slot_information(&self) -> Option<u8> {
131 self.peer_group_size()
132 .and_then(|size| self.parts.get_field_byte(size + 0x13))
133 }
134
135 pub fn slot_physical_width(&self) -> Option<SlotWidthData> {
142 self.peer_group_size().and_then(|size| {
143 self.parts
144 .get_field_byte(size + 0x14)
145 .map(|raw| SlotWidthData::from(raw))
146 })
147 }
148
149 pub fn slot_pitch(&self) -> Option<u16> {
163 self.peer_group_size()
164 .and_then(|size| self.parts.get_field_word(size + 0x15))
165 }
166
167 pub fn slot_height(&self) -> Option<SlotHeightData> {
173 self.peer_group_size().and_then(|size| {
174 self.parts
175 .get_field_byte(size + 0x17)
176 .map(|raw| SlotHeightData::from(raw))
177 })
178 }
179}
180
181impl fmt::Debug for SMBiosSystemSlot<'_> {
182 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
183 fmt.debug_struct(std::any::type_name::<SMBiosSystemSlot<'_>>())
184 .field("header", &self.parts.header)
185 .field("slot_designation", &self.slot_designation())
186 .field("system_slot_type", &self.system_slot_type())
187 .field("slot_data_bus_width", &self.slot_data_bus_width())
188 .field("current_usage", &self.current_usage())
189 .field("slot_length", &self.slot_length())
190 .field("slot_id", &self.slot_id())
191 .field("slot_characteristics_1", &self.slot_characteristics_1())
192 .field("slot_characteristics_2", &self.slot_characteristics_2())
193 .field("segment_group_number", &self.segment_group_number())
194 .field("bus_number", &self.bus_number())
195 .field("device_function_number", &self.device_function_number())
196 .field("data_bus_width", &self.data_bus_width())
197 .field("peer_group_count", &self.peer_group_count())
198 .field("peer_group_iterator", &self.peer_group_iterator())
199 .field("slot_information", &self.slot_information())
200 .field("slot_physical_width", &self.slot_physical_width())
201 .field("slot_pitch", &self.slot_pitch())
202 .finish()
203 }
204}
205
206impl Serialize for SMBiosSystemSlot<'_> {
207 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
208 where
209 S: Serializer,
210 {
211 let mut state = serializer.serialize_struct("SMBiosSystemSlot", 18)?;
212 state.serialize_field("header", &self.parts.header)?;
213 state.serialize_field("slot_designation", &self.slot_designation())?;
214 state.serialize_field("system_slot_type", &self.system_slot_type())?;
215 state.serialize_field("slot_data_bus_width", &self.slot_data_bus_width())?;
216 state.serialize_field("current_usage", &self.current_usage())?;
217 state.serialize_field("slot_length", &self.slot_length())?;
218 state.serialize_field("slot_id", &self.slot_id())?;
219 state.serialize_field("slot_characteristics_1", &self.slot_characteristics_1())?;
220 state.serialize_field("slot_characteristics_2", &self.slot_characteristics_2())?;
221 state.serialize_field("segment_group_number", &self.segment_group_number())?;
222 state.serialize_field("bus_number", &self.bus_number())?;
223 state.serialize_field("device_function_number", &self.device_function_number())?;
224 state.serialize_field("data_bus_width", &self.data_bus_width())?;
225 state.serialize_field("peer_group_count", &self.peer_group_count())?;
226 state.serialize_field("peer_group_iterator", &self.peer_group_iterator())?;
227 state.serialize_field("slot_information", &self.slot_information())?;
228 state.serialize_field("slot_physical_width", &self.slot_physical_width())?;
229 state.serialize_field("slot_pitch", &self.slot_pitch())?;
230 state.end()
231 }
232}
233
234#[derive(Serialize, Debug, PartialEq, Eq, Clone, Copy)]
246pub struct SystemSlotId(pub [u8; 2]);
247
248impl Deref for SystemSlotId {
249 type Target = [u8; 2];
250
251 fn deref(&self) -> &Self::Target {
252 &self.0
253 }
254}
255
256impl SystemSlotId {
257 pub fn byte_0(&self) -> u8 {
259 self.0[0]
260 }
261
262 pub fn byte_1(&self) -> u8 {
264 self.0[1]
265 }
266}
267
268pub struct SystemSlotTypeData {
270 pub raw: u8,
277 pub value: SystemSlotType,
279}
280
281impl Deref for SystemSlotTypeData {
282 type Target = SystemSlotType;
283
284 fn deref(&self) -> &Self::Target {
285 &self.value
286 }
287}
288
289impl From<u8> for SystemSlotTypeData {
290 fn from(raw: u8) -> Self {
292 use M2SlotType::*;
293 use MXMSlotType::*;
294 use PciExpressGeneration::*;
295 use PciExpressSlotWidth::*;
296 use SystemSlotType::*;
297 SystemSlotTypeData {
298 value: match raw {
299 0x01 => Other,
300 0x02 => Unknown,
301 0x03 => Isa,
302 0x04 => Mca,
303 0x05 => Eisa,
304 0x06 => Pci,
305 0x07 => Pcmcia,
306 0x08 => VlVesa,
307 0x09 => Proprietary,
308 0x0A => ProcessorCardSlot,
309 0x0B => ProprietaryMemoryCardSlot,
310 0x0C => IORiserCardSlot,
311 0x0D => NuBus,
312 0x0E => Pci66MhzCapable,
313 0x0F => Agp(AgpSlotWidth::X1),
314 0x10 => Agp(AgpSlotWidth::X2),
315 0x11 => Agp(AgpSlotWidth::X4),
316 0x12 => PciX,
317 0x13 => Agp(AgpSlotWidth::X8),
318 0x14 => M2(M2Socket1DP),
319 0x15 => M2(M2Socket1SD),
320 0x16 => M2(M2Socket2),
321 0x17 => M2(M2Socket3),
322 0x18 => Mxm(MxmTypeI),
323 0x19 => Mxm(MxmTypeII),
324 0x1A => Mxm(MxmTypeIIIStandard),
325 0x1B => Mxm(MxmTypeIIIHE),
326 0x1C => Mxm(MxmTypeIV),
327 0x1D => Mxm(Mxm3TypeA),
328 0x1E => Mxm(Mxm3TypeB),
329 0x1F => PciExpress(PCIExpressGen2, Sff8639),
330 0x20 => PciExpress(PCIExpressGen3, Sff8639),
331 0x21 => PciExpress(Undefined, PciExpressMini52WithKeepouts),
332 0x22 => PciExpress(Undefined, PciExpressMini52WithoutKeepouts),
333 0x23 => PciExpress(Undefined, PciExpressMini76),
334 0x24 => PciExpress(PCIExpressGen4, Sff8639),
335 0x25 => PciExpress(PCIExpressGen5, Sff8639),
336 0x26 => OcpNic30SmallFormFactor,
337 0x27 => OcpNic30LargeFormFactor,
338 0x28 => OcpNicPriorTo30,
339 0x30 => CxlFlexbus1,
340 0xA0 => PC98C20,
341 0xA1 => PC98C24,
342 0xA2 => PC98E,
343 0xA3 => PC98LocalBus,
344 0xA4 => PC98Card,
345 0xA5 => PciExpress(PCIExpressGen1, UndefinedSlotWidth),
346 0xA6 => PciExpress(PCIExpressGen1, X1),
347 0xA7 => PciExpress(PCIExpressGen1, X2),
348 0xA8 => PciExpress(PCIExpressGen1, X4),
349 0xA9 => PciExpress(PCIExpressGen1, X8),
350 0xAA => PciExpress(PCIExpressGen1, X16),
351 0xAB => PciExpress(PCIExpressGen2, UndefinedSlotWidth),
352 0xAC => PciExpress(PCIExpressGen2, X1),
353 0xAD => PciExpress(PCIExpressGen2, X2),
354 0xAE => PciExpress(PCIExpressGen2, X4),
355 0xAF => PciExpress(PCIExpressGen2, X8),
356 0xB0 => PciExpress(PCIExpressGen2, X16),
357 0xB1 => PciExpress(PCIExpressGen3, UndefinedSlotWidth),
358 0xB2 => PciExpress(PCIExpressGen3, X1),
359 0xB3 => PciExpress(PCIExpressGen3, X2),
360 0xB4 => PciExpress(PCIExpressGen3, X4),
361 0xB5 => PciExpress(PCIExpressGen3, X8),
362 0xB6 => PciExpress(PCIExpressGen3, X16),
363 0xB8 => PciExpress(PCIExpressGen4, UndefinedSlotWidth),
364 0xB9 => PciExpress(PCIExpressGen4, X1),
365 0xBA => PciExpress(PCIExpressGen4, X2),
366 0xBB => PciExpress(PCIExpressGen4, X4),
367 0xBC => PciExpress(PCIExpressGen4, X8),
368 0xBD => PciExpress(PCIExpressGen4, X16),
369 0xBE => PciExpress(PCIExpressGen5, UndefinedSlotWidth),
370 0xBF => PciExpress(PCIExpressGen5, X1),
371 0xC0 => PciExpress(PCIExpressGen5, X2),
372 0xC1 => PciExpress(PCIExpressGen5, X4),
373 0xC2 => PciExpress(PCIExpressGen5, X8),
374 0xC3 => PciExpress(PCIExpressGen5, X16),
375 0xC4 => PciExpress(PCIExpressGen6, UndefinedSlotWidth),
376 0xC5 => EnterpriseAndDataCenter1UE1,
377 0xC6 => EnterpriseAndDataCenter3InE3,
378 _ => None,
379 },
380 raw,
381 }
382 }
383}
384
385impl fmt::Debug for SystemSlotTypeData {
386 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
387 fmt.debug_struct(std::any::type_name::<SystemSlotTypeData>())
388 .field("raw", &self.raw)
389 .field("value", &self.value)
390 .finish()
391 }
392}
393
394impl Serialize for SystemSlotTypeData {
395 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
396 where
397 S: Serializer,
398 {
399 let mut state = serializer.serialize_struct("SystemSlotTypeData", 2)?;
400 state.serialize_field("raw", &self.raw)?;
401 state.serialize_field("value", &self.value)?;
402 state.end()
403 }
404}
405
406impl fmt::Display for SystemSlotTypeData {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 match &self.value {
409 SystemSlotType::None => write!(f, "{}", &self.raw),
410 _ => write!(f, "{:?}", &self.value),
411 }
412 }
413}
414
415#[derive(Serialize, Debug, PartialEq, Eq)]
417pub enum SystemSlotType {
418 Other,
420 Unknown,
422 Isa,
424 Mca,
426 Eisa,
428 Pci,
430 Pcmcia,
432 VlVesa,
434 Proprietary,
436 ProcessorCardSlot,
438 ProprietaryMemoryCardSlot,
440 IORiserCardSlot,
442 NuBus,
444 Pci66MhzCapable,
446 Agp(AgpSlotWidth),
448 Mxm(MXMSlotType),
450 PciX,
452 M2(M2SlotType),
454 OcpNic30SmallFormFactor,
456 OcpNic30LargeFormFactor,
458 OcpNicPriorTo30,
460 CxlFlexbus1,
462 PC98C20,
464 PC98C24,
466 PC98E,
468 PC98LocalBus,
470 PC98Card,
472 PciExpress(PciExpressGeneration, PciExpressSlotWidth),
474 EnterpriseAndDataCenter1UE1,
476 EnterpriseAndDataCenter3InE3,
478 None,
480}
481
482#[derive(Serialize, Debug, PartialEq, Eq)]
484pub enum PciExpressGeneration {
485 PCIExpressGen1,
487 PCIExpressGen2,
489 PCIExpressGen3,
491 PCIExpressGen4,
493 PCIExpressGen5,
495 PCIExpressGen6,
497 Undefined,
499}
500
501#[derive(Serialize, Debug, PartialEq, Eq)]
503pub enum PciExpressSlotWidth {
504 UndefinedSlotWidth,
506 X1,
508 X2,
510 X4,
512 X8,
514 X16,
516 Sff8639,
518 PciExpressMini52WithKeepouts,
520 PciExpressMini52WithoutKeepouts,
522 PciExpressMini76,
524}
525
526#[derive(Serialize, Debug, PartialEq, Eq)]
528pub enum AgpSlotWidth {
529 X1,
531 X2,
533 X4,
535 X8,
537}
538
539#[derive(Serialize, Debug, PartialEq, Eq)]
541pub enum MXMSlotType {
542 MxmTypeI,
544 MxmTypeII,
546 MxmTypeIIIStandard,
548 MxmTypeIIIHE,
550 MxmTypeIV,
552 Mxm3TypeA,
554 Mxm3TypeB,
556}
557
558#[derive(Serialize, Debug, PartialEq, Eq)]
560pub enum M2SlotType {
561 M2Socket1DP,
563 M2Socket1SD,
565 M2Socket2,
567 M2Socket3,
569}
570
571pub struct SlotWidthData {
573 pub raw: u8,
580 pub value: SlotWidth,
582}
583
584impl Deref for SlotWidthData {
585 type Target = SlotWidth;
586
587 fn deref(&self) -> &Self::Target {
588 &self.value
589 }
590}
591
592impl From<u8> for SlotWidthData {
593 fn from(raw: u8) -> Self {
594 SlotWidthData {
595 value: match raw {
596 0x01 => SlotWidth::Other,
597 0x02 => SlotWidth::Unknown,
598 0x03 => SlotWidth::Bit8,
599 0x04 => SlotWidth::Bit16,
600 0x05 => SlotWidth::Bit32,
601 0x06 => SlotWidth::Bit64,
602 0x07 => SlotWidth::Bit128,
603 0x08 => SlotWidth::X1,
604 0x09 => SlotWidth::X2,
605 0x0A => SlotWidth::X4,
606 0x0B => SlotWidth::X8,
607 0x0C => SlotWidth::X12,
608 0x0D => SlotWidth::X16,
609 0x0E => SlotWidth::X32,
610 _ => SlotWidth::None,
611 },
612 raw,
613 }
614 }
615}
616
617impl fmt::Debug for SlotWidthData {
618 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
619 fmt.debug_struct(std::any::type_name::<SlotWidthData>())
620 .field("raw", &self.raw)
621 .field("value", &self.value)
622 .finish()
623 }
624}
625
626impl Serialize for SlotWidthData {
627 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
628 where
629 S: Serializer,
630 {
631 let mut state = serializer.serialize_struct("SlotWidthData", 2)?;
632 state.serialize_field("raw", &self.raw)?;
633 state.serialize_field("value", &self.value)?;
634 state.end()
635 }
636}
637
638#[derive(Serialize, Debug, PartialEq, Eq)]
640pub enum SlotWidth {
641 Other,
643 Unknown,
645 Bit8,
647 Bit16,
649 Bit32,
651 Bit64,
653 Bit128,
655 X1,
657 X2,
659 X4,
661 X8,
663 X12,
665 X16,
667 X32,
669 None,
671}
672
673pub struct SlotHeightData {
675 pub raw: u8,
682 pub value: SlotHeight,
684}
685
686impl Deref for SlotHeightData {
687 type Target = SlotHeight;
688
689 fn deref(&self) -> &Self::Target {
690 &self.value
691 }
692}
693
694impl From<u8> for SlotHeightData {
695 fn from(raw: u8) -> Self {
696 SlotHeightData {
697 value: match raw {
698 0x00 => SlotHeight::NotApplicable,
699 0x01 => SlotHeight::Other,
700 0x02 => SlotHeight::Unknown,
701 0x03 => SlotHeight::FullHeight,
702 0x04 => SlotHeight::LowProfile,
703 _ => SlotHeight::None,
704 },
705 raw,
706 }
707 }
708}
709
710impl fmt::Debug for SlotHeightData {
711 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
712 fmt.debug_struct(std::any::type_name::<SlotHeightData>())
713 .field("raw", &self.raw)
714 .field("value", &self.value)
715 .finish()
716 }
717}
718
719impl Serialize for SlotHeightData {
720 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
721 where
722 S: Serializer,
723 {
724 let mut state = serializer.serialize_struct("SlotHeightData", 2)?;
725 state.serialize_field("raw", &self.raw)?;
726 state.serialize_field("value", &self.value)?;
727 state.end()
728 }
729}
730
731#[derive(Serialize, Debug, PartialEq, Eq)]
733pub enum SlotHeight {
734 NotApplicable,
736 Other,
738 Unknown,
740 FullHeight,
742 LowProfile,
744 None,
746}
747
748pub struct SlotCurrentUsageData {
750 pub raw: u8,
757 pub value: SlotCurrentUsage,
759}
760
761impl Deref for SlotCurrentUsageData {
762 type Target = SlotCurrentUsage;
763
764 fn deref(&self) -> &Self::Target {
765 &self.value
766 }
767}
768
769impl From<u8> for SlotCurrentUsageData {
770 fn from(raw: u8) -> Self {
771 SlotCurrentUsageData {
772 value: match raw {
773 0x01 => SlotCurrentUsage::Other,
774 0x02 => SlotCurrentUsage::Unknown,
775 0x03 => SlotCurrentUsage::Available,
776 0x04 => SlotCurrentUsage::InUse,
777 0x05 => SlotCurrentUsage::Unavailable,
778 _ => SlotCurrentUsage::None,
779 },
780 raw,
781 }
782 }
783}
784
785impl fmt::Debug for SlotCurrentUsageData {
786 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
787 fmt.debug_struct(std::any::type_name::<SlotCurrentUsageData>())
788 .field("raw", &self.raw)
789 .field("value", &self.value)
790 .finish()
791 }
792}
793
794impl Serialize for SlotCurrentUsageData {
795 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
796 where
797 S: Serializer,
798 {
799 let mut state = serializer.serialize_struct("SlotCurrentUsageData", 2)?;
800 state.serialize_field("raw", &self.raw)?;
801 state.serialize_field("value", &self.value)?;
802 state.end()
803 }
804}
805
806#[derive(Serialize, Debug, PartialEq, Eq)]
808pub enum SlotCurrentUsage {
809 Other,
811 Unknown,
813 Available,
815 InUse,
817 Unavailable,
819 None,
821}
822
823pub struct SlotLengthData {
825 pub raw: u8,
832 pub value: SlotLength,
834}
835
836impl Deref for SlotLengthData {
837 type Target = SlotLength;
838
839 fn deref(&self) -> &Self::Target {
840 &self.value
841 }
842}
843
844impl From<u8> for SlotLengthData {
845 fn from(raw: u8) -> Self {
846 use SlotLength::*;
847 SlotLengthData {
848 value: match raw {
849 0x01 => Other,
850 0x02 => Unknown,
851 0x03 => ShortLength,
852 0x04 => LongLength,
853 0x05 => DriveFormFactor25,
854 0x06 => DriveFormFactor35,
855 _ => None,
856 },
857 raw,
858 }
859 }
860}
861
862impl fmt::Debug for SlotLengthData {
863 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
864 fmt.debug_struct(std::any::type_name::<SlotLengthData>())
865 .field("raw", &self.raw)
866 .field("value", &self.value)
867 .finish()
868 }
869}
870
871impl Serialize for SlotLengthData {
872 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
873 where
874 S: Serializer,
875 {
876 let mut state = serializer.serialize_struct("SlotLengthData", 2)?;
877 state.serialize_field("raw", &self.raw)?;
878 state.serialize_field("value", &self.value)?;
879 state.end()
880 }
881}
882
883#[derive(Serialize, Debug, PartialEq, Eq)]
885pub enum SlotLength {
886 Other,
888 Unknown,
890 ShortLength,
892 LongLength,
894 DriveFormFactor25,
896 DriveFormFactor35,
898 None,
900}
901
902#[derive(PartialEq, Eq)]
904pub struct SystemSlotCharacteristics1 {
905 pub raw: u8,
909}
910
911impl Deref for SystemSlotCharacteristics1 {
912 type Target = u8;
913
914 fn deref(&self) -> &Self::Target {
915 &self.raw
916 }
917}
918
919impl From<u8> for SystemSlotCharacteristics1 {
920 fn from(raw: u8) -> Self {
921 SystemSlotCharacteristics1 { raw }
922 }
923}
924
925impl SystemSlotCharacteristics1 {
926 pub fn unknown(&self) -> bool {
928 self.raw & 0x01 == 0x01
929 }
930
931 pub fn provides5_volts(&self) -> bool {
933 self.raw & 0x02 == 0x02
934 }
935
936 pub fn provides33_volts(&self) -> bool {
938 self.raw & 0x04 == 0x04
939 }
940
941 pub fn shared(&self) -> bool {
943 self.raw & 0x08 == 0x08
944 }
945
946 pub fn supports_pc_card16(&self) -> bool {
948 self.raw & 0x10 == 0x10
949 }
950
951 pub fn supports_card_bus(&self) -> bool {
953 self.raw & 0x20 == 0x20
954 }
955
956 pub fn supports_zoom_video(&self) -> bool {
958 self.raw & 0x40 == 0x40
959 }
960
961 pub fn supports_modem_ring_resume(&self) -> bool {
963 self.raw & 0x80 == 0x80
964 }
965}
966
967impl fmt::Debug for SystemSlotCharacteristics1 {
968 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
969 fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics1>())
970 .field("raw", &self.raw)
971 .field("unknown", &self.unknown())
972 .field("provides5_volts", &self.provides5_volts())
973 .field("provides33_volts", &self.provides33_volts())
974 .field("shared", &self.shared())
975 .field("supports_pc_card16", &self.supports_pc_card16())
976 .field("supports_card_bus", &self.supports_card_bus())
977 .field("supports_zoom_video", &self.supports_zoom_video())
978 .field(
979 "supports_modem_ring_resume",
980 &self.supports_modem_ring_resume(),
981 )
982 .finish()
983 }
984}
985
986impl Serialize for SystemSlotCharacteristics1 {
987 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
988 where
989 S: Serializer,
990 {
991 let mut state = serializer.serialize_struct("SystemSlotCharacteristics1", 9)?;
992 state.serialize_field("raw", &self.raw)?;
993 state.serialize_field("unknown", &self.unknown())?;
994 state.serialize_field("provides5_volts", &self.provides5_volts())?;
995 state.serialize_field("provides33_volts", &self.provides33_volts())?;
996 state.serialize_field("shared", &self.shared())?;
997 state.serialize_field("supports_pc_card16", &self.supports_pc_card16())?;
998 state.serialize_field("supports_card_bus", &self.supports_card_bus())?;
999 state.serialize_field("supports_zoom_video", &self.supports_zoom_video())?;
1000 state.serialize_field(
1001 "supports_modem_ring_resume",
1002 &self.supports_modem_ring_resume(),
1003 )?;
1004 state.end()
1005 }
1006}
1007
1008#[derive(PartialEq, Eq)]
1010pub struct SystemSlotCharacteristics2 {
1011 pub raw: u8,
1018}
1019
1020impl Deref for SystemSlotCharacteristics2 {
1021 type Target = u8;
1022
1023 fn deref(&self) -> &Self::Target {
1024 &self.raw
1025 }
1026}
1027
1028impl From<u8> for SystemSlotCharacteristics2 {
1029 fn from(raw: u8) -> Self {
1030 SystemSlotCharacteristics2 { raw }
1031 }
1032}
1033
1034impl SystemSlotCharacteristics2 {
1035 pub fn supports_power_management_event(&self) -> bool {
1037 self.raw & 0x01 == 0x01
1038 }
1039
1040 pub fn supports_hot_plug_devices(&self) -> bool {
1042 self.raw & 0x02 == 0x02
1043 }
1044
1045 pub fn supports_smbus_signal(&self) -> bool {
1047 self.raw & 0x04 == 0x04
1048 }
1049
1050 pub fn supports_bifurcation(&self) -> bool {
1056 self.raw & 0x08 == 0x08
1057 }
1058
1059 pub fn supports_suprise_removal(&self) -> bool {
1063 self.raw & 0x10 == 0x10
1064 }
1065
1066 pub fn flexbus_slot_cxl10_capable(&self) -> bool {
1068 self.raw & 0x20 == 0x20
1069 }
1070
1071 pub fn flexbus_slot_cxl20_capable(&self) -> bool {
1073 self.raw & 0x40 == 0x40
1074 }
1075
1076 pub fn flexbus_slot_cxl30_capable(&self) -> bool {
1078 self.raw & 0x80 == 0x80
1079 }
1080}
1081
1082impl fmt::Debug for SystemSlotCharacteristics2 {
1083 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1084 fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics2>())
1085 .field("raw", &self.raw)
1086 .field(
1087 "supports_power_management_event",
1088 &self.supports_power_management_event(),
1089 )
1090 .field(
1091 "supports_hot_plug_devices",
1092 &self.supports_hot_plug_devices(),
1093 )
1094 .field("supports_smbus_signal", &self.supports_smbus_signal())
1095 .field("supports_bifurcation", &self.supports_bifurcation())
1096 .field("supports_suprise_removal", &self.supports_suprise_removal())
1097 .field(
1098 "flexbus_slot_cxl10_capable",
1099 &self.flexbus_slot_cxl10_capable(),
1100 )
1101 .field(
1102 "flexbus_slot_cxl20_capable",
1103 &self.flexbus_slot_cxl20_capable(),
1104 )
1105 .field(
1106 "flexbus_slot_cxl30_capable",
1107 &self.flexbus_slot_cxl30_capable(),
1108 )
1109 .finish()
1110 }
1111}
1112
1113impl Serialize for SystemSlotCharacteristics2 {
1114 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1115 where
1116 S: Serializer,
1117 {
1118 let mut state = serializer.serialize_struct("SystemSlotCharacteristics2", 8)?;
1119 state.serialize_field("raw", &self.raw)?;
1120 state.serialize_field(
1121 "supports_power_management_event",
1122 &self.supports_power_management_event(),
1123 )?;
1124 state.serialize_field(
1125 "supports_hot_plug_devices",
1126 &self.supports_hot_plug_devices(),
1127 )?;
1128 state.serialize_field("supports_smbus_signal", &self.supports_smbus_signal())?;
1129 state.serialize_field("supports_bifurcation", &self.supports_bifurcation())?;
1130 state.serialize_field("supports_suprise_removal", &self.supports_suprise_removal())?;
1131 state.serialize_field(
1132 "flexbus_slot_cxl10_capable",
1133 &self.flexbus_slot_cxl10_capable(),
1134 )?;
1135 state.serialize_field(
1136 "flexbus_slot_cxl20_capable",
1137 &self.flexbus_slot_cxl20_capable(),
1138 )?;
1139 state.serialize_field(
1140 "flexbus_slot_cxl30_capable",
1141 &self.flexbus_slot_cxl30_capable(),
1142 )?;
1143 state.end()
1144 }
1145}
1146
1147#[derive(Serialize, Debug, PartialEq, Eq)]
1149pub enum SegmentGroupNumber {
1150 SingleSegment,
1152 Number(u16),
1154 NotApplicable,
1157}
1158
1159impl From<u16> for SegmentGroupNumber {
1160 fn from(raw: u16) -> Self {
1161 match raw {
1162 0x00 => SegmentGroupNumber::SingleSegment,
1163 0xFF => SegmentGroupNumber::NotApplicable,
1164 _ => SegmentGroupNumber::Number(raw),
1165 }
1166 }
1167}
1168
1169#[derive(Serialize, Debug, PartialEq, Eq)]
1171pub enum BusNumber {
1172 Number(u8),
1174 NotApplicable,
1177}
1178
1179impl From<u8> for BusNumber {
1180 fn from(raw: u8) -> Self {
1181 match raw {
1182 0xFF => BusNumber::NotApplicable,
1183 _ => BusNumber::Number(raw),
1184 }
1185 }
1186}
1187
1188#[derive(Serialize, Debug, PartialEq, Eq)]
1190pub enum DeviceFunctionNumber {
1191 Number {
1193 device: u8,
1195 function: u8,
1197 },
1198 NotApplicable,
1201}
1202
1203impl From<u8> for DeviceFunctionNumber {
1204 fn from(raw: u8) -> Self {
1205 match raw {
1206 0xFF => DeviceFunctionNumber::NotApplicable,
1207 _ => DeviceFunctionNumber::Number {
1208 device: (raw & 0b11111000) >> 3,
1209 function: raw & 0b00000111,
1210 },
1211 }
1212 }
1213}
1214
1215pub struct SlotPeerGroup<'a> {
1217 system_slot: &'a SMBiosSystemSlot<'a>,
1218 entry_offset: usize,
1219}
1220
1221impl<'a> SlotPeerGroup<'a> {
1222 const SIZE: usize = 5;
1224 const SEGMENT_GROUP_NUMBER_OFFSET: usize = 0;
1225 const BUS_NUMBER_OFFSET: usize = 2;
1226 const DEVICE_FUNCTION_NUMBER_OFFSET: usize = 3;
1227 const DATA_BUS_WIDTH_OFFSET: usize = 4;
1228
1229 fn new(system_slot: &'a SMBiosSystemSlot<'a>, entry_offset: usize) -> Self {
1230 Self {
1231 system_slot,
1232 entry_offset,
1233 }
1234 }
1235
1236 pub fn segment_group_number(&self) -> Option<u16> {
1238 self.system_slot
1239 .parts()
1240 .get_field_word(self.entry_offset + Self::SEGMENT_GROUP_NUMBER_OFFSET)
1241 }
1242
1243 pub fn bus_number(&self) -> Option<u8> {
1245 self.system_slot
1246 .parts()
1247 .get_field_byte(self.entry_offset + Self::BUS_NUMBER_OFFSET)
1248 }
1249
1250 pub fn device_function_number(&self) -> Option<u8> {
1252 self.system_slot
1253 .parts()
1254 .get_field_byte(self.entry_offset + Self::DEVICE_FUNCTION_NUMBER_OFFSET)
1255 }
1256
1257 pub fn data_bus_width(&self) -> Option<u8> {
1261 self.system_slot
1262 .parts()
1263 .get_field_byte(self.entry_offset + Self::DATA_BUS_WIDTH_OFFSET)
1264 }
1265}
1266
1267impl fmt::Debug for SlotPeerGroup<'_> {
1268 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1269 fmt.debug_struct(std::any::type_name::<SlotPeerGroup<'_>>())
1270 .field("segment_group_number", &self.segment_group_number())
1271 .field("bus_number", &self.bus_number())
1272 .field("device_function_number", &self.device_function_number())
1273 .field("data_bus_width", &self.data_bus_width())
1274 .finish()
1275 }
1276}
1277
1278impl Serialize for SlotPeerGroup<'_> {
1279 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1280 where
1281 S: Serializer,
1282 {
1283 let mut state = serializer.serialize_struct("SlotPeerGroup", 4)?;
1284 state.serialize_field("segment_group_number", &self.segment_group_number())?;
1285 state.serialize_field("bus_number", &self.bus_number())?;
1286 state.serialize_field("device_function_number", &self.device_function_number())?;
1287 state.serialize_field("data_bus_width", &self.data_bus_width())?;
1288 state.end()
1289 }
1290}
1291
1292pub struct SlotPeerGroupIterator<'a> {
1294 data: &'a SMBiosSystemSlot<'a>,
1295 current_index: usize,
1296 current_entry: usize,
1297 number_of_entries: usize,
1298}
1299
1300impl<'a> SlotPeerGroupIterator<'a> {
1301 const PEER_GROUPS_OFFSET: usize = 0x13;
1302
1303 fn new(data: &'a SMBiosSystemSlot<'a>) -> Self {
1304 SlotPeerGroupIterator {
1305 data: data,
1306 current_index: Self::PEER_GROUPS_OFFSET,
1307 current_entry: 0,
1308 number_of_entries: data.peer_group_count().unwrap_or(0),
1309 }
1310 }
1311
1312 fn reset(&mut self) {
1313 self.current_index = Self::PEER_GROUPS_OFFSET;
1314 self.current_entry = 0;
1315 }
1316}
1317
1318impl<'a> IntoIterator for &'a SlotPeerGroupIterator<'a> {
1319 type Item = SlotPeerGroup<'a>;
1320 type IntoIter = SlotPeerGroupIterator<'a>;
1321
1322 fn into_iter(self) -> Self::IntoIter {
1323 SlotPeerGroupIterator {
1324 data: self.data,
1325 current_index: SlotPeerGroupIterator::PEER_GROUPS_OFFSET,
1326 current_entry: 0,
1327 number_of_entries: self.data.peer_group_count().unwrap_or(0),
1328 }
1329 }
1330}
1331
1332impl<'a> Iterator for SlotPeerGroupIterator<'a> {
1333 type Item = SlotPeerGroup<'a>;
1334
1335 fn next(&mut self) -> Option<Self::Item> {
1336 if self.current_entry == self.number_of_entries {
1337 self.reset();
1338 return None;
1339 }
1340
1341 let next_index = self.current_index + SlotPeerGroup::SIZE;
1342 match self
1343 .data
1344 .parts()
1345 .get_field_data(self.current_index, next_index)
1346 {
1347 Some(_) => {
1348 let result = SlotPeerGroup::new(self.data, self.current_index);
1349 self.current_index = next_index;
1350 self.current_entry += 1;
1351 Some(result)
1352 }
1353 None => {
1354 self.reset();
1355 None
1356 }
1357 }
1358 }
1359}
1360
1361impl<'a> fmt::Debug for SlotPeerGroupIterator<'a> {
1362 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1363 fmt.debug_list().entries(self.into_iter()).finish()
1364 }
1365}
1366
1367impl<'a> Serialize for SlotPeerGroupIterator<'a> {
1368 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1369 where
1370 S: Serializer,
1371 {
1372 let groups: Vec<SlotPeerGroup<'_>> = self.into_iter().collect();
1373 let mut seq = serializer.serialize_seq(Some(groups.len()))?;
1374 for e in groups {
1375 seq.serialize_element(&e)?;
1376 }
1377 seq.end()
1378 }
1379}
1380
1381#[cfg(test)]
1382mod tests {
1383 use super::*;
1384
1385 #[test]
1386 fn unit_test() {
1387 let struct_type9 = vec![
1395 0x09, 0x11, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x05, 0x07, 0x0C, 0x01, 0x00,
1396 0x00, 0x00, 0x08, 0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
1397 ];
1398
1399 let parts = UndefinedStruct::new(&struct_type9);
1400 let test_struct = SMBiosSystemSlot::new(&parts);
1401
1402 assert_eq!(
1403 test_struct.slot_designation().to_string(),
1404 "J6B2".to_string()
1405 );
1406
1407 assert_eq!(
1408 *test_struct.system_slot_type().unwrap(),
1409 SystemSlotType::PciExpress(
1410 PciExpressGeneration::PCIExpressGen1,
1411 PciExpressSlotWidth::UndefinedSlotWidth,
1412 )
1413 );
1414
1415 assert_eq!(*test_struct.slot_data_bus_width().unwrap(), SlotWidth::X16);
1416
1417 let slot_id = test_struct.slot_id().unwrap();
1418 assert_eq!(slot_id.byte_0(), 5);
1419 assert_eq!(slot_id.byte_1(), 7);
1420
1421 assert!(test_struct.data_bus_width().is_none());
1423
1424 let struct_type9 = vec![
1426 0x09, 0x1C, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x00, 0x00, 0x0C, 0x01, 0x00,
1427 0x00, 0x00, 0x08, 0x99, 0x01, 0x23, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0xAB, 0x09,
1428 0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
1429 ];
1430 let parts = UndefinedStruct::new(&struct_type9);
1431 let test_struct = SMBiosSystemSlot::new(&parts);
1432
1433 assert_eq!(test_struct.data_bus_width(), Some(0x99));
1435 assert_eq!(test_struct.peer_group_count(), Some(0x01));
1436
1437 let mut iterator = test_struct.peer_group_iterator().into_iter();
1438 let first = iterator.next().unwrap();
1439 assert_eq!(first.segment_group_number(), Some(0x0123));
1440 assert_eq!(first.bus_number(), Some(0x04));
1441 assert_eq!(first.device_function_number(), Some(0x05));
1442 assert_eq!(first.data_bus_width(), Some(0x06));
1443
1444 assert_eq!(test_struct.slot_information(), Some(0x07));
1449 assert_eq!(*test_struct.slot_physical_width().unwrap(), SlotWidth::X1);
1450 assert_eq!(test_struct.slot_pitch(), Some(0x09AB));
1451
1452 println!("{:?}", test_struct);
1453 }
1454}