1use crate::core::{strings::*, Header, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeSeq, ser::SerializeStruct, Serialize, Serializer};
4use std::fmt;
5
6pub struct SMBiosOnBoardDeviceInformation<'a> {
20 parts: &'a UndefinedStruct,
21}
22
23impl<'a> SMBiosStruct<'a> for SMBiosOnBoardDeviceInformation<'a> {
24 const STRUCT_TYPE: u8 = 10u8;
25
26 fn new(parts: &'a UndefinedStruct) -> Self {
27 Self { parts }
28 }
29
30 fn parts(&self) -> &'a UndefinedStruct {
31 self.parts
32 }
33}
34
35impl<'a> SMBiosOnBoardDeviceInformation<'a> {
36 pub fn number_of_devices(&self) -> usize {
38 let struct_length = self.parts().header.length() as usize;
39
40 (struct_length - Header::SIZE) / OnBoardDevice::SIZE
41 }
42
43 pub fn onboard_device_iterator(&'a self) -> OnBoardDeviceIterator<'a> {
45 OnBoardDeviceIterator::new(self)
46 }
47}
48
49impl fmt::Debug for SMBiosOnBoardDeviceInformation<'_> {
50 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
51 fmt.debug_struct(std::any::type_name::<SMBiosOnBoardDeviceInformation<'_>>())
52 .field("header", &self.parts.header)
53 .field("number_of_devices", &self.number_of_devices())
54 .field("onboard_device_iterator", &self.onboard_device_iterator())
55 .finish()
56 }
57}
58
59impl Serialize for SMBiosOnBoardDeviceInformation<'_> {
60 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
61 where
62 S: Serializer,
63 {
64 let mut state = serializer.serialize_struct("SMBiosOnBoardDeviceInformation", 3)?;
65 state.serialize_field("header", &self.parts.header)?;
66 state.serialize_field("number_of_devices", &self.number_of_devices())?;
67 state.serialize_field("onboard_device_iterator", &self.onboard_device_iterator())?;
68 state.end()
69 }
70}
71
72pub struct OnBoardDevice<'a> {
74 onboard_device_information: &'a SMBiosOnBoardDeviceInformation<'a>,
75 entry_offset: usize,
76}
77
78impl<'a> OnBoardDevice<'a> {
79 const SIZE: usize = 2;
86
87 fn new(
88 onboard_device_information: &'a SMBiosOnBoardDeviceInformation<'a>,
89 entry_offset: usize,
90 ) -> Self {
91 Self {
92 onboard_device_information,
93 entry_offset,
94 }
95 }
96
97 pub fn device_type(&self) -> Option<OnBoardDeviceType> {
99 self.onboard_device_information
100 .parts()
101 .get_field_byte(self.entry_offset)
102 .map(|raw| OnBoardDeviceType::from(raw))
103 }
104
105 pub fn description(&self) -> SMBiosString {
107 self.onboard_device_information
108 .parts()
109 .get_field_string(self.entry_offset + 1)
110 }
111}
112
113impl fmt::Debug for OnBoardDevice<'_> {
114 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
115 fmt.debug_struct(std::any::type_name::<OnBoardDevice<'_>>())
116 .field("device_type", &self.device_type())
117 .field("description", &self.description())
118 .finish()
119 }
120}
121
122impl Serialize for OnBoardDevice<'_> {
123 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
124 where
125 S: Serializer,
126 {
127 let mut state = serializer.serialize_struct("OnBoardDevice", 2)?;
128 state.serialize_field("device_type", &self.device_type())?;
129 state.serialize_field("description", &self.description())?;
130 state.end()
131 }
132}
133
134pub struct OnBoardDeviceType {
136 pub raw: u8,
138}
139
140impl OnBoardDeviceType {
141 pub fn type_of_device(&self) -> TypeOfDevice {
143 let result = self.raw & 0x7F;
144 match result {
145 0x01 => TypeOfDevice::Other,
146 0x02 => TypeOfDevice::Unknown,
147 0x03 => TypeOfDevice::Video,
148 0x04 => TypeOfDevice::ScsiController,
149 0x05 => TypeOfDevice::Ethernet,
150 0x06 => TypeOfDevice::TokenRing,
151 0x07 => TypeOfDevice::Sound,
152 0x08 => TypeOfDevice::PataController,
153 0x09 => TypeOfDevice::SataController,
154 0x0A => TypeOfDevice::SasController,
155 0x0B => TypeOfDevice::WirelessLan,
156 0x0C => TypeOfDevice::Bluetooth,
157 0x0D => TypeOfDevice::Wwan,
158 0x0E => TypeOfDevice::Emmc,
159 0x0F => TypeOfDevice::NvmeController,
160 0x10 => TypeOfDevice::UfsController,
161 _ => TypeOfDevice::None,
162 }
163 }
164
165 pub fn status(&self) -> DeviceStatus {
167 if self.raw & 0x80 == 0x80 {
168 DeviceStatus::Enabled
169 } else {
170 DeviceStatus::Disabled
171 }
172 }
173}
174
175impl From<u8> for OnBoardDeviceType {
176 fn from(raw: u8) -> Self {
177 OnBoardDeviceType { raw }
178 }
179}
180
181impl fmt::Debug for OnBoardDeviceType {
182 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
183 fmt.debug_struct(std::any::type_name::<OnBoardDevice<'_>>())
184 .field("raw", &self.raw)
185 .field("type_of_device", &self.type_of_device())
186 .field("status", &self.status())
187 .finish()
188 }
189}
190
191impl Serialize for OnBoardDeviceType {
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: Serializer,
195 {
196 let mut state = serializer.serialize_struct("OnBoardDeviceType", 3)?;
197 state.serialize_field("raw", &self.raw)?;
198 state.serialize_field("type_of_device", &self.type_of_device())?;
199 state.serialize_field("status", &self.status())?;
200 state.end()
201 }
202}
203
204#[derive(Serialize, Debug, PartialEq, Eq)]
206pub enum TypeOfDevice {
207 Other,
209 Unknown,
211 Video,
213 ScsiController,
215 Ethernet,
217 TokenRing,
219 Sound,
221 PataController,
223 SataController,
225 SasController,
227 WirelessLan,
229 Bluetooth,
231 Wwan,
233 Emmc,
235 NvmeController,
237 UfsController,
239 None,
241}
242
243#[derive(Serialize, Debug, PartialEq, Eq)]
245pub enum DeviceStatus {
246 Enabled,
248 Disabled,
250}
251
252pub struct OnBoardDeviceIterator<'a> {
254 data: &'a SMBiosOnBoardDeviceInformation<'a>,
255 current_index: usize,
256 current_entry: usize,
257 number_of_entries: usize,
258}
259
260impl<'a> OnBoardDeviceIterator<'a> {
261 const DEVICES_OFFSET: usize = 4usize;
262
263 fn new(data: &'a SMBiosOnBoardDeviceInformation<'a>) -> Self {
264 OnBoardDeviceIterator {
265 data: data,
266 current_index: Self::DEVICES_OFFSET,
267 current_entry: 0,
268 number_of_entries: data.number_of_devices(),
269 }
270 }
271
272 fn reset(&mut self) {
273 self.current_index = Self::DEVICES_OFFSET;
274 self.current_entry = 0;
275 }
276}
277
278impl<'a> IntoIterator for &'a OnBoardDeviceIterator<'a> {
279 type Item = OnBoardDevice<'a>;
280 type IntoIter = OnBoardDeviceIterator<'a>;
281
282 fn into_iter(self) -> Self::IntoIter {
283 OnBoardDeviceIterator {
284 data: self.data,
285 current_index: OnBoardDeviceIterator::DEVICES_OFFSET,
286 current_entry: 0,
287 number_of_entries: self.data.number_of_devices(),
288 }
289 }
290}
291
292impl<'a> Iterator for OnBoardDeviceIterator<'a> {
293 type Item = OnBoardDevice<'a>;
294
295 fn next(&mut self) -> Option<Self::Item> {
296 if self.current_entry == self.number_of_entries {
297 self.reset();
298 return None;
299 }
300
301 let next_index = self.current_index + OnBoardDevice::SIZE;
302 match self
303 .data
304 .parts()
305 .get_field_data(self.current_index, next_index)
306 {
307 Some(_) => {
308 let result = OnBoardDevice::new(self.data, self.current_index);
309 self.current_index = next_index;
310 self.current_entry = self.current_entry + 1;
311 Some(result)
312 }
313 None => {
314 self.reset();
315 None
316 }
317 }
318 }
319}
320
321impl<'a> fmt::Debug for OnBoardDeviceIterator<'a> {
322 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
323 fmt.debug_list().entries(self.into_iter()).finish()
324 }
325}
326
327impl<'a> Serialize for OnBoardDeviceIterator<'a> {
328 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
329 where
330 S: Serializer,
331 {
332 let devices: Vec<OnBoardDevice<'_>> = self.into_iter().collect();
333 let mut seq = serializer.serialize_seq(Some(devices.len()))?;
334 for e in devices {
335 seq.serialize_element(&e)?;
336 }
337 seq.end()
338 }
339}
340
341#[cfg(test)]
342mod tests {
343 use super::*;
344
345 #[test]
346 fn unit_test() {
347 let struct_type10 = vec![
348 0x0A, 0x06, 0x21, 0x00, 0x83, 0x01, 0x20, 0x20, 0x20, 0x54, 0x6F, 0x20, 0x42, 0x65,
349 0x20, 0x46, 0x69, 0x6C, 0x6C, 0x65, 0x64, 0x20, 0x42, 0x79, 0x20, 0x4F, 0x2E, 0x45,
350 0x2E, 0x4D, 0x2E, 0x00, 0x00,
351 ];
352
353 let parts = UndefinedStruct::new(&struct_type10);
354 let test_struct = SMBiosOnBoardDeviceInformation::new(&parts);
355
356 println!("{:?}", test_struct);
357
358 assert_eq!(test_struct.number_of_devices(), 1);
359
360 let mut iterator = test_struct.onboard_device_iterator().into_iter();
361
362 let item = iterator.next().unwrap();
363
364 assert_eq!(
365 item.description().to_string(),
366 " To Be Filled By O.E.M.".to_string()
367 );
368
369 let device_type = item.device_type().unwrap();
370 assert_eq!(device_type.type_of_device(), TypeOfDevice::Video);
371 assert_eq!(device_type.status(), DeviceStatus::Enabled);
372
373 assert!(iterator.next().is_none());
374 }
375}