1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "chre/platform/slpi/see/see_cal_helper.h"
18 
19 #include "chre/core/sensor_type_helpers.h"
20 #include "chre/platform/assert.h"
21 #include "chre/platform/log.h"
22 #include "chre/platform/slpi/see/see_helper.h"
23 #include "chre/util/lock_guard.h"
24 #include "chre/util/macros.h"
25 
26 namespace chre {
27 
applyCalibration(uint8_t sensorType,const float input[3],float output[3]) const28 void SeeCalHelper::applyCalibration(uint8_t sensorType, const float input[3],
29                                     float output[3]) const {
30   bool applied = false;
31   size_t index = getCalIndexFromSensorType(sensorType);
32   if (index < ARRAY_SIZE(mCalInfo)) {
33     LockGuard<Mutex> lock(mMutex);
34 
35     // TODO: Support compensation matrix and scaling factor calibration
36     if (mCalInfo[index].cal.hasBias) {
37       for (size_t i = 0; i < 3; i++) {
38         output[i] = input[i] - mCalInfo[index].cal.bias[i];
39       }
40       applied = true;
41     }
42   }
43 
44   if (!applied) {
45     for (size_t i = 0; i < 3; i++) {
46       output[i] = input[i];
47     }
48   }
49 }
50 
getBias(uint8_t sensorType,struct chreSensorThreeAxisData * biasData) const51 bool SeeCalHelper::getBias(uint8_t sensorType,
52                            struct chreSensorThreeAxisData *biasData) const {
53   CHRE_ASSERT(biasData != nullptr);
54 
55   bool success = false;
56   if (biasData != nullptr) {
57     size_t index = getCalIndexFromSensorType(sensorType);
58     if (index < ARRAY_SIZE(mCalInfo)) {
59       LockGuard<Mutex> lock(mMutex);
60 
61       if (mCalInfo[index].cal.hasBias) {
62         biasData->header.baseTimestamp = mCalInfo[index].cal.timestamp;
63         biasData->header.readingCount = 1;
64         biasData->header.accuracy = mCalInfo[index].cal.accuracy;
65         biasData->header.reserved = 0;
66 
67         for (size_t i = 0; i < 3; i++) {
68           biasData->readings[0].bias[i] = mCalInfo[index].cal.bias[i];
69         }
70         biasData->readings[0].timestampDelta = 0;
71         success = true;
72       }
73     }
74   }
75 
76   return success;
77 }
78 
areCalUpdatesEnabled(const sns_std_suid & suid) const79 bool SeeCalHelper::areCalUpdatesEnabled(const sns_std_suid &suid) const {
80   size_t index = getCalIndexFromSuid(suid);
81   if (index < ARRAY_SIZE(mCalInfo)) {
82     return mCalInfo[index].enabled;
83   }
84   return false;
85 }
86 
configureCalUpdates(const sns_std_suid & suid,bool enable,SeeHelper & helper)87 bool SeeCalHelper::configureCalUpdates(const sns_std_suid &suid, bool enable,
88                                        SeeHelper &helper) {
89   bool success = false;
90 
91   size_t index = getCalIndexFromSuid(suid);
92   if (index >= ARRAY_SIZE(mCalInfo)) {
93     CHRE_ASSERT(false);
94   } else if ((mCalInfo[index].enabled == enable) ||
95              helper.configureOnChangeSensor(suid, enable)) {
96     success = true;
97     mCalInfo[index].enabled = enable;
98   }
99 
100   return success;
101 }
102 
getCalSuidFromSensorType(uint8_t sensorType) const103 const sns_std_suid *SeeCalHelper::getCalSuidFromSensorType(
104     uint8_t sensorType) const {
105   // Mutex not needed, SUID is not modified after init
106   size_t calIndex = getCalIndexFromSensorType(sensorType);
107   if (calIndex < ARRAY_SIZE(mCalInfo) && mCalInfo[calIndex].suid.has_value()) {
108     return &mCalInfo[calIndex].suid.value();
109   }
110   return nullptr;
111 }
112 
findCalibrationSensors(SeeHelper & seeHelper)113 bool SeeCalHelper::findCalibrationSensors(SeeHelper &seeHelper) {
114   bool success = true;
115 
116   DynamicVector<sns_std_suid> suids;
117   for (size_t i = 0; i < ARRAY_SIZE(mCalInfo); i++) {
118     const char *calType = getDataTypeForCalSensorIndex(i);
119     if (!seeHelper.findSuidSync(calType, &suids)) {
120       success = false;
121       LOGE("Failed to find sensor '%s'", calType);
122     } else {
123       mCalInfo[i].suid = suids[0];
124     }
125   }
126 
127   return success;
128 }
129 
updateCalibration(const sns_std_suid & suid,bool hasBias,float bias[3],bool hasScale,float scale[3],bool hasMatrix,float matrix[9],uint8_t accuracy,uint64_t timestamp)130 void SeeCalHelper::updateCalibration(const sns_std_suid &suid, bool hasBias,
131                                      float bias[3], bool hasScale,
132                                      float scale[3], bool hasMatrix,
133                                      float matrix[9], uint8_t accuracy,
134                                      uint64_t timestamp) {
135   size_t index = getCalIndexFromSuid(suid);
136   if (index < ARRAY_SIZE(mCalInfo)) {
137     LockGuard<Mutex> lock(mMutex);
138     SeeCalData &calData = mCalInfo[index].cal;
139 
140     calData.hasBias = hasBias;
141     if (hasBias) {
142       memcpy(calData.bias, bias, sizeof(calData.bias));
143     }
144 
145     calData.hasScale = hasScale;
146     if (hasScale) {
147       memcpy(calData.scale, scale, sizeof(calData.scale));
148     }
149 
150     calData.hasMatrix = hasMatrix;
151     if (hasMatrix) {
152       memcpy(calData.matrix, matrix, sizeof(calData.matrix));
153     }
154 
155     calData.accuracy = accuracy;
156     calData.timestamp = timestamp;
157   }
158 }
159 
getSensorTypeFromSuid(const sns_std_suid & suid,uint8_t * sensorType) const160 bool SeeCalHelper::getSensorTypeFromSuid(const sns_std_suid &suid,
161                                          uint8_t *sensorType) const {
162   size_t calSensorIndex = getCalIndexFromSuid(suid);
163   bool found = true;
164   switch (static_cast<SeeCalSensor>(calSensorIndex)) {
165 #ifdef CHRE_ENABLE_ACCEL_CAL
166     case SeeCalSensor::AccelCal:
167       *sensorType = CHRE_SENSOR_TYPE_ACCELEROMETER;
168       break;
169 #endif  // CHRE_ENABLE_ACCEL_CAL
170     case SeeCalSensor::GyroCal:
171       *sensorType = CHRE_SENSOR_TYPE_GYROSCOPE;
172       break;
173     case SeeCalSensor::MagCal:
174       *sensorType = CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD;
175       break;
176     default:
177       // Don't assert here as SEE may send us calibration updates for other
178       // sensors even if CHRE doesn't request them.
179       found = false;
180       break;
181   }
182   return found;
183 }
184 
getCalIndexFromSensorType(uint8_t sensorType)185 size_t SeeCalHelper::getCalIndexFromSensorType(uint8_t sensorType) {
186   SeeCalSensor index;
187   switch (sensorType) {
188 #ifdef CHRE_ENABLE_ACCEL_CAL
189     case CHRE_SENSOR_TYPE_ACCELEROMETER:
190       index = SeeCalSensor::AccelCal;
191       break;
192 #endif  // CHRE_ENABLE_ACCEL_CAL
193     case CHRE_SENSOR_TYPE_GYROSCOPE:
194       index = SeeCalSensor::GyroCal;
195       break;
196     case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
197       index = SeeCalSensor::MagCal;
198       break;
199     default:
200       index = SeeCalSensor::NumCalSensors;
201   }
202   return static_cast<size_t>(index);
203 }
204 
getDataTypeForCalSensorIndex(size_t calSensorIndex)205 const char *SeeCalHelper::getDataTypeForCalSensorIndex(size_t calSensorIndex) {
206   switch (static_cast<SeeCalSensor>(calSensorIndex)) {
207 #ifdef CHRE_ENABLE_ACCEL_CAL
208     case SeeCalSensor::AccelCal:
209       return "accel_cal";
210 #endif  // CHRE_ENABLE_ACCEL_CAL
211     case SeeCalSensor::GyroCal:
212       return "gyro_cal";
213     case SeeCalSensor::MagCal:
214       return "mag_cal";
215     default:
216       CHRE_ASSERT(false);
217   }
218   return nullptr;
219 }
220 
getCalIndexFromSuid(const sns_std_suid & suid) const221 size_t SeeCalHelper::getCalIndexFromSuid(const sns_std_suid &suid) const {
222   size_t i = 0;
223   for (; i < ARRAY_SIZE(mCalInfo); i++) {
224     if (mCalInfo[i].suid.has_value() &&
225         suidsMatch(suid, mCalInfo[i].suid.value())) {
226       break;
227     }
228   }
229   return i;
230 }
231 
232 }  // namespace chre
233