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)]
247pub struct SystemSlotId(pub [u8; 2]);
248
249impl Deref for SystemSlotId {
250 type Target = [u8; 2];
251
252 fn deref(&self) -> &Self::Target {
253 &self.0
254 }
255}
256
257impl SystemSlotId {
258 pub fn byte_0(&self) -> u8 {
260 self.0[0]
261 }
262
263 pub fn byte_1(&self) -> u8 {
265 self.0[1]
266 }
267}
268
269pub struct SystemSlotTypeData {
271 pub raw: u8,
278 pub value: SystemSlotType,
280}
281
282impl Deref for SystemSlotTypeData {
283 type Target = SystemSlotType;
284
285 fn deref(&self) -> &Self::Target {
286 &self.value
287 }
288}
289
290impl From<u8> for SystemSlotTypeData {
291 fn from(raw: u8) -> Self {
293 use M2SlotType::*;
294 use MXMSlotType::*;
295 use PciExpressGeneration::*;
296 use PciExpressSlotWidth::*;
297 use SystemSlotType::*;
298 SystemSlotTypeData {
299 value: match raw {
300 0x01 => Other,
301 0x02 => Unknown,
302 0x03 => Isa,
303 0x04 => Mca,
304 0x05 => Eisa,
305 0x06 => Pci,
306 0x07 => Pcmcia,
307 0x08 => VlVesa,
308 0x09 => Proprietary,
309 0x0A => ProcessorCardSlot,
310 0x0B => ProprietaryMemoryCardSlot,
311 0x0C => IORiserCardSlot,
312 0x0D => NuBus,
313 0x0E => Pci66MhzCapable,
314 0x0F => Agp(AgpSlotWidth::X1),
315 0x10 => Agp(AgpSlotWidth::X2),
316 0x11 => Agp(AgpSlotWidth::X4),
317 0x12 => PciX,
318 0x13 => Agp(AgpSlotWidth::X8),
319 0x14 => M2(M2Socket1DP),
320 0x15 => M2(M2Socket1SD),
321 0x16 => M2(M2Socket2),
322 0x17 => M2(M2Socket3),
323 0x18 => Mxm(MxmTypeI),
324 0x19 => Mxm(MxmTypeII),
325 0x1A => Mxm(MxmTypeIIIStandard),
326 0x1B => Mxm(MxmTypeIIIHE),
327 0x1C => Mxm(MxmTypeIV),
328 0x1D => Mxm(Mxm3TypeA),
329 0x1E => Mxm(Mxm3TypeB),
330 0x1F => PciExpress(PCIExpressGen2, Sff8639),
331 0x20 => PciExpress(PCIExpressGen3, Sff8639),
332 0x21 => PciExpress(Undefined, PciExpressMini52WithKeepouts),
333 0x22 => PciExpress(Undefined, PciExpressMini52WithoutKeepouts),
334 0x23 => PciExpress(Undefined, PciExpressMini76),
335 0x24 => PciExpress(PCIExpressGen4, Sff8639),
336 0x25 => PciExpress(PCIExpressGen5, Sff8639),
337 0x26 => OcpNic30SmallFormFactor,
338 0x27 => OcpNic30LargeFormFactor,
339 0x28 => OcpNicPriorTo30,
340 0x30 => CxlFlexbus1,
341 0xA0 => PC98C20,
342 0xA1 => PC98C24,
343 0xA2 => PC98E,
344 0xA3 => PC98LocalBus,
345 0xA4 => PC98Card,
346 0xA5 => PciExpress(PCIExpressGen1, UndefinedSlotWidth),
347 0xA6 => PciExpress(PCIExpressGen1, X1),
348 0xA7 => PciExpress(PCIExpressGen1, X2),
349 0xA8 => PciExpress(PCIExpressGen1, X4),
350 0xA9 => PciExpress(PCIExpressGen1, X8),
351 0xAA => PciExpress(PCIExpressGen1, X16),
352 0xAB => PciExpress(PCIExpressGen2, UndefinedSlotWidth),
353 0xAC => PciExpress(PCIExpressGen2, X1),
354 0xAD => PciExpress(PCIExpressGen2, X2),
355 0xAE => PciExpress(PCIExpressGen2, X4),
356 0xAF => PciExpress(PCIExpressGen2, X8),
357 0xB0 => PciExpress(PCIExpressGen2, X16),
358 0xB1 => PciExpress(PCIExpressGen3, UndefinedSlotWidth),
359 0xB2 => PciExpress(PCIExpressGen3, X1),
360 0xB3 => PciExpress(PCIExpressGen3, X2),
361 0xB4 => PciExpress(PCIExpressGen3, X4),
362 0xB5 => PciExpress(PCIExpressGen3, X8),
363 0xB6 => PciExpress(PCIExpressGen3, X16),
364 0xB8 => PciExpress(PCIExpressGen4, UndefinedSlotWidth),
365 0xB9 => PciExpress(PCIExpressGen4, X1),
366 0xBA => PciExpress(PCIExpressGen4, X2),
367 0xBB => PciExpress(PCIExpressGen4, X4),
368 0xBC => PciExpress(PCIExpressGen4, X8),
369 0xBD => PciExpress(PCIExpressGen4, X16),
370 0xBE => PciExpress(PCIExpressGen5, UndefinedSlotWidth),
371 0xBF => PciExpress(PCIExpressGen5, X1),
372 0xC0 => PciExpress(PCIExpressGen5, X2),
373 0xC1 => PciExpress(PCIExpressGen5, X4),
374 0xC2 => PciExpress(PCIExpressGen5, X8),
375 0xC3 => PciExpress(PCIExpressGen5, X16),
376 0xC4 => PciExpress(PCIExpressGen6, UndefinedSlotWidth),
377 0xC5 => EnterpriseAndDataCenter1UE1,
378 0xC6 => EnterpriseAndDataCenter3InE3,
379 _ => None,
380 },
381 raw,
382 }
383 }
384}
385
386impl fmt::Debug for SystemSlotTypeData {
387 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
388 fmt.debug_struct(std::any::type_name::<SystemSlotTypeData>())
389 .field("raw", &self.raw)
390 .field("value", &self.value)
391 .finish()
392 }
393}
394
395impl Serialize for SystemSlotTypeData {
396 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
397 where
398 S: Serializer,
399 {
400 let mut state = serializer.serialize_struct("SystemSlotTypeData", 2)?;
401 state.serialize_field("raw", &self.raw)?;
402 state.serialize_field("value", &self.value)?;
403 state.end()
404 }
405}
406
407impl fmt::Display for SystemSlotTypeData {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 match &self.value {
410 SystemSlotType::None => write!(f, "{}", &self.raw),
411 _ => write!(f, "{:?}", &self.value),
412 }
413 }
414}
415
416#[derive(Serialize, Debug, PartialEq, Eq)]
418pub enum SystemSlotType {
419 Other,
421 Unknown,
423 Isa,
425 Mca,
427 Eisa,
429 Pci,
431 Pcmcia,
433 VlVesa,
435 Proprietary,
437 ProcessorCardSlot,
439 ProprietaryMemoryCardSlot,
441 IORiserCardSlot,
443 NuBus,
445 Pci66MhzCapable,
447 Agp(AgpSlotWidth),
449 Mxm(MXMSlotType),
451 PciX,
453 M2(M2SlotType),
455 OcpNic30SmallFormFactor,
457 OcpNic30LargeFormFactor,
459 OcpNicPriorTo30,
461 CxlFlexbus1,
463 PC98C20,
465 PC98C24,
467 PC98E,
469 PC98LocalBus,
471 PC98Card,
473 PciExpress(PciExpressGeneration, PciExpressSlotWidth),
475 EnterpriseAndDataCenter1UE1,
477 EnterpriseAndDataCenter3InE3,
479 None,
481}
482
483#[derive(Serialize, Debug, PartialEq, Eq)]
485pub enum PciExpressGeneration {
486 PCIExpressGen1,
488 PCIExpressGen2,
490 PCIExpressGen3,
492 PCIExpressGen4,
494 PCIExpressGen5,
496 PCIExpressGen6,
498 Undefined,
500}
501
502#[derive(Serialize, Debug, PartialEq, Eq)]
504pub enum PciExpressSlotWidth {
505 UndefinedSlotWidth,
507 X1,
509 X2,
511 X4,
513 X8,
515 X16,
517 Sff8639,
519 PciExpressMini52WithKeepouts,
521 PciExpressMini52WithoutKeepouts,
523 PciExpressMini76,
525}
526
527#[derive(Serialize, Debug, PartialEq, Eq)]
529pub enum AgpSlotWidth {
530 X1,
532 X2,
534 X4,
536 X8,
538}
539
540#[derive(Serialize, Debug, PartialEq, Eq)]
542pub enum MXMSlotType {
543 MxmTypeI,
545 MxmTypeII,
547 MxmTypeIIIStandard,
549 MxmTypeIIIHE,
551 MxmTypeIV,
553 Mxm3TypeA,
555 Mxm3TypeB,
557}
558
559#[derive(Serialize, Debug, PartialEq, Eq)]
561pub enum M2SlotType {
562 M2Socket1DP,
564 M2Socket1SD,
566 M2Socket2,
568 M2Socket3,
570}
571
572pub struct SlotWidthData {
574 pub raw: u8,
581 pub value: SlotWidth,
583}
584
585impl Deref for SlotWidthData {
586 type Target = SlotWidth;
587
588 fn deref(&self) -> &Self::Target {
589 &self.value
590 }
591}
592
593impl From<u8> for SlotWidthData {
594 fn from(raw: u8) -> Self {
595 SlotWidthData {
596 value: match raw {
597 0x01 => SlotWidth::Other,
598 0x02 => SlotWidth::Unknown,
599 0x03 => SlotWidth::Bit8,
600 0x04 => SlotWidth::Bit16,
601 0x05 => SlotWidth::Bit32,
602 0x06 => SlotWidth::Bit64,
603 0x07 => SlotWidth::Bit128,
604 0x08 => SlotWidth::X1,
605 0x09 => SlotWidth::X2,
606 0x0A => SlotWidth::X4,
607 0x0B => SlotWidth::X8,
608 0x0C => SlotWidth::X12,
609 0x0D => SlotWidth::X16,
610 0x0E => SlotWidth::X32,
611 _ => SlotWidth::None,
612 },
613 raw,
614 }
615 }
616}
617
618impl fmt::Debug for SlotWidthData {
619 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
620 fmt.debug_struct(std::any::type_name::<SlotWidthData>())
621 .field("raw", &self.raw)
622 .field("value", &self.value)
623 .finish()
624 }
625}
626
627impl Serialize for SlotWidthData {
628 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
629 where
630 S: Serializer,
631 {
632 let mut state = serializer.serialize_struct("SlotWidthData", 2)?;
633 state.serialize_field("raw", &self.raw)?;
634 state.serialize_field("value", &self.value)?;
635 state.end()
636 }
637}
638
639#[derive(Serialize, Debug, PartialEq, Eq)]
641pub enum SlotWidth {
642 Other,
644 Unknown,
646 Bit8,
648 Bit16,
650 Bit32,
652 Bit64,
654 Bit128,
656 X1,
658 X2,
660 X4,
662 X8,
664 X12,
666 X16,
668 X32,
670 None,
672}
673
674pub struct SlotHeightData {
676 pub raw: u8,
683 pub value: SlotHeight,
685}
686
687impl Deref for SlotHeightData {
688 type Target = SlotHeight;
689
690 fn deref(&self) -> &Self::Target {
691 &self.value
692 }
693}
694
695impl From<u8> for SlotHeightData {
696 fn from(raw: u8) -> Self {
697 SlotHeightData {
698 value: match raw {
699 0x00 => SlotHeight::NotApplicable,
700 0x01 => SlotHeight::Other,
701 0x02 => SlotHeight::Unknown,
702 0x03 => SlotHeight::FullHeight,
703 0x04 => SlotHeight::LowProfile,
704 _ => SlotHeight::None,
705 },
706 raw,
707 }
708 }
709}
710
711impl fmt::Debug for SlotHeightData {
712 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
713 fmt.debug_struct(std::any::type_name::<SlotHeightData>())
714 .field("raw", &self.raw)
715 .field("value", &self.value)
716 .finish()
717 }
718}
719
720impl Serialize for SlotHeightData {
721 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
722 where
723 S: Serializer,
724 {
725 let mut state = serializer.serialize_struct("SlotHeightData", 2)?;
726 state.serialize_field("raw", &self.raw)?;
727 state.serialize_field("value", &self.value)?;
728 state.end()
729 }
730}
731
732#[derive(Serialize, Debug, PartialEq, Eq)]
734pub enum SlotHeight {
735 NotApplicable,
737 Other,
739 Unknown,
741 FullHeight,
743 LowProfile,
745 None,
747}
748
749pub struct SlotCurrentUsageData {
751 pub raw: u8,
758 pub value: SlotCurrentUsage,
760}
761
762impl Deref for SlotCurrentUsageData {
763 type Target = SlotCurrentUsage;
764
765 fn deref(&self) -> &Self::Target {
766 &self.value
767 }
768}
769
770impl From<u8> for SlotCurrentUsageData {
771 fn from(raw: u8) -> Self {
772 SlotCurrentUsageData {
773 value: match raw {
774 0x01 => SlotCurrentUsage::Other,
775 0x02 => SlotCurrentUsage::Unknown,
776 0x03 => SlotCurrentUsage::Available,
777 0x04 => SlotCurrentUsage::InUse,
778 0x05 => SlotCurrentUsage::Unavailable,
779 _ => SlotCurrentUsage::None,
780 },
781 raw,
782 }
783 }
784}
785
786impl fmt::Debug for SlotCurrentUsageData {
787 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
788 fmt.debug_struct(std::any::type_name::<SlotCurrentUsageData>())
789 .field("raw", &self.raw)
790 .field("value", &self.value)
791 .finish()
792 }
793}
794
795impl Serialize for SlotCurrentUsageData {
796 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
797 where
798 S: Serializer,
799 {
800 let mut state = serializer.serialize_struct("SlotCurrentUsageData", 2)?;
801 state.serialize_field("raw", &self.raw)?;
802 state.serialize_field("value", &self.value)?;
803 state.end()
804 }
805}
806
807#[derive(Serialize, Debug, PartialEq, Eq)]
809pub enum SlotCurrentUsage {
810 Other,
812 Unknown,
814 Available,
816 InUse,
818 Unavailable,
820 None,
822}
823
824pub struct SlotLengthData {
826 pub raw: u8,
833 pub value: SlotLength,
835}
836
837impl Deref for SlotLengthData {
838 type Target = SlotLength;
839
840 fn deref(&self) -> &Self::Target {
841 &self.value
842 }
843}
844
845impl From<u8> for SlotLengthData {
846 fn from(raw: u8) -> Self {
847 use SlotLength::*;
848 SlotLengthData {
849 value: match raw {
850 0x01 => Other,
851 0x02 => Unknown,
852 0x03 => ShortLength,
853 0x04 => LongLength,
854 0x05 => DriveFormFactor25,
855 0x06 => DriveFormFactor35,
856 _ => None,
857 },
858 raw,
859 }
860 }
861}
862
863impl fmt::Debug for SlotLengthData {
864 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
865 fmt.debug_struct(std::any::type_name::<SlotLengthData>())
866 .field("raw", &self.raw)
867 .field("value", &self.value)
868 .finish()
869 }
870}
871
872impl Serialize for SlotLengthData {
873 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
874 where
875 S: Serializer,
876 {
877 let mut state = serializer.serialize_struct("SlotLengthData", 2)?;
878 state.serialize_field("raw", &self.raw)?;
879 state.serialize_field("value", &self.value)?;
880 state.end()
881 }
882}
883
884#[derive(Serialize, Debug, PartialEq, Eq)]
886pub enum SlotLength {
887 Other,
889 Unknown,
891 ShortLength,
893 LongLength,
895 DriveFormFactor25,
897 DriveFormFactor35,
899 None,
901}
902
903#[derive(PartialEq, Eq)]
905pub struct SystemSlotCharacteristics1 {
906 pub raw: u8,
910}
911
912impl Deref for SystemSlotCharacteristics1 {
913 type Target = u8;
914
915 fn deref(&self) -> &Self::Target {
916 &self.raw
917 }
918}
919
920impl From<u8> for SystemSlotCharacteristics1 {
921 fn from(raw: u8) -> Self {
922 SystemSlotCharacteristics1 { raw }
923 }
924}
925
926impl SystemSlotCharacteristics1 {
927 pub fn unknown(&self) -> bool {
929 self.raw & 0x01 == 0x01
930 }
931
932 pub fn provides5_volts(&self) -> bool {
934 self.raw & 0x02 == 0x02
935 }
936
937 pub fn provides33_volts(&self) -> bool {
939 self.raw & 0x04 == 0x04
940 }
941
942 pub fn shared(&self) -> bool {
944 self.raw & 0x08 == 0x08
945 }
946
947 pub fn supports_pc_card16(&self) -> bool {
949 self.raw & 0x10 == 0x10
950 }
951
952 pub fn supports_card_bus(&self) -> bool {
954 self.raw & 0x20 == 0x20
955 }
956
957 pub fn supports_zoom_video(&self) -> bool {
959 self.raw & 0x40 == 0x40
960 }
961
962 pub fn supports_modem_ring_resume(&self) -> bool {
964 self.raw & 0x80 == 0x80
965 }
966}
967
968impl fmt::Debug for SystemSlotCharacteristics1 {
969 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
970 fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics1>())
971 .field("raw", &self.raw)
972 .field("unknown", &self.unknown())
973 .field("provides5_volts", &self.provides5_volts())
974 .field("provides33_volts", &self.provides33_volts())
975 .field("shared", &self.shared())
976 .field("supports_pc_card16", &self.supports_pc_card16())
977 .field("supports_card_bus", &self.supports_card_bus())
978 .field("supports_zoom_video", &self.supports_zoom_video())
979 .field(
980 "supports_modem_ring_resume",
981 &self.supports_modem_ring_resume(),
982 )
983 .finish()
984 }
985}
986
987impl Serialize for SystemSlotCharacteristics1 {
988 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
989 where
990 S: Serializer,
991 {
992 let mut state = serializer.serialize_struct("SystemSlotCharacteristics1", 9)?;
993 state.serialize_field("raw", &self.raw)?;
994 state.serialize_field("unknown", &self.unknown())?;
995 state.serialize_field("provides5_volts", &self.provides5_volts())?;
996 state.serialize_field("provides33_volts", &self.provides33_volts())?;
997 state.serialize_field("shared", &self.shared())?;
998 state.serialize_field("supports_pc_card16", &self.supports_pc_card16())?;
999 state.serialize_field("supports_card_bus", &self.supports_card_bus())?;
1000 state.serialize_field("supports_zoom_video", &self.supports_zoom_video())?;
1001 state.serialize_field(
1002 "supports_modem_ring_resume",
1003 &self.supports_modem_ring_resume(),
1004 )?;
1005 state.end()
1006 }
1007}
1008
1009#[derive(PartialEq, Eq)]
1011pub struct SystemSlotCharacteristics2 {
1012 pub raw: u8,
1019}
1020
1021impl Deref for SystemSlotCharacteristics2 {
1022 type Target = u8;
1023
1024 fn deref(&self) -> &Self::Target {
1025 &self.raw
1026 }
1027}
1028
1029impl From<u8> for SystemSlotCharacteristics2 {
1030 fn from(raw: u8) -> Self {
1031 SystemSlotCharacteristics2 { raw }
1032 }
1033}
1034
1035impl SystemSlotCharacteristics2 {
1036 pub fn supports_power_management_event(&self) -> bool {
1038 self.raw & 0x01 == 0x01
1039 }
1040
1041 pub fn supports_hot_plug_devices(&self) -> bool {
1043 self.raw & 0x02 == 0x02
1044 }
1045
1046 pub fn supports_smbus_signal(&self) -> bool {
1048 self.raw & 0x04 == 0x04
1049 }
1050
1051 pub fn supports_bifurcation(&self) -> bool {
1057 self.raw & 0x08 == 0x08
1058 }
1059
1060 pub fn supports_suprise_removal(&self) -> bool {
1064 self.raw & 0x10 == 0x10
1065 }
1066
1067 pub fn flexbus_slot_cxl10_capable(&self) -> bool {
1069 self.raw & 0x20 == 0x20
1070 }
1071
1072 pub fn flexbus_slot_cxl20_capable(&self) -> bool {
1074 self.raw & 0x40 == 0x40
1075 }
1076
1077 pub fn flexbus_slot_cxl30_capable(&self) -> bool {
1079 self.raw & 0x80 == 0x80
1080 }
1081}
1082
1083impl fmt::Debug for SystemSlotCharacteristics2 {
1084 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1085 fmt.debug_struct(std::any::type_name::<SystemSlotCharacteristics2>())
1086 .field("raw", &self.raw)
1087 .field(
1088 "supports_power_management_event",
1089 &self.supports_power_management_event(),
1090 )
1091 .field(
1092 "supports_hot_plug_devices",
1093 &self.supports_hot_plug_devices(),
1094 )
1095 .field("supports_smbus_signal", &self.supports_smbus_signal())
1096 .field("supports_bifurcation", &self.supports_bifurcation())
1097 .field("supports_suprise_removal", &self.supports_suprise_removal())
1098 .field(
1099 "flexbus_slot_cxl10_capable",
1100 &self.flexbus_slot_cxl10_capable(),
1101 )
1102 .field(
1103 "flexbus_slot_cxl20_capable",
1104 &self.flexbus_slot_cxl20_capable(),
1105 )
1106 .field(
1107 "flexbus_slot_cxl30_capable",
1108 &self.flexbus_slot_cxl30_capable(),
1109 )
1110 .finish()
1111 }
1112}
1113
1114impl Serialize for SystemSlotCharacteristics2 {
1115 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1116 where
1117 S: Serializer,
1118 {
1119 let mut state = serializer.serialize_struct("SystemSlotCharacteristics2", 8)?;
1120 state.serialize_field("raw", &self.raw)?;
1121 state.serialize_field(
1122 "supports_power_management_event",
1123 &self.supports_power_management_event(),
1124 )?;
1125 state.serialize_field(
1126 "supports_hot_plug_devices",
1127 &self.supports_hot_plug_devices(),
1128 )?;
1129 state.serialize_field("supports_smbus_signal", &self.supports_smbus_signal())?;
1130 state.serialize_field("supports_bifurcation", &self.supports_bifurcation())?;
1131 state.serialize_field("supports_suprise_removal", &self.supports_suprise_removal())?;
1132 state.serialize_field(
1133 "flexbus_slot_cxl10_capable",
1134 &self.flexbus_slot_cxl10_capable(),
1135 )?;
1136 state.serialize_field(
1137 "flexbus_slot_cxl20_capable",
1138 &self.flexbus_slot_cxl20_capable(),
1139 )?;
1140 state.serialize_field(
1141 "flexbus_slot_cxl30_capable",
1142 &self.flexbus_slot_cxl30_capable(),
1143 )?;
1144 state.end()
1145 }
1146}
1147
1148#[derive(Serialize, Debug, PartialEq, Eq)]
1150pub enum SegmentGroupNumber {
1151 SingleSegment,
1153 Number(u16),
1155 NotApplicable,
1158}
1159
1160impl From<u16> for SegmentGroupNumber {
1161 fn from(raw: u16) -> Self {
1162 match raw {
1163 0x00 => SegmentGroupNumber::SingleSegment,
1164 0xFF => SegmentGroupNumber::NotApplicable,
1165 _ => SegmentGroupNumber::Number(raw),
1166 }
1167 }
1168}
1169
1170#[derive(Serialize, Debug, PartialEq, Eq)]
1172pub enum BusNumber {
1173 Number(u8),
1175 NotApplicable,
1178}
1179
1180impl From<u8> for BusNumber {
1181 fn from(raw: u8) -> Self {
1182 match raw {
1183 0xFF => BusNumber::NotApplicable,
1184 _ => BusNumber::Number(raw),
1185 }
1186 }
1187}
1188
1189#[derive(Serialize, Debug, PartialEq, Eq)]
1191pub enum DeviceFunctionNumber {
1192 Number {
1194 device: u8,
1196 function: u8,
1198 },
1199 NotApplicable,
1202}
1203
1204impl From<u8> for DeviceFunctionNumber {
1205 fn from(raw: u8) -> Self {
1206 match raw {
1207 0xFF => DeviceFunctionNumber::NotApplicable,
1208 _ => DeviceFunctionNumber::Number {
1209 device: (raw & 0b11111000) >> 3,
1210 function: raw & 0b00000111,
1211 },
1212 }
1213 }
1214}
1215
1216pub struct SlotPeerGroup<'a> {
1218 system_slot: &'a SMBiosSystemSlot<'a>,
1219 entry_offset: usize,
1220}
1221
1222impl<'a> SlotPeerGroup<'a> {
1223 const SIZE: usize = 5;
1225 const SEGMENT_GROUP_NUMBER_OFFSET: usize = 0;
1226 const BUS_NUMBER_OFFSET: usize = 2;
1227 const DEVICE_FUNCTION_NUMBER_OFFSET: usize = 3;
1228 const DATA_BUS_WIDTH_OFFSET: usize = 4;
1229
1230 fn new(system_slot: &'a SMBiosSystemSlot<'a>, entry_offset: usize) -> Self {
1231 Self {
1232 system_slot,
1233 entry_offset,
1234 }
1235 }
1236
1237 pub fn segment_group_number(&self) -> Option<u16> {
1239 self.system_slot
1240 .parts()
1241 .get_field_word(self.entry_offset + Self::SEGMENT_GROUP_NUMBER_OFFSET)
1242 }
1243
1244 pub fn bus_number(&self) -> Option<u8> {
1246 self.system_slot
1247 .parts()
1248 .get_field_byte(self.entry_offset + Self::BUS_NUMBER_OFFSET)
1249 }
1250
1251 pub fn device_function_number(&self) -> Option<u8> {
1253 self.system_slot
1254 .parts()
1255 .get_field_byte(self.entry_offset + Self::DEVICE_FUNCTION_NUMBER_OFFSET)
1256 }
1257
1258 pub fn data_bus_width(&self) -> Option<u8> {
1262 self.system_slot
1263 .parts()
1264 .get_field_byte(self.entry_offset + Self::DATA_BUS_WIDTH_OFFSET)
1265 }
1266}
1267
1268impl fmt::Debug for SlotPeerGroup<'_> {
1269 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1270 fmt.debug_struct(std::any::type_name::<SlotPeerGroup<'_>>())
1271 .field("segment_group_number", &self.segment_group_number())
1272 .field("bus_number", &self.bus_number())
1273 .field("device_function_number", &self.device_function_number())
1274 .field("data_bus_width", &self.data_bus_width())
1275 .finish()
1276 }
1277}
1278
1279impl Serialize for SlotPeerGroup<'_> {
1280 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1281 where
1282 S: Serializer,
1283 {
1284 let mut state = serializer.serialize_struct("SlotPeerGroup", 4)?;
1285 state.serialize_field("segment_group_number", &self.segment_group_number())?;
1286 state.serialize_field("bus_number", &self.bus_number())?;
1287 state.serialize_field("device_function_number", &self.device_function_number())?;
1288 state.serialize_field("data_bus_width", &self.data_bus_width())?;
1289 state.end()
1290 }
1291}
1292
1293pub struct SlotPeerGroupIterator<'a> {
1295 data: &'a SMBiosSystemSlot<'a>,
1296 current_index: usize,
1297 current_entry: usize,
1298 number_of_entries: usize,
1299}
1300
1301impl<'a> SlotPeerGroupIterator<'a> {
1302 const PEER_GROUPS_OFFSET: usize = 0x13;
1303
1304 fn new(data: &'a SMBiosSystemSlot<'a>) -> Self {
1305 SlotPeerGroupIterator {
1306 data: data,
1307 current_index: Self::PEER_GROUPS_OFFSET,
1308 current_entry: 0,
1309 number_of_entries: data.peer_group_count().unwrap_or(0),
1310 }
1311 }
1312
1313 fn reset(&mut self) {
1314 self.current_index = Self::PEER_GROUPS_OFFSET;
1315 self.current_entry = 0;
1316 }
1317}
1318
1319impl<'a> IntoIterator for &'a SlotPeerGroupIterator<'a> {
1320 type Item = SlotPeerGroup<'a>;
1321 type IntoIter = SlotPeerGroupIterator<'a>;
1322
1323 fn into_iter(self) -> Self::IntoIter {
1324 SlotPeerGroupIterator {
1325 data: self.data,
1326 current_index: SlotPeerGroupIterator::PEER_GROUPS_OFFSET,
1327 current_entry: 0,
1328 number_of_entries: self.data.peer_group_count().unwrap_or(0),
1329 }
1330 }
1331}
1332
1333impl<'a> Iterator for SlotPeerGroupIterator<'a> {
1334 type Item = SlotPeerGroup<'a>;
1335
1336 fn next(&mut self) -> Option<Self::Item> {
1337 if self.current_entry == self.number_of_entries {
1338 self.reset();
1339 return None;
1340 }
1341
1342 let next_index = self.current_index + SlotPeerGroup::SIZE;
1343 match self
1344 .data
1345 .parts()
1346 .get_field_data(self.current_index, next_index)
1347 {
1348 Some(_) => {
1349 let result = SlotPeerGroup::new(self.data, self.current_index);
1350 self.current_index = next_index;
1351 self.current_entry += 1;
1352 Some(result)
1353 }
1354 None => {
1355 self.reset();
1356 None
1357 }
1358 }
1359 }
1360}
1361
1362impl<'a> fmt::Debug for SlotPeerGroupIterator<'a> {
1363 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1364 fmt.debug_list().entries(self.into_iter()).finish()
1365 }
1366}
1367
1368impl<'a> Serialize for SlotPeerGroupIterator<'a> {
1369 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1370 where
1371 S: Serializer,
1372 {
1373 let groups: Vec<SlotPeerGroup<'_>> = self.into_iter().collect();
1374 let mut seq = serializer.serialize_seq(Some(groups.len()))?;
1375 for e in groups {
1376 seq.serialize_element(&e)?;
1377 }
1378 seq.end()
1379 }
1380}
1381
1382#[cfg(test)]
1383mod tests {
1384 use super::*;
1385
1386 #[test]
1387 fn unit_test() {
1388 let struct_type9 = vec![
1396 0x09, 0x11, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x05, 0x07, 0x0C, 0x01, 0x00,
1397 0x00, 0x00, 0x08, 0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
1398 ];
1399
1400 let parts = UndefinedStruct::new(&struct_type9);
1401 let test_struct = SMBiosSystemSlot::new(&parts);
1402
1403 assert_eq!(
1404 test_struct.slot_designation().to_string(),
1405 "J6B2".to_string()
1406 );
1407
1408 assert_eq!(
1409 *test_struct.system_slot_type().unwrap(),
1410 SystemSlotType::PciExpress(
1411 PciExpressGeneration::PCIExpressGen1,
1412 PciExpressSlotWidth::UndefinedSlotWidth,
1413 )
1414 );
1415
1416 assert_eq!(*test_struct.slot_data_bus_width().unwrap(), SlotWidth::X16);
1417
1418 let slot_id = test_struct.slot_id().unwrap();
1419 assert_eq!(slot_id.byte_0(), 5);
1420 assert_eq!(slot_id.byte_1(), 7);
1421
1422 assert!(test_struct.data_bus_width().is_none());
1424
1425 let struct_type9 = vec![
1427 0x09, 0x1C, 0x1C, 0x00, 0x01, 0xA5, 0x0D, 0x04, 0x04, 0x00, 0x00, 0x0C, 0x01, 0x00,
1428 0x00, 0x00, 0x08, 0x99, 0x01, 0x23, 0x01, 0x04, 0x05, 0x06, 0x07, 0x08, 0xAB, 0x09,
1429 0x4A, 0x36, 0x42, 0x32, 0x00, 0x00,
1430 ];
1431 let parts = UndefinedStruct::new(&struct_type9);
1432 let test_struct = SMBiosSystemSlot::new(&parts);
1433
1434 assert_eq!(test_struct.data_bus_width(), Some(0x99));
1436 assert_eq!(test_struct.peer_group_count(), Some(0x01));
1437
1438 let mut iterator = test_struct.peer_group_iterator().into_iter();
1439 let first = iterator.next().unwrap();
1440 assert_eq!(first.segment_group_number(), Some(0x0123));
1441 assert_eq!(first.bus_number(), Some(0x04));
1442 assert_eq!(first.device_function_number(), Some(0x05));
1443 assert_eq!(first.data_bus_width(), Some(0x06));
1444
1445 assert_eq!(test_struct.slot_information(), Some(0x07));
1450 assert_eq!(*test_struct.slot_physical_width().unwrap(), SlotWidth::X1);
1451 assert_eq!(test_struct.slot_pitch(), Some(0x09AB));
1452
1453 println!("{:?}", test_struct);
1454 }
1455}