xref: /openbmc/phosphor-host-ipmid/sensorhandler.hpp (revision f7452cb646898a90f85d95208721d714c8b1709e)
1 #pragma once
2 
3 #include <stdint.h>
4 
5 #include <ipmid/api.hpp>
6 #include <ipmid/types.hpp>
7 
8 #include <exception>
9 
10 /**
11  * @enum device_type
12  * IPMI FRU device types
13  */
14 enum device_type
15 {
16     IPMI_PHYSICAL_FRU = 0x00,
17     IPMI_LOGICAL_FRU = 0x80,
18 };
19 
20 // Discrete sensor types.
21 enum ipmi_sensor_types
22 {
23     IPMI_SENSOR_TEMP = 0x01,
24     IPMI_SENSOR_VOLTAGE = 0x02,
25     IPMI_SENSOR_CURRENT = 0x03,
26     IPMI_SENSOR_FAN = 0x04,
27     IPMI_SENSOR_TPM = 0xCC,
28 };
29 
30 /** @brief Custom exception for reading sensors that are not funcitonal.
31  */
32 struct SensorFunctionalError : public std::exception
33 {
whatSensorFunctionalError34     const char* what() const noexcept
35     {
36         return "Sensor not functional";
37     }
38 };
39 
40 #define MAX_DBUS_PATH 128
41 struct dbus_interface_t
42 {
43     uint8_t sensornumber;
44     uint8_t sensortype;
45 
46     char bus[MAX_DBUS_PATH];
47     char path[MAX_DBUS_PATH];
48     char interface[MAX_DBUS_PATH];
49 };
50 
51 struct PlatformEventRequest
52 {
53     uint8_t eventMessageRevision;
54     uint8_t sensorType;
55     uint8_t sensorNumber;
56     uint8_t eventDirectionType;
57     uint8_t data[3];
58 };
59 
60 static constexpr const char* ipmiSELPath = "/xyz/openbmc_project/Logging/IPMI";
61 static constexpr const char* ipmiSELAddInterface =
62     "xyz.openbmc_project.Logging.IPMI";
63 static const std::string ipmiSELAddMessage = "IPMI generated SEL Entry";
64 
65 static constexpr int selSystemEventSizeWith3Bytes = 8;
66 static constexpr int selSystemEventSizeWith2Bytes = 7;
67 static constexpr int selSystemEventSizeWith1Bytes = 6;
68 static constexpr int selIPMBEventSize = 7;
69 static constexpr uint8_t directionMask = 0x80;
70 static constexpr uint8_t byte3EnableMask = 0x30;
71 static constexpr uint8_t byte2EnableMask = 0xC0;
72 
73 int set_sensor_dbus_state_s(uint8_t, const char*, const char*);
74 int set_sensor_dbus_state_y(uint8_t, const char*, const uint8_t);
75 int find_openbmc_path(uint8_t, dbus_interface_t*);
76 
77 ipmi_ret_t ipmi_sen_get_sdr(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
78                             ipmi_request_t request, ipmi_response_t response,
79                             ipmi_data_len_t data_len, ipmi_context_t context);
80 
81 ipmi::RspType<uint16_t> ipmiSensorReserveSdr();
82 
83 static const uint16_t FRU_RECORD_ID_START = 256;
84 static const uint16_t ENTITY_RECORD_ID_START = 512;
85 static const uint8_t SDR_VERSION = 0x51;
86 static const uint16_t END_OF_RECORD = 0xFFFF;
87 static const uint8_t LENGTH_MASK = 0x1F;
88 
89 /**
90  * Get SDR Info
91  */
92 
93 namespace get_sdr_info
94 {
95 namespace request
96 {
97 // Note: for some reason the ipmi_request_t appears to be the
98 // raw value for this call.
get_count(void * req)99 inline bool get_count(void* req)
100 {
101     return (bool)((uint64_t)(req) & 1);
102 }
103 } // namespace request
104 } // namespace get_sdr_info
105 
106 /**
107  * Get SDR
108  */
109 namespace get_sdr
110 {
111 
112 struct GetSdrReq
113 {
114     uint8_t reservation_id_lsb;
115     uint8_t reservation_id_msb;
116     uint8_t record_id_lsb;
117     uint8_t record_id_msb;
118     uint8_t offset;
119     uint8_t bytes_to_read;
120 } __attribute__((packed));
121 
122 namespace request
123 {
124 
get_reservation_id(GetSdrReq * req)125 inline uint16_t get_reservation_id(GetSdrReq* req)
126 {
127     return (req->reservation_id_lsb + (req->reservation_id_msb << 8));
128 };
129 
get_record_id(GetSdrReq * req)130 inline uint16_t get_record_id(GetSdrReq* req)
131 {
132     return (req->record_id_lsb + (req->record_id_msb << 8));
133 };
134 
135 } // namespace request
136 
137 // Response
138 struct GetSdrResp
139 {
140     uint8_t next_record_id_lsb;
141     uint8_t next_record_id_msb;
142     uint8_t record_data[64];
143 } __attribute__((packed));
144 
145 namespace response
146 {
147 
set_next_record_id(uint16_t next,GetSdrResp * resp)148 inline void set_next_record_id(uint16_t next, GetSdrResp* resp)
149 {
150     resp->next_record_id_lsb = next & 0xff;
151     resp->next_record_id_msb = (next >> 8) & 0xff;
152 };
153 
154 } // namespace response
155 
156 // Record header
157 struct SensorDataRecordHeader
158 {
159     uint8_t record_id_lsb;
160     uint8_t record_id_msb;
161     uint8_t sdr_version;
162     uint8_t record_type;
163     uint8_t record_length; // Length not counting the header
164 } __attribute__((packed));
165 
166 namespace header
167 {
168 
set_record_id(int id,SensorDataRecordHeader * hdr)169 inline void set_record_id(int id, SensorDataRecordHeader* hdr)
170 {
171     hdr->record_id_lsb = (id & 0xFF);
172     hdr->record_id_msb = (id >> 8) & 0xFF;
173 };
174 
175 } // namespace header
176 
177 enum SensorDataRecordType
178 {
179     SENSOR_DATA_FULL_RECORD = 0x1,
180     SENSOR_DATA_COMPACT_RECORD = 0x2,
181     SENSOR_DATA_EVENT_RECORD = 0x3,
182     SENSOR_DATA_ENTITY_RECORD = 0x8,
183     SENSOR_DATA_FRU_RECORD = 0x11,
184     SENSOR_DATA_MGMT_CTRL_LOCATOR = 0x12,
185 };
186 
187 // Record key
188 struct SensorDataRecordKey
189 {
190     uint8_t owner_id;
191     uint8_t owner_lun;
192     uint8_t sensor_number;
193 } __attribute__((packed));
194 
195 /** @struct SensorDataFruRecordKey
196  *
197  *  FRU Device Locator Record(key) - SDR Type 11
198  */
199 struct SensorDataFruRecordKey
200 {
201     uint8_t deviceAddress;
202     uint8_t fruID;
203     uint8_t accessLun;
204     uint8_t channelNumber;
205 } __attribute__((packed));
206 
207 /** @struct SensorDataEntityRecordKey
208  *
209  *  Entity Association Record(key) - SDR Type 8
210  */
211 struct SensorDataEntityRecordKey
212 {
213     uint8_t containerEntityId;
214     uint8_t containerEntityInstance;
215     uint8_t flags;
216     uint8_t entityId1;
217     uint8_t entityInstance1;
218 } __attribute__((packed));
219 
220 namespace key
221 {
222 
223 static constexpr uint8_t listOrRangeBit = 7;
224 static constexpr uint8_t linkedBit = 6;
225 
set_owner_id_ipmb(SensorDataRecordKey * key)226 inline void set_owner_id_ipmb(SensorDataRecordKey* key)
227 {
228     key->owner_id &= ~0x01;
229 };
230 
set_owner_id_system_sw(SensorDataRecordKey * key)231 inline void set_owner_id_system_sw(SensorDataRecordKey* key)
232 {
233     key->owner_id |= 0x01;
234 };
235 
set_owner_id_bmc(SensorDataRecordKey * key)236 inline void set_owner_id_bmc(SensorDataRecordKey* key)
237 {
238     key->owner_id |= 0x20;
239 };
240 
set_owner_id_address(uint8_t addr,SensorDataRecordKey * key)241 inline void set_owner_id_address(uint8_t addr, SensorDataRecordKey* key)
242 {
243     key->owner_id &= 0x01;
244     key->owner_id |= addr << 1;
245 };
246 
set_owner_lun(uint8_t lun,SensorDataRecordKey * key)247 inline void set_owner_lun(uint8_t lun, SensorDataRecordKey* key)
248 {
249     key->owner_lun &= ~0x03;
250     key->owner_lun |= (lun & 0x03);
251 };
252 
set_owner_lun_channel(uint8_t channel,SensorDataRecordKey * key)253 inline void set_owner_lun_channel(uint8_t channel, SensorDataRecordKey* key)
254 {
255     key->owner_lun &= 0x0f;
256     key->owner_lun |= ((channel & 0xf) << 4);
257 };
258 
set_flags(bool isList,bool isLinked,SensorDataEntityRecordKey * key)259 inline void set_flags(bool isList, bool isLinked,
260                       SensorDataEntityRecordKey* key)
261 {
262     key->flags = 0x00;
263     if (!isList)
264         key->flags |= 1 << listOrRangeBit;
265 
266     if (isLinked)
267         key->flags |= 1 << linkedBit;
268 };
269 
270 } // namespace key
271 
272 /** @struct GetSensorThresholdsResponse
273  *
274  *  Response structure for Get Sensor Thresholds command
275  */
276 struct GetSensorThresholdsResponse
277 {
278     uint8_t validMask;           //!< valid mask
279     uint8_t lowerNonCritical;    //!< lower non-critical threshold
280     uint8_t lowerCritical;       //!< lower critical threshold
281     uint8_t lowerNonRecoverable; //!< lower non-recoverable threshold
282     uint8_t upperNonCritical;    //!< upper non-critical threshold
283     uint8_t upperCritical;       //!< upper critical threshold
284     uint8_t upperNonRecoverable; //!< upper non-recoverable threshold
285 } __attribute__((packed));
286 
287 // Body - full record
288 #define FULL_RECORD_ID_STR_MAX_LENGTH 16
289 
290 static const int FRU_RECORD_DEVICE_ID_MAX_LENGTH = 16;
291 
292 struct SensorDataFullRecordBody
293 {
294     uint8_t entity_id;
295     uint8_t entity_instance;
296     uint8_t sensor_initialization;
297     uint8_t sensor_capabilities; // no macro support
298     uint8_t sensor_type;
299     uint8_t event_reading_type;
300     uint8_t supported_assertions[2];          // no macro support
301     uint8_t supported_deassertions[2];        // no macro support
302     uint8_t discrete_reading_setting_mask[2]; // no macro support
303     uint8_t sensor_units_1;
304     uint8_t sensor_units_2_base;
305     uint8_t sensor_units_3_modifier;
306     uint8_t linearization;
307     uint8_t m_lsb;
308     uint8_t m_msb_and_tolerance;
309     uint8_t b_lsb;
310     uint8_t b_msb_and_accuracy_lsb;
311     uint8_t accuracy_and_sensor_direction;
312     uint8_t r_b_exponents;
313     uint8_t analog_characteristic_flags; // no macro support
314     uint8_t nominal_reading;
315     uint8_t normal_max;
316     uint8_t normal_min;
317     uint8_t sensor_max;
318     uint8_t sensor_min;
319     uint8_t upper_nonrecoverable_threshold;
320     uint8_t upper_critical_threshold;
321     uint8_t upper_noncritical_threshold;
322     uint8_t lower_nonrecoverable_threshold;
323     uint8_t lower_critical_threshold;
324     uint8_t lower_noncritical_threshold;
325     uint8_t positive_threshold_hysteresis;
326     uint8_t negative_threshold_hysteresis;
327     uint16_t reserved;
328     uint8_t oem_reserved;
329     uint8_t id_string_info;
330     char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
331 } __attribute__((packed));
332 
333 /** @struct SensorDataCompactRecord
334  *
335  *  Compact Sensor Record(body) - SDR Type 2
336  */
337 struct SensorDataCompactRecordBody
338 {
339     uint8_t entity_id;
340     uint8_t entity_instance;
341     uint8_t sensor_initialization;
342     uint8_t sensor_capabilities; // no macro support
343     uint8_t sensor_type;
344     uint8_t event_reading_type;
345     uint8_t supported_assertions[2];          // no macro support
346     uint8_t supported_deassertions[2];        // no macro support
347     uint8_t discrete_reading_setting_mask[2]; // no macro support
348     uint8_t sensor_units_1;
349     uint8_t sensor_units_2_base;
350     uint8_t sensor_units_3_modifier;
351     uint8_t record_sharing[2];
352     uint8_t positive_threshold_hysteresis;
353     uint8_t negative_threshold_hysteresis;
354     uint8_t reserved[3];
355     uint8_t oem_reserved;
356     uint8_t id_string_info;
357     char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
358 } __attribute__((packed));
359 
360 /** @struct SensorDataEventRecord
361  *
362  *  Event Only Sensor Record(body) - SDR Type 3
363  */
364 struct SensorDataEventRecordBody
365 {
366     uint8_t entity_id;
367     uint8_t entity_instance;
368     uint8_t sensor_type;
369     uint8_t event_reading_type;
370     uint8_t sensor_record_sharing_1;
371     uint8_t sensor_record_sharing_2;
372     uint8_t reserved;
373     uint8_t oem_reserved;
374     uint8_t id_string_info;
375     char id_string[FULL_RECORD_ID_STR_MAX_LENGTH];
376 } __attribute__((packed));
377 
378 /** @struct SensorDataFruRecordBody
379  *
380  *  FRU Device Locator Record(body) - SDR Type 11
381  */
382 struct SensorDataFruRecordBody
383 {
384     uint8_t reserved;
385     uint8_t deviceType;
386     uint8_t deviceTypeModifier;
387     uint8_t entityID;
388     uint8_t entityInstance;
389     uint8_t oem;
390     uint8_t deviceIDLen;
391     char deviceID[FRU_RECORD_DEVICE_ID_MAX_LENGTH];
392 } __attribute__((packed));
393 
394 /** @struct SensorDataEntityRecordBody
395  *
396  *  Entity Association Record(body) - SDR Type 8
397  */
398 struct SensorDataEntityRecordBody
399 {
400     uint8_t entityId2;
401     uint8_t entityInstance2;
402     uint8_t entityId3;
403     uint8_t entityInstance3;
404     uint8_t entityId4;
405     uint8_t entityInstance4;
406 } __attribute__((packed));
407 
408 namespace body
409 {
410 
set_entity_instance_number(uint8_t n,SensorDataFullRecordBody * body)411 inline void set_entity_instance_number(uint8_t n,
412                                        SensorDataFullRecordBody* body)
413 {
414     body->entity_instance &= 1 << 7;
415     body->entity_instance |= (n & ~(1 << 7));
416 };
set_entity_physical_entity(SensorDataFullRecordBody * body)417 inline void set_entity_physical_entity(SensorDataFullRecordBody* body)
418 {
419     body->entity_instance &= ~(1 << 7);
420 };
set_entity_logical_container(SensorDataFullRecordBody * body)421 inline void set_entity_logical_container(SensorDataFullRecordBody* body)
422 {
423     body->entity_instance |= 1 << 7;
424 };
425 
sensor_scanning_state(bool enabled,SensorDataFullRecordBody * body)426 inline void sensor_scanning_state(bool enabled, SensorDataFullRecordBody* body)
427 {
428     if (enabled)
429     {
430         body->sensor_initialization |= 1 << 0;
431     }
432     else
433     {
434         body->sensor_initialization &= ~(1 << 0);
435     };
436 };
event_generation_state(bool enabled,SensorDataFullRecordBody * body)437 inline void event_generation_state(bool enabled, SensorDataFullRecordBody* body)
438 {
439     if (enabled)
440     {
441         body->sensor_initialization |= 1 << 1;
442     }
443     else
444     {
445         body->sensor_initialization &= ~(1 << 1);
446     }
447 };
init_types_state(bool enabled,SensorDataFullRecordBody * body)448 inline void init_types_state(bool enabled, SensorDataFullRecordBody* body)
449 {
450     if (enabled)
451     {
452         body->sensor_initialization |= 1 << 2;
453     }
454     else
455     {
456         body->sensor_initialization &= ~(1 << 2);
457     }
458 };
init_hyst_state(bool enabled,SensorDataFullRecordBody * body)459 inline void init_hyst_state(bool enabled, SensorDataFullRecordBody* body)
460 {
461     if (enabled)
462     {
463         body->sensor_initialization |= 1 << 3;
464     }
465     else
466     {
467         body->sensor_initialization &= ~(1 << 3);
468     }
469 };
init_thresh_state(bool enabled,SensorDataFullRecordBody * body)470 inline void init_thresh_state(bool enabled, SensorDataFullRecordBody* body)
471 {
472     if (enabled)
473     {
474         body->sensor_initialization |= 1 << 4;
475     }
476     else
477     {
478         body->sensor_initialization &= ~(1 << 4);
479     }
480 };
init_events_state(bool enabled,SensorDataFullRecordBody * body)481 inline void init_events_state(bool enabled, SensorDataFullRecordBody* body)
482 {
483     if (enabled)
484     {
485         body->sensor_initialization |= 1 << 5;
486     }
487     else
488     {
489         body->sensor_initialization &= ~(1 << 5);
490     }
491 };
init_scanning_state(bool enabled,SensorDataFullRecordBody * body)492 inline void init_scanning_state(bool enabled, SensorDataFullRecordBody* body)
493 {
494     if (enabled)
495     {
496         body->sensor_initialization |= 1 << 6;
497     }
498     else
499     {
500         body->sensor_initialization &= ~(1 << 6);
501     }
502 };
init_settable_state(bool enabled,SensorDataFullRecordBody * body)503 inline void init_settable_state(bool enabled, SensorDataFullRecordBody* body)
504 {
505     if (enabled)
506     {
507         body->sensor_initialization |= 1 << 7;
508     }
509     else
510     {
511         body->sensor_initialization &= ~(1 << 7);
512     }
513 };
514 
set_percentage(SensorDataFullRecordBody * body)515 inline void set_percentage(SensorDataFullRecordBody* body)
516 {
517     body->sensor_units_1 |= 1 << 0;
518 };
unset_percentage(SensorDataFullRecordBody * body)519 inline void unset_percentage(SensorDataFullRecordBody* body)
520 {
521     body->sensor_units_1 &= ~(1 << 0);
522 };
set_modifier_operation(uint8_t op,SensorDataFullRecordBody * body)523 inline void set_modifier_operation(uint8_t op, SensorDataFullRecordBody* body)
524 {
525     body->sensor_units_1 &= ~(3 << 1);
526     body->sensor_units_1 |= (op & 0x3) << 1;
527 };
set_rate_unit(uint8_t unit,SensorDataFullRecordBody * body)528 inline void set_rate_unit(uint8_t unit, SensorDataFullRecordBody* body)
529 {
530     body->sensor_units_1 &= ~(7 << 3);
531     body->sensor_units_1 |= (unit & 0x7) << 3;
532 };
set_analog_data_format(uint8_t format,SensorDataFullRecordBody * body)533 inline void set_analog_data_format(uint8_t format,
534                                    SensorDataFullRecordBody* body)
535 {
536     body->sensor_units_1 &= ~(3 << 6);
537     body->sensor_units_1 |= (format & 0x3) << 6;
538 };
539 
set_m(uint16_t m,SensorDataFullRecordBody * body)540 inline void set_m(uint16_t m, SensorDataFullRecordBody* body)
541 {
542     body->m_lsb = m & 0xff;
543     body->m_msb_and_tolerance &= ~(3 << 6);
544     body->m_msb_and_tolerance |= ((m & (3 << 8)) >> 2);
545 };
set_tolerance(uint8_t tol,SensorDataFullRecordBody * body)546 inline void set_tolerance(uint8_t tol, SensorDataFullRecordBody* body)
547 {
548     body->m_msb_and_tolerance &= ~0x3f;
549     body->m_msb_and_tolerance |= tol & 0x3f;
550 };
551 
set_b(uint16_t b,SensorDataFullRecordBody * body)552 inline void set_b(uint16_t b, SensorDataFullRecordBody* body)
553 {
554     body->b_lsb = b & 0xff;
555     body->b_msb_and_accuracy_lsb &= ~(3 << 6);
556     body->b_msb_and_accuracy_lsb |= ((b & (3 << 8)) >> 2);
557 };
set_accuracy(uint16_t acc,SensorDataFullRecordBody * body)558 inline void set_accuracy(uint16_t acc, SensorDataFullRecordBody* body)
559 {
560     // bottom 6 bits
561     body->b_msb_and_accuracy_lsb &= ~0x3f;
562     body->b_msb_and_accuracy_lsb |= acc & 0x3f;
563     // top 4 bits
564     body->accuracy_and_sensor_direction &= 0x0f;
565     body->accuracy_and_sensor_direction |= ((acc >> 6) & 0xf) << 4;
566 };
set_accuracy_exp(uint8_t exp,SensorDataFullRecordBody * body)567 inline void set_accuracy_exp(uint8_t exp, SensorDataFullRecordBody* body)
568 {
569     body->accuracy_and_sensor_direction &= ~(3 << 2);
570     body->accuracy_and_sensor_direction |= (exp & 3) << 2;
571 };
set_sensor_dir(uint8_t dir,SensorDataFullRecordBody * body)572 inline void set_sensor_dir(uint8_t dir, SensorDataFullRecordBody* body)
573 {
574     body->accuracy_and_sensor_direction &= ~(3 << 0);
575     body->accuracy_and_sensor_direction |= (dir & 3);
576 };
577 
set_b_exp(uint8_t exp,SensorDataFullRecordBody * body)578 inline void set_b_exp(uint8_t exp, SensorDataFullRecordBody* body)
579 {
580     body->r_b_exponents &= 0xf0;
581     body->r_b_exponents |= exp & 0x0f;
582 };
set_r_exp(uint8_t exp,SensorDataFullRecordBody * body)583 inline void set_r_exp(uint8_t exp, SensorDataFullRecordBody* body)
584 {
585     body->r_b_exponents &= 0x0f;
586     body->r_b_exponents |= (exp & 0x0f) << 4;
587 };
588 
set_id_strlen(uint8_t len,SensorDataFullRecordBody * body)589 inline void set_id_strlen(uint8_t len, SensorDataFullRecordBody* body)
590 {
591     body->id_string_info &= ~(0x1f);
592     body->id_string_info |= len & 0x1f;
593 };
set_id_strlen(uint8_t len,SensorDataEventRecordBody * body)594 inline void set_id_strlen(uint8_t len, SensorDataEventRecordBody* body)
595 {
596     body->id_string_info &= ~(0x1f);
597     body->id_string_info |= len & 0x1f;
598 };
get_id_strlen(SensorDataFullRecordBody * body)599 inline uint8_t get_id_strlen(SensorDataFullRecordBody* body)
600 {
601     return body->id_string_info & 0x1f;
602 };
set_id_type(uint8_t type,SensorDataFullRecordBody * body)603 inline void set_id_type(uint8_t type, SensorDataFullRecordBody* body)
604 {
605     body->id_string_info &= ~(3 << 6);
606     body->id_string_info |= (type & 0x3) << 6;
607 };
set_id_type(uint8_t type,SensorDataEventRecordBody * body)608 inline void set_id_type(uint8_t type, SensorDataEventRecordBody* body)
609 {
610     body->id_string_info &= ~(3 << 6);
611     body->id_string_info |= (type & 0x3) << 6;
612 };
613 
set_device_id_strlen(uint8_t len,SensorDataFruRecordBody * body)614 inline void set_device_id_strlen(uint8_t len, SensorDataFruRecordBody* body)
615 {
616     body->deviceIDLen &= ~(LENGTH_MASK);
617     body->deviceIDLen |= len & LENGTH_MASK;
618 };
619 
get_device_id_strlen(SensorDataFruRecordBody * body)620 inline uint8_t get_device_id_strlen(SensorDataFruRecordBody* body)
621 {
622     return body->deviceIDLen & LENGTH_MASK;
623 };
624 
set_readable_mask(uint8_t mask,SensorDataFullRecordBody * body)625 inline void set_readable_mask(uint8_t mask, SensorDataFullRecordBody* body)
626 {
627     body->discrete_reading_setting_mask[1] = mask & 0x3F;
628 }
629 
630 } // namespace body
631 
632 // More types contained in section 43.17 Sensor Unit Type Codes,
633 // IPMI spec v2 rev 1.1
634 enum SensorUnitTypeCodes
635 {
636     SENSOR_UNIT_UNSPECIFIED = 0,
637     SENSOR_UNIT_DEGREES_C = 1,
638     SENSOR_UNIT_VOLTS = 4,
639     SENSOR_UNIT_AMPERES = 5,
640     SENSOR_UNIT_WATTS = 6,
641     SENSOR_UNIT_JOULES = 7,
642     SENSOR_UNIT_RPM = 18,
643     SENSOR_UNIT_METERS = 34,
644     SENSOR_UNIT_REVOLUTIONS = 41,
645 };
646 
647 struct SensorDataFullRecord
648 {
649     SensorDataRecordHeader header;
650     SensorDataRecordKey key;
651     SensorDataFullRecordBody body;
652 } __attribute__((packed));
653 
654 /** @struct SensorDataComapactRecord
655  *
656  *  Compact Sensor Record - SDR Type 2
657  */
658 struct SensorDataCompactRecord
659 {
660     SensorDataRecordHeader header;
661     SensorDataRecordKey key;
662     SensorDataCompactRecordBody body;
663 } __attribute__((packed));
664 
665 /** @struct SensorDataEventRecord
666  *
667  *  Event Only Sensor Record - SDR Type 3
668  */
669 struct SensorDataEventRecord
670 {
671     SensorDataRecordHeader header;
672     SensorDataRecordKey key;
673     SensorDataEventRecordBody body;
674 } __attribute__((packed));
675 
676 /** @struct SensorDataFruRecord
677  *
678  *  FRU Device Locator Record - SDR Type 11
679  */
680 struct SensorDataFruRecord
681 {
682     SensorDataRecordHeader header;
683     SensorDataFruRecordKey key;
684     SensorDataFruRecordBody body;
685 } __attribute__((packed));
686 
687 /** @struct SensorDataEntityRecord
688  *
689  *  Entity Association Record - SDR Type 8
690  */
691 struct SensorDataEntityRecord
692 {
693     SensorDataRecordHeader header;
694     SensorDataEntityRecordKey key;
695     SensorDataEntityRecordBody body;
696 } __attribute__((packed));
697 
698 } // namespace get_sdr
699 
700 namespace ipmi
701 {
702 
703 namespace sensor
704 {
705 
706 /**
707  * @brief Map offset to the corresponding bit in the assertion byte.
708  *
709  * The discrete sensors support up to 14 states. 0-7 offsets are stored in one
710  * byte and offsets 8-14 in the second byte.
711  *
712  * @param[in] offset - offset number.
713  * @param[in/out] resp - get sensor reading response.
714  */
setOffset(uint8_t offset,ipmi::sensor::GetSensorResponse * resp)715 inline void setOffset(uint8_t offset, ipmi::sensor::GetSensorResponse* resp)
716 {
717     if (offset > 7)
718     {
719         resp->discreteReadingSensorStates |= 1 << (offset - 8);
720     }
721     else
722     {
723         resp->thresholdLevelsStates |= 1 << offset;
724     }
725 }
726 
727 /**
728  * @brief Set the reading field in the response.
729  *
730  * @param[in] offset - offset number.
731  * @param[in/out] resp - get sensor reading response.
732  */
setReading(uint8_t value,ipmi::sensor::GetSensorResponse * resp)733 inline void setReading(uint8_t value, ipmi::sensor::GetSensorResponse* resp)
734 {
735     resp->reading = value;
736 }
737 
738 /**
739  * @brief Map the value to the assertion bytes. The assertion states are stored
740  *        in 2 bytes.
741  *
742  * @param[in] value - value to mapped to the assertion byte.
743  * @param[in/out] resp - get sensor reading response.
744  */
setAssertionBytes(uint16_t value,ipmi::sensor::GetSensorResponse * resp)745 inline void setAssertionBytes(uint16_t value,
746                               ipmi::sensor::GetSensorResponse* resp)
747 {
748     resp->thresholdLevelsStates = static_cast<uint8_t>(value & 0x00FF);
749     resp->discreteReadingSensorStates = static_cast<uint8_t>(value >> 8);
750 }
751 
752 /**
753  * @brief Set the scanning enabled bit in the response.
754  *
755  * @param[in/out] resp - get sensor reading response.
756  */
enableScanning(ipmi::sensor::GetSensorResponse * resp)757 inline void enableScanning(ipmi::sensor::GetSensorResponse* resp)
758 {
759     resp->readingOrStateUnavailable = false;
760     resp->scanningEnabled = true;
761     resp->allEventMessagesEnabled = false;
762 }
763 
764 } // namespace sensor
765 
766 } // namespace ipmi
767