xref: /openbmc/dbus-sensors/src/ipmb/IpmbSDRSensor.cpp (revision 73f6cdcfb63720f47822bbf626bb9ae72b791263)
1d7be555eSGeorge Liu #include "IpmbSDRSensor.hpp"
2d7be555eSGeorge Liu 
3*73f6cdcfSGeorge Liu #include <phosphor-logging/lg2.hpp>
4d7be555eSGeorge Liu #include <sdbusplus/asio/connection.hpp>
5d7be555eSGeorge Liu 
6d7be555eSGeorge Liu #include <cmath>
7d7be555eSGeorge Liu #include <cstddef>
8d7be555eSGeorge Liu #include <cstdint>
9d7be555eSGeorge Liu #include <functional>
10d7be555eSGeorge Liu #include <memory>
11d7be555eSGeorge Liu #include <string>
12d7be555eSGeorge Liu #include <utility>
13d7be555eSGeorge Liu #include <vector>
14d7be555eSGeorge Liu 
15d7be555eSGeorge Liu const constexpr char* ipmbService = "xyz.openbmc_project.Ipmi.Channel.Ipmb";
16d7be555eSGeorge Liu const constexpr char* ipmbDbusPath = "/xyz/openbmc_project/Ipmi/Channel/Ipmb";
17d7be555eSGeorge Liu const constexpr char* ipmbInterface = "org.openbmc.Ipmb";
18d7be555eSGeorge Liu const constexpr char* ipmbMethod = "sendRequest";
19d7be555eSGeorge Liu static constexpr uint8_t lun = 0;
20d7be555eSGeorge Liu 
IpmbSDRDevice(std::shared_ptr<sdbusplus::asio::connection> & dbusConnection,uint8_t cmdAddr)21d7be555eSGeorge Liu IpmbSDRDevice::IpmbSDRDevice(
22d7be555eSGeorge Liu     std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
23d7be555eSGeorge Liu     uint8_t cmdAddr) :
24d7be555eSGeorge Liu     commandAddress(cmdAddr << 2), hostIndex(cmdAddr + 1), conn(dbusConnection)
25d7be555eSGeorge Liu {}
26d7be555eSGeorge Liu 
validateStatus(boost::system::error_code ec,const IpmbMethodType & response,int hostIndex)27d7be555eSGeorge Liu bool validateStatus(boost::system::error_code ec,
28d7be555eSGeorge Liu                     const IpmbMethodType& response, int hostIndex)
29d7be555eSGeorge Liu {
30d7be555eSGeorge Liu     if (ec)
31d7be555eSGeorge Liu     {
32d7be555eSGeorge Liu         return false;
33d7be555eSGeorge Liu     }
34d7be555eSGeorge Liu 
35d7be555eSGeorge Liu     const int status = std::get<0>(response);
36d7be555eSGeorge Liu     if (status != 0)
37d7be555eSGeorge Liu     {
38*73f6cdcfSGeorge Liu         lg2::error("Error reading from IPMB SDR for host '{INDEX}'", "INDEX",
39*73f6cdcfSGeorge Liu                    hostIndex);
40d7be555eSGeorge Liu         return false;
41d7be555eSGeorge Liu     }
42d7be555eSGeorge Liu     return true;
43d7be555eSGeorge Liu }
44d7be555eSGeorge Liu 
45d7be555eSGeorge Liu /* This function will store the record count of the SDR sensors for each IPMB
46d7be555eSGeorge Liu  * bus */
getSDRRepositoryInfo()47d7be555eSGeorge Liu void IpmbSDRDevice::getSDRRepositoryInfo()
48d7be555eSGeorge Liu {
49d7be555eSGeorge Liu     std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();
50d7be555eSGeorge Liu 
51d7be555eSGeorge Liu     conn->async_method_call(
52d7be555eSGeorge Liu         [weakRef](boost::system::error_code ec,
53d7be555eSGeorge Liu                   const IpmbMethodType& response) {
54d7be555eSGeorge Liu             auto self = weakRef.lock();
55d7be555eSGeorge Liu             if (!self)
56d7be555eSGeorge Liu             {
57d7be555eSGeorge Liu                 return;
58d7be555eSGeorge Liu             }
59d7be555eSGeorge Liu 
60d7be555eSGeorge Liu             auto status = std::bind_front(validateStatus, ec, response);
61d7be555eSGeorge Liu             if (!status(self->hostIndex))
62d7be555eSGeorge Liu             {
63d7be555eSGeorge Liu                 return;
64d7be555eSGeorge Liu             }
65d7be555eSGeorge Liu 
66d7be555eSGeorge Liu             const std::vector<uint8_t>& data = std::get<5>(response);
67d7be555eSGeorge Liu             const size_t sdrInfoDataSize = 14;
68d7be555eSGeorge Liu 
69d7be555eSGeorge Liu             if (data.size() < sdrInfoDataSize)
70d7be555eSGeorge Liu             {
71*73f6cdcfSGeorge Liu                 lg2::error(
72*73f6cdcfSGeorge Liu                     "IPMB Get SDR Repository Info data is empty for host '{INDEX}'",
73*73f6cdcfSGeorge Liu                     "INDEX", self->hostIndex);
74d7be555eSGeorge Liu                 return;
75d7be555eSGeorge Liu             }
76d7be555eSGeorge Liu 
77d7be555eSGeorge Liu             constexpr uint8_t recordCountLSB = 1;
78d7be555eSGeorge Liu             constexpr uint8_t recordCountMSB = 2;
79d7be555eSGeorge Liu 
80d7be555eSGeorge Liu             uint16_t recordCount = (data[recordCountMSB] << 8) |
81d7be555eSGeorge Liu                                    data[recordCountLSB];
82d7be555eSGeorge Liu 
83d7be555eSGeorge Liu             self->reserveSDRRepository(recordCount);
84d7be555eSGeorge Liu         },
85d7be555eSGeorge Liu         ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
86d7be555eSGeorge Liu         sdr::netfnStorageReq, lun, sdr::cmdStorageGetSdrInfo, sdrCommandData);
87d7be555eSGeorge Liu }
88d7be555eSGeorge Liu 
89d7be555eSGeorge Liu /* This function will store the reserve ID for each IPMB bus index */
reserveSDRRepository(uint16_t recordCount)90d7be555eSGeorge Liu void IpmbSDRDevice::reserveSDRRepository(uint16_t recordCount)
91d7be555eSGeorge Liu {
92d7be555eSGeorge Liu     std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();
93d7be555eSGeorge Liu 
94d7be555eSGeorge Liu     conn->async_method_call(
95d7be555eSGeorge Liu         [weakRef, recordCount](boost::system::error_code ec,
96d7be555eSGeorge Liu                                const IpmbMethodType& response) {
97d7be555eSGeorge Liu             auto self = weakRef.lock();
98d7be555eSGeorge Liu             if (!self)
99d7be555eSGeorge Liu             {
100d7be555eSGeorge Liu                 return;
101d7be555eSGeorge Liu             }
102d7be555eSGeorge Liu 
103d7be555eSGeorge Liu             auto status = std::bind_front(validateStatus, ec, response);
104d7be555eSGeorge Liu             if (!status(self->hostIndex))
105d7be555eSGeorge Liu             {
106d7be555eSGeorge Liu                 return;
107d7be555eSGeorge Liu             }
108d7be555eSGeorge Liu 
109d7be555eSGeorge Liu             const std::vector<uint8_t>& data = std::get<5>(response);
110d7be555eSGeorge Liu             const size_t sdrReserveDataSize = 2;
111d7be555eSGeorge Liu 
112d7be555eSGeorge Liu             if (data.size() < sdrReserveDataSize)
113d7be555eSGeorge Liu             {
114*73f6cdcfSGeorge Liu                 lg2::error(
115*73f6cdcfSGeorge Liu                     "IPMB SDR Reserve Repository data is empty for host '{INDEX}'",
116*73f6cdcfSGeorge Liu                     "INDEX", self->hostIndex);
117d7be555eSGeorge Liu                 return;
118d7be555eSGeorge Liu             }
119d7be555eSGeorge Liu             uint8_t resrvIDLSB = data[0];
120d7be555eSGeorge Liu             uint8_t resrvIDMSB = data[1];
121d7be555eSGeorge Liu 
122d7be555eSGeorge Liu             self->getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
123d7be555eSGeorge Liu         },
124d7be555eSGeorge Liu         ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
125d7be555eSGeorge Liu         sdr::netfnStorageReq, lun, sdr::cmdStorageReserveSdr, sdrCommandData);
126d7be555eSGeorge Liu }
127d7be555eSGeorge Liu 
128d7be555eSGeorge Liu /* This function will read all the information related to the sensor
129d7be555eSGeorge Liu  * such as name, threshold value, unit, device address, SDR type */
getSDRSensorData(uint16_t recordCount,uint8_t resrvIDLSB,uint8_t resrvIDMSB)130d7be555eSGeorge Liu void IpmbSDRDevice::getSDRSensorData(uint16_t recordCount, uint8_t resrvIDLSB,
131d7be555eSGeorge Liu                                      uint8_t resrvIDMSB)
132d7be555eSGeorge Liu {
133d7be555eSGeorge Liu     std::weak_ptr<IpmbSDRDevice> weakRef = weak_from_this();
134d7be555eSGeorge Liu 
135d7be555eSGeorge Liu     uint8_t loopCount = sdr::perCountByte * iCnt;
136d7be555eSGeorge Liu     std::vector<uint8_t> commandData = {resrvIDLSB,      resrvIDMSB,
137d7be555eSGeorge Liu                                         nextRecordIDLSB, nextRecordIDMSB,
138d7be555eSGeorge Liu                                         loopCount,       sdr::perCountByte};
139d7be555eSGeorge Liu 
140d7be555eSGeorge Liu     conn->async_method_call(
141d7be555eSGeorge Liu         [weakRef, recordCount, resrvIDLSB, resrvIDMSB](
142d7be555eSGeorge Liu             boost::system::error_code ec, const IpmbMethodType& response) {
143d7be555eSGeorge Liu             auto self = weakRef.lock();
144d7be555eSGeorge Liu             if (!self)
145d7be555eSGeorge Liu             {
146d7be555eSGeorge Liu                 return;
147d7be555eSGeorge Liu             }
148d7be555eSGeorge Liu 
149d7be555eSGeorge Liu             auto status = std::bind_front(validateStatus, ec, response);
150d7be555eSGeorge Liu             if (!status(self->hostIndex))
151d7be555eSGeorge Liu             {
152d7be555eSGeorge Liu                 return;
153d7be555eSGeorge Liu             }
154d7be555eSGeorge Liu 
155d7be555eSGeorge Liu             const std::vector<uint8_t>& data = std::get<5>(response);
156d7be555eSGeorge Liu             const size_t sdrSensorDataSize = 18;
157d7be555eSGeorge Liu 
158d7be555eSGeorge Liu             if (data.size() < sdrSensorDataSize)
159d7be555eSGeorge Liu             {
160*73f6cdcfSGeorge Liu                 lg2::error("IPMB SDR sensor data is empty for host '{INDEX}'",
161*73f6cdcfSGeorge Liu                            "INDEX", self->hostIndex);
162d7be555eSGeorge Liu                 return;
163d7be555eSGeorge Liu             }
164d7be555eSGeorge Liu 
165d7be555eSGeorge Liu             self->handleSDRData(data, recordCount, resrvIDLSB, resrvIDMSB);
166d7be555eSGeorge Liu         },
167d7be555eSGeorge Liu         ipmbService, ipmbDbusPath, ipmbInterface, ipmbMethod, commandAddress,
168d7be555eSGeorge Liu         sdr::netfnStorageReq, lun, sdr::cmdStorageGetSdr, commandData);
169d7be555eSGeorge Liu }
170d7be555eSGeorge Liu 
171d7be555eSGeorge Liu /* This function will handle the sensor data received by IPMB response */
handleSDRData(const std::vector<uint8_t> & data,uint16_t recordCount,uint8_t resrvIDLSB,uint8_t resrvIDMSB)172d7be555eSGeorge Liu void IpmbSDRDevice::handleSDRData(const std::vector<uint8_t>& data,
173d7be555eSGeorge Liu                                   uint16_t recordCount, uint8_t resrvIDLSB,
174d7be555eSGeorge Liu                                   uint8_t resrvIDMSB)
175d7be555eSGeorge Liu {
176d7be555eSGeorge Liu     sdrData.insert(sdrData.end(), data.begin(), data.end());
177d7be555eSGeorge Liu 
178d7be555eSGeorge Liu     /* dataLength represents the size of data for SDR types */
179d7be555eSGeorge Liu     uint8_t dataLength = sdrData[sdr::dataLengthByte] + sdr::dataLengthByte + 1;
180d7be555eSGeorge Liu 
181d7be555eSGeorge Liu     /*  If sdrData size is less than dataLength, it will call getSDRSensorData
182d7be555eSGeorge Liu      *  function recursively till all the data is received.
183d7be555eSGeorge Liu      */
184d7be555eSGeorge Liu     if (sdrData.size() < dataLength)
185d7be555eSGeorge Liu     {
186d7be555eSGeorge Liu         iCnt++;
187d7be555eSGeorge Liu         getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
188d7be555eSGeorge Liu     }
189d7be555eSGeorge Liu     else
190d7be555eSGeorge Liu     {
191d7be555eSGeorge Liu         /*  After all the data is received, it is passed to checkSDRData
192d7be555eSGeorge Liu          *  function. Next sensor record ID is stored based on the previous
193d7be555eSGeorge Liu          *  record ID. Vector of sdrData is cleared to store next sensor data.
194d7be555eSGeorge Liu          *  validRecordCount is incremented and getSDRSensorData function is
195d7be555eSGeorge Liu          *  called to proceed with next set of sensors.
196d7be555eSGeorge Liu          */
197d7be555eSGeorge Liu         checkSDRData(sdrData, dataLength);
198d7be555eSGeorge Liu         iCnt = 0;
199d7be555eSGeorge Liu         nextRecordIDLSB = sdrData[sdr::sdrNxtRecLSB];
200d7be555eSGeorge Liu         nextRecordIDMSB = sdrData[sdr::sdrNxtRecMSB];
201d7be555eSGeorge Liu         sdrData.clear();
202d7be555eSGeorge Liu 
203d7be555eSGeorge Liu         if (validRecordCount == recordCount)
204d7be555eSGeorge Liu         {
205d7be555eSGeorge Liu             /* Once all the sensors are read and recordCount matched, it will
206d7be555eSGeorge Liu              * return. */
207d7be555eSGeorge Liu             nextRecordIDLSB = 0;
208d7be555eSGeorge Liu             nextRecordIDMSB = 0;
209d7be555eSGeorge Liu             return;
210d7be555eSGeorge Liu         }
211d7be555eSGeorge Liu         validRecordCount++;
212d7be555eSGeorge Liu         getSDRSensorData(recordCount, resrvIDLSB, resrvIDMSB);
213d7be555eSGeorge Liu     }
214d7be555eSGeorge Liu }
215d7be555eSGeorge Liu 
216d7be555eSGeorge Liu /* This function will convert the SDR sensor data such as sensor unit, name, ID,
217d7be555eSGeorge Liu  * type from decimal to readable format */
checkSDRData(std::vector<uint8_t> & sdrDataBytes,uint8_t dataLength) const218d7be555eSGeorge Liu void IpmbSDRDevice::checkSDRData(std::vector<uint8_t>& sdrDataBytes,
219d7be555eSGeorge Liu                                  uint8_t dataLength) const
220d7be555eSGeorge Liu {
221d7be555eSGeorge Liu     if (sdrDataBytes.size() < dataLength)
222d7be555eSGeorge Liu     {
223d7be555eSGeorge Liu         return;
224d7be555eSGeorge Liu     }
225d7be555eSGeorge Liu 
226d7be555eSGeorge Liu     /* sdrType represents the SDR Type (Byte 5) such as 1, 2, 3 */
227d7be555eSGeorge Liu     uint8_t sdrType = sdrDataBytes[sdr::sdrType];
228d7be555eSGeorge Liu     if (sdrType != static_cast<uint8_t>(SDRType::sdrType01))
229d7be555eSGeorge Liu     {
230d7be555eSGeorge Liu         return;
231d7be555eSGeorge Liu     }
232d7be555eSGeorge Liu 
233d7be555eSGeorge Liu     /*  dataLen represents the data length (Byte 6) for SDR sensor */
234d7be555eSGeorge Liu     int dataLen = sdrDataBytes[sdr::dataLengthByte];
235d7be555eSGeorge Liu 
236d7be555eSGeorge Liu     /* iStrLen represents the length of the sensor name for SDR Type 1 */
237d7be555eSGeorge Liu     const uint8_t sdrLenBit = 0x1F;
238d7be555eSGeorge Liu     int strLen = (sdrDataBytes[sdrtype01::nameLengthByte]) & (sdrLenBit);
239d7be555eSGeorge Liu 
240d7be555eSGeorge Liu     /* iStrAddr represents the starting byte (Byte 56) for SDR sensor name */
241d7be555eSGeorge Liu     int strAddr = dataLen + ((dataLen / (sdr::perCountByte)) * 4) -
242d7be555eSGeorge Liu                   (strLen - 1);
243d7be555eSGeorge Liu 
244d7be555eSGeorge Liu     /* Below for loop will convert the bytes to string and form a sensor name */
245d7be555eSGeorge Liu 
246d7be555eSGeorge Liu     std::string tempName(sdrDataBytes.begin() + strAddr,
247d7be555eSGeorge Liu                          sdrDataBytes.begin() + strAddr + strLen);
248d7be555eSGeorge Liu 
249d7be555eSGeorge Liu     checkSDRType01Threshold(sdrDataBytes, (hostIndex - 1), tempName);
250d7be555eSGeorge Liu }
251d7be555eSGeorge Liu 
252d7be555eSGeorge Liu /* This function will convert the raw value of threshold for each sensor */
checkSDRType01Threshold(std::vector<uint8_t> & sdrDataBytes,int busIndex,std::string tempName)253d7be555eSGeorge Liu void IpmbSDRDevice::checkSDRType01Threshold(std::vector<uint8_t>& sdrDataBytes,
254d7be555eSGeorge Liu                                             int busIndex, std::string tempName)
255d7be555eSGeorge Liu {
256d7be555eSGeorge Liu     const uint8_t bitShiftMsb = 2;
257d7be555eSGeorge Liu     const uint8_t sdrThresAccess = 0x0C;
258d7be555eSGeorge Liu 
259d7be555eSGeorge Liu     /* linear represents the sensor's linearization (Byte 27) */
260d7be555eSGeorge Liu     uint8_t linear = sdrDataBytes[sdrtype01::sdrLinearByte];
261d7be555eSGeorge Liu     if (linear != 0)
262d7be555eSGeorge Liu     {
263d7be555eSGeorge Liu         return;
264d7be555eSGeorge Liu     }
265d7be555eSGeorge Liu 
266d7be555eSGeorge Liu     /* sdrSensCapability (Byte 13) and(&) with sdrThresAccess(0x0C) will declare
267d7be555eSGeorge Liu      * whether threshold is present for each sensor */
268d7be555eSGeorge Liu     int threshold = (sdrDataBytes[sdrtype01::sensorCapability]) &
269d7be555eSGeorge Liu                     (sdrThresAccess);
270d7be555eSGeorge Liu 
271d7be555eSGeorge Liu     /* mData        - 10 bits
272d7be555eSGeorge Liu      * mDataByte    - Byte 28 - 8 bits LSB
273d7be555eSGeorge Liu      * mTolDataByte - Byte 29 - 2 bits MSB [7-6]
274d7be555eSGeorge Liu      */
275d7be555eSGeorge Liu     uint16_t mData =
276d7be555eSGeorge Liu         ((sdrDataBytes[sdrtype01::mTolDataByte] & 0xC0) << bitShiftMsb) |
277d7be555eSGeorge Liu         sdrDataBytes[sdrtype01::mDataByte];
278d7be555eSGeorge Liu 
279d7be555eSGeorge Liu     /* bData        - 10 bits
280d7be555eSGeorge Liu      * bDataByte    - Byte 30 - 8 bits LSB
281d7be555eSGeorge Liu      * bAcuDataByte - Byte 31 - 2 bits MSB [7-6]
282d7be555eSGeorge Liu      */
283d7be555eSGeorge Liu     uint16_t bData =
284d7be555eSGeorge Liu         ((sdrDataBytes[sdrtype01::bAcuDataByte] & 0xC0) << bitShiftMsb) |
285d7be555eSGeorge Liu         sdrDataBytes[sdrtype01::bDataByte];
286d7be555eSGeorge Liu 
287d7be555eSGeorge Liu     /* rbExpDataByte (Byte 33) represents the exponent value
288d7be555eSGeorge Liu      *  Bit [3-0] - B Exponent 2's complement signed bit.
289d7be555eSGeorge Liu      *  Bit [7-4] - R Exponent 2's complement signed bit.
290d7be555eSGeorge Liu      */
291d7be555eSGeorge Liu     int8_t bExpVal = sdrDataBytes[sdrtype01::rbExpDataByte] & 0xF;
292d7be555eSGeorge Liu     if (bExpVal > 7)
293d7be555eSGeorge Liu     {
294d7be555eSGeorge Liu         bExpVal = (~bExpVal + 1) & 0xF;
295d7be555eSGeorge Liu     }
296d7be555eSGeorge Liu 
297d7be555eSGeorge Liu     /* Shifting the data to right by 4, since rExpVal has 4 bits from 4 to 7 in
298d7be555eSGeorge Liu      * byte 33 */
299d7be555eSGeorge Liu     int8_t rExpVal = (sdrDataBytes[sdrtype01::rbExpDataByte] >> 4) & 0xF;
300d7be555eSGeorge Liu     if (rExpVal > 7)
301d7be555eSGeorge Liu     {
302d7be555eSGeorge Liu         rExpVal = (~rExpVal + 1) & 0xF;
303d7be555eSGeorge Liu         rExpVal = -rExpVal;
304d7be555eSGeorge Liu     }
305d7be555eSGeorge Liu 
306d7be555eSGeorge Liu     /* Sensor Threshold Reading Conversion
307d7be555eSGeorge Liu      *
308d7be555eSGeorge Liu      *  Y = ((Mx + (B * 10^K1)) * (10^K2))
309d7be555eSGeorge Liu      *
310d7be555eSGeorge Liu      *  X  - Raw value of threshold
311d7be555eSGeorge Liu      *  M  - mData Value
312d7be555eSGeorge Liu      *  B  - bData Value
313d7be555eSGeorge Liu      *  K1 - Signed Exponent of bExpVal
314d7be555eSGeorge Liu      *  K2 - Signed Exponent of rExpVal
315d7be555eSGeorge Liu      */
316d7be555eSGeorge Liu 
317d7be555eSGeorge Liu     double bDataVal = bData * pow(10, bExpVal);
318d7be555eSGeorge Liu     double expVal = pow(10, rExpVal);
319d7be555eSGeorge Liu 
320d7be555eSGeorge Liu     double thresUpCri =
321d7be555eSGeorge Liu         sensorValCalculation(mData, bDataVal, expVal,
322d7be555eSGeorge Liu                              sdrDataBytes[sdrtype01::upperCriticalThreshold]);
323d7be555eSGeorge Liu     double thresLoCri =
324d7be555eSGeorge Liu         sensorValCalculation(mData, bDataVal, expVal,
325d7be555eSGeorge Liu                              sdrDataBytes[sdrtype01::lowerCriticalThreshold]);
326d7be555eSGeorge Liu 
327d7be555eSGeorge Liu     struct SensorInfo temp;
328d7be555eSGeorge Liu 
329d7be555eSGeorge Liu     temp.sensorReadName = std::move(tempName);
330d7be555eSGeorge Liu     temp.sensorUnit = sdrDataBytes[sdrtype01::sdrUnitType];
331d7be555eSGeorge Liu 
332d7be555eSGeorge Liu     temp.thresUpperCri = thresUpCri;
333d7be555eSGeorge Liu     temp.thresLowerCri = thresLoCri;
334d7be555eSGeorge Liu 
335d7be555eSGeorge Liu     temp.sensorNumber = sdrDataBytes[sdr::sdrSensorNum];
336d7be555eSGeorge Liu     temp.sensCap = threshold;
337d7be555eSGeorge Liu 
338d7be555eSGeorge Liu     sensorRecord[busIndex].emplace_back(std::move(temp));
339d7be555eSGeorge Liu 
340d7be555eSGeorge Liu     SensorValConversion val = {mData, bDataVal, expVal,
341d7be555eSGeorge Liu                                sdrDataBytes[sdrtype01::sdrNegHandle]};
342d7be555eSGeorge Liu 
343d7be555eSGeorge Liu     sensorValRecord[busIndex][sdrDataBytes[sdr::sdrSensorNum]] = val;
344d7be555eSGeorge Liu }
345d7be555eSGeorge Liu 
346d7be555eSGeorge Liu /* This function will calculate the sensor's threshold value */
sensorValCalculation(uint16_t mValue,double bValue,double expValue,double value)347d7be555eSGeorge Liu double IpmbSDRDevice::sensorValCalculation(uint16_t mValue, double bValue,
348d7be555eSGeorge Liu                                            double expValue, double value)
349d7be555eSGeorge Liu {
350d7be555eSGeorge Liu     double sensorValue = ((mValue * value) + bValue) * expValue;
351d7be555eSGeorge Liu     return sensorValue;
352d7be555eSGeorge Liu }
353