1use crate::core::{strings::*, UndefinedStruct};
2use crate::SMBiosStruct;
3use serde::{ser::SerializeStruct, Serialize, Serializer};
4use std::fmt;
5
6pub struct SMBiosTemperatureProbe<'a> {
13 parts: &'a UndefinedStruct,
14}
15
16impl<'a> SMBiosStruct<'a> for SMBiosTemperatureProbe<'a> {
17 const STRUCT_TYPE: u8 = 28u8;
18
19 fn new(parts: &'a UndefinedStruct) -> Self {
20 Self { parts }
21 }
22
23 fn parts(&self) -> &'a UndefinedStruct {
24 self.parts
25 }
26}
27
28impl<'a> SMBiosTemperatureProbe<'a> {
29 pub fn description(&self) -> SMBiosString {
33 self.parts.get_field_string(0x04)
34 }
35
36 pub fn location_and_status(&self) -> Option<TemperatureProbeLocationAndStatus> {
41 self.parts
42 .get_field_byte(0x05)
43 .map(|raw| TemperatureProbeLocationAndStatus::from(raw))
44 }
45
46 pub fn maximum_value(&self) -> Option<ProbeTemperature> {
52 self.parts
53 .get_field_word(0x06)
54 .map(|raw| ProbeTemperature::from(raw))
55 }
56
57 pub fn minimum_value(&self) -> Option<ProbeTemperature> {
63 self.parts
64 .get_field_word(0x08)
65 .map(|raw| ProbeTemperature::from(raw))
66 }
67
68 pub fn resolution(&self) -> Option<TemperatureProbeResolution> {
74 self.parts
75 .get_field_word(0x0A)
76 .map(|raw| TemperatureProbeResolution::from(raw))
77 }
78
79 pub fn tolerance(&self) -> Option<ProbeTemperature> {
85 self.parts
86 .get_field_word(0x0C)
87 .map(|raw| ProbeTemperature::from(raw))
88 }
89
90 pub fn accuracy(&self) -> Option<TemperatureProbeAccuracy> {
96 self.parts
97 .get_field_word(0x0E)
98 .map(|raw| TemperatureProbeAccuracy::from(raw))
99 }
100
101 pub fn oem_defined(&self) -> Option<u32> {
105 self.parts.get_field_dword(0x10)
106 }
107
108 pub fn nominal_value(&self) -> Option<ProbeTemperature> {
114 self.parts
115 .get_field_word(0x14)
116 .map(|raw| ProbeTemperature::from(raw))
117 }
118}
119
120impl fmt::Debug for SMBiosTemperatureProbe<'_> {
121 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
122 fmt.debug_struct(std::any::type_name::<SMBiosTemperatureProbe<'_>>())
123 .field("header", &self.parts.header)
124 .field("description", &self.description())
125 .field("location_and_status", &self.location_and_status())
126 .field("maximum_value", &self.maximum_value())
127 .field("minimum_value", &self.minimum_value())
128 .field("resolution", &self.resolution())
129 .field("tolerance", &self.tolerance())
130 .field("accuracy", &self.accuracy())
131 .field("oem_defined", &self.oem_defined())
132 .field("nominal_value", &self.nominal_value())
133 .finish()
134 }
135}
136
137impl Serialize for SMBiosTemperatureProbe<'_> {
138 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
139 where
140 S: Serializer,
141 {
142 let mut state = serializer.serialize_struct("SMBiosTemperatureProbe", 10)?;
143 state.serialize_field("header", &self.parts.header)?;
144 state.serialize_field("description", &self.description())?;
145 state.serialize_field("location_and_status", &self.location_and_status())?;
146 state.serialize_field("maximum_value", &self.maximum_value())?;
147 state.serialize_field("minimum_value", &self.minimum_value())?;
148 state.serialize_field("resolution", &self.resolution())?;
149 state.serialize_field("tolerance", &self.tolerance())?;
150 state.serialize_field("accuracy", &self.accuracy())?;
151 state.serialize_field("oem_defined", &self.oem_defined())?;
152 state.serialize_field("nominal_value", &self.nominal_value())?;
153 state.end()
154 }
155}
156
157#[derive(PartialEq, Eq)]
159pub struct TemperatureProbeLocationAndStatus {
160 pub raw: u8,
162}
163
164impl From<u8> for TemperatureProbeLocationAndStatus {
165 fn from(raw: u8) -> Self {
166 TemperatureProbeLocationAndStatus { raw }
167 }
168}
169
170impl TemperatureProbeLocationAndStatus {
171 pub fn location(&self) -> TemperatureProbeLocation {
173 TemperatureProbeLocation::from(self.raw)
174 }
175
176 pub fn status(&self) -> TemperatureProbeStatus {
178 TemperatureProbeStatus::from(self.raw)
179 }
180}
181
182impl fmt::Debug for TemperatureProbeLocationAndStatus {
183 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
184 fmt.debug_struct(std::any::type_name::<TemperatureProbeLocationAndStatus>())
185 .field("raw", &self.raw)
186 .field("location", &self.location())
187 .field("status", &self.status())
188 .finish()
189 }
190}
191
192impl Serialize for TemperatureProbeLocationAndStatus {
193 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
194 where
195 S: Serializer,
196 {
197 let mut state = serializer.serialize_struct("TemperatureProbeLocationAndStatus", 3)?;
198 state.serialize_field("raw", &self.raw)?;
199 state.serialize_field("location", &self.location())?;
200 state.serialize_field("status", &self.status())?;
201 state.end()
202 }
203}
204
205#[derive(Serialize, Debug, PartialEq, Eq)]
207pub enum TemperatureProbeStatus {
208 Other,
210 Unknown,
212 OK,
214 NonCritical,
216 Critical,
218 NonRecoverable,
220 None,
222}
223
224impl From<u8> for TemperatureProbeStatus {
225 fn from(raw: u8) -> Self {
226 match raw & 0b1110_0000 {
227 0b0000_0000 => TemperatureProbeStatus::None,
228 0b0010_0000 => TemperatureProbeStatus::Other,
229 0b0100_0000 => TemperatureProbeStatus::Unknown,
230 0b0110_0000 => TemperatureProbeStatus::OK,
231 0b1000_0000 => TemperatureProbeStatus::NonCritical,
232 0b1010_0000 => TemperatureProbeStatus::Critical,
233 0b1100_0000 => TemperatureProbeStatus::NonRecoverable,
234 0b1110_0000 => TemperatureProbeStatus::None,
235 _ => panic!("impossible value"),
236 }
237 }
238}
239
240#[derive(Serialize, Debug, PartialEq, Eq)]
242pub enum TemperatureProbeLocation {
243 Other,
245 Unknown,
247 Processor,
249 Disk,
251 PeripheralBay,
253 SystemManagementModule,
255 Motherboard,
257 MemoryModule,
259 ProcessorModule,
261 PowerUnit,
263 AddInCard,
265 FrontPanelBoard,
267 BackPanelBoard,
269 PowerSystemBoard,
271 DriveBackPlane,
273 None,
275}
276
277impl From<u8> for TemperatureProbeLocation {
278 fn from(raw: u8) -> Self {
279 match raw & 0b0001_1111 {
280 0b0000_0001 => TemperatureProbeLocation::Other,
281 0b0000_0010 => TemperatureProbeLocation::Unknown,
282 0b0000_0011 => TemperatureProbeLocation::Processor,
283 0b0000_0100 => TemperatureProbeLocation::Disk,
284 0b0000_0101 => TemperatureProbeLocation::PeripheralBay,
285 0b0000_0110 => TemperatureProbeLocation::SystemManagementModule,
286 0b0000_0111 => TemperatureProbeLocation::Motherboard,
287 0b0000_1000 => TemperatureProbeLocation::MemoryModule,
288 0b0000_1001 => TemperatureProbeLocation::ProcessorModule,
289 0b0000_1010 => TemperatureProbeLocation::PowerUnit,
290 0b0000_1011 => TemperatureProbeLocation::AddInCard,
291 0b0000_1100 => TemperatureProbeLocation::FrontPanelBoard,
292 0b0000_1101 => TemperatureProbeLocation::BackPanelBoard,
293 0b0000_1110 => TemperatureProbeLocation::PowerSystemBoard,
294 0b0000_1111 => TemperatureProbeLocation::DriveBackPlane,
295 _ => TemperatureProbeLocation::None,
296 }
297 }
298}
299
300#[derive(Serialize, Debug)]
302pub enum ProbeTemperature {
303 OneTenthDegreesC(u16),
305 Unknown,
307}
308
309impl From<u16> for ProbeTemperature {
310 fn from(raw: u16) -> Self {
311 match raw {
312 0x8000 => ProbeTemperature::Unknown,
313 _ => ProbeTemperature::OneTenthDegreesC(raw),
314 }
315 }
316}
317
318#[derive(Serialize, Debug)]
320pub enum TemperatureProbeResolution {
321 OneOneThousandthDegreesC(u16),
323 Unknown,
325}
326
327impl From<u16> for TemperatureProbeResolution {
328 fn from(raw: u16) -> Self {
329 match raw {
330 0x8000 => TemperatureProbeResolution::Unknown,
331 _ => TemperatureProbeResolution::OneOneThousandthDegreesC(raw),
332 }
333 }
334}
335
336#[derive(Serialize, Debug)]
338pub enum TemperatureProbeAccuracy {
339 OneOneHundredthDegreesC(u16),
341 Unknown,
343}
344
345impl From<u16> for TemperatureProbeAccuracy {
346 fn from(raw: u16) -> Self {
347 match raw {
348 0x8000 => TemperatureProbeAccuracy::Unknown,
349 _ => TemperatureProbeAccuracy::OneOneHundredthDegreesC(raw),
350 }
351 }
352}
353
354#[cfg(test)]
355mod tests {
356 use super::*;
357
358 #[test]
359 fn unit_test() {
360 let struct_type28 = vec![
361 0x1C, 0x16, 0x2A, 0x00, 0x01, 0x67, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80,
362 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x4C, 0x4D, 0x37, 0x38, 0x41, 0x00,
363 0x00,
364 ];
365
366 let parts = UndefinedStruct::new(&struct_type28);
367 let test_struct = SMBiosTemperatureProbe::new(&parts);
368
369 assert_eq!(test_struct.description().to_string(), "LM78A".to_string());
370 assert_eq!(
371 test_struct.location_and_status(),
372 Some(TemperatureProbeLocationAndStatus::from(103))
373 );
374 match test_struct.maximum_value().unwrap() {
375 ProbeTemperature::OneTenthDegreesC(_) => panic!("expected unknown"),
376 ProbeTemperature::Unknown => (),
377 }
378 match test_struct.minimum_value().unwrap() {
379 ProbeTemperature::OneTenthDegreesC(_) => panic!("expected unknown"),
380 ProbeTemperature::Unknown => (),
381 }
382 match test_struct.resolution().unwrap() {
383 TemperatureProbeResolution::OneOneThousandthDegreesC(_) => panic!("expected unknown"),
384 TemperatureProbeResolution::Unknown => (),
385 }
386 match test_struct.tolerance().unwrap() {
387 ProbeTemperature::OneTenthDegreesC(_) => panic!("expected unknown"),
388 ProbeTemperature::Unknown => (),
389 }
390 match test_struct.accuracy().unwrap() {
391 TemperatureProbeAccuracy::OneOneHundredthDegreesC(_) => panic!("expected unknown"),
392 TemperatureProbeAccuracy::Unknown => (),
393 }
394 assert_eq!(test_struct.oem_defined(), Some(0));
395 match test_struct.nominal_value().unwrap() {
396 ProbeTemperature::OneTenthDegreesC(_) => panic!("expected unknown"),
397 ProbeTemperature::Unknown => (),
398 }
399 }
400}