ash.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (C) 2017 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. #include <cinttypes>
  17. extern "C" {
  18. #include "fixed_point.h"
  19. #include "sns_smgr_api_v01.h"
  20. } // extern "C"
  21. #include "ash_api/ash.h"
  22. #include "chre/platform/assert.h"
  23. #include "chre/platform/log.h"
  24. #include "chre/platform/memory.h"
  25. #include "chre/platform/slpi/smgr/smgr_client.h"
  26. #include "chre_api/chre/sensor.h"
  27. using chre::getSmrHelper;
  28. using chre::getSensorServiceSmrClientHandle;
  29. using chre::MakeUnique;
  30. using chre::MakeUniqueZeroFill;
  31. using chre::memoryAlloc;
  32. using chre::memoryFree;
  33. using chre::UniquePtr;
  34. namespace {
  35. //! The constant to convert magnetometer readings from uT in Android to Gauss
  36. //! in SMGR.
  37. constexpr float kGaussPerMicroTesla = 0.01f;
  38. /**
  39. * @param sensorType One of the CHRE_SENSOR_TYPE_* constants.
  40. * @return true if runtime sensor calibration is supported on this platform.
  41. */
  42. bool isCalibrationSupported(uint8_t sensorType) {
  43. switch (sensorType) {
  44. case CHRE_SENSOR_TYPE_ACCELEROMETER:
  45. case CHRE_SENSOR_TYPE_GYROSCOPE:
  46. case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
  47. return true;
  48. default:
  49. return false;
  50. }
  51. }
  52. /**
  53. * @param sensorType One of the CHRE_SENSOR_TYPE_* constants.
  54. * @return The sensor ID of the sensor type as defined in the SMGR API.
  55. */
  56. uint8_t getSensorId(uint8_t sensorType) {
  57. switch (sensorType) {
  58. case CHRE_SENSOR_TYPE_ACCELEROMETER:
  59. return SNS_SMGR_ID_ACCEL_V01;
  60. case CHRE_SENSOR_TYPE_GYROSCOPE:
  61. return SNS_SMGR_ID_GYRO_V01;
  62. case CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD:
  63. return SNS_SMGR_ID_MAG_V01;
  64. default:
  65. return 0;
  66. }
  67. }
  68. /**
  69. * Populates the calibration request mesasge.
  70. *
  71. * @param sensorType One of the CHRE_SENSOR_TYPE_* constants.
  72. * @param calInfo The sensor calibraion info supplied by the user.
  73. * @param calRequest The SMGR cal request message to be populated.
  74. */
  75. void populateCalRequest(uint8_t sensorType, const ashCalInfo *calInfo,
  76. sns_smgr_sensor_cal_req_msg_v01 *calRequest) {
  77. CHRE_ASSERT(calInfo);
  78. CHRE_ASSERT(calRequest);
  79. calRequest->usage = SNS_SMGR_CAL_DYNAMIC_V01;
  80. calRequest->SensorId = getSensorId(sensorType);
  81. calRequest->DataType = SNS_SMGR_DATA_TYPE_PRIMARY_V01;
  82. // Convert from micro Tesla to Gauss for magnetometer bias
  83. float scaling = 1.0f;
  84. if (sensorType == CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD) {
  85. scaling = kGaussPerMicroTesla;
  86. }
  87. // Convert from Android to SMGR's NED coordinate and invert the sign as SMGR
  88. // defines Sc = CM * (Su + Bias) in sns_rh_calibrate_cm_and_bias().
  89. calRequest->ZeroBias_len = 3;
  90. calRequest->ZeroBias[0] = FX_FLTTOFIX_Q16(-calInfo->bias[1] * scaling);
  91. calRequest->ZeroBias[1] = FX_FLTTOFIX_Q16(-calInfo->bias[0] * scaling);
  92. calRequest->ZeroBias[2] = FX_FLTTOFIX_Q16(calInfo->bias[2] * scaling);
  93. // ScaleFactor will be over-written by compensation matrix.
  94. calRequest->ScaleFactor_len = 3;
  95. calRequest->ScaleFactor[0] = FX_FLTTOFIX_Q16(1.0f);
  96. calRequest->ScaleFactor[1] = FX_FLTTOFIX_Q16(1.0f);
  97. calRequest->ScaleFactor[2] = FX_FLTTOFIX_Q16(1.0f);
  98. // Convert from Android to SMGR's NED coordinate.
  99. calRequest->CompensationMatrix_valid = true;
  100. calRequest->CompensationMatrix_len = 9;
  101. calRequest->CompensationMatrix[0] = FX_FLTTOFIX_Q16(calInfo->compMatrix[4]);
  102. calRequest->CompensationMatrix[1] = FX_FLTTOFIX_Q16(calInfo->compMatrix[3]);
  103. calRequest->CompensationMatrix[2] = FX_FLTTOFIX_Q16(-calInfo->compMatrix[5]);
  104. calRequest->CompensationMatrix[3] = FX_FLTTOFIX_Q16(calInfo->compMatrix[1]);
  105. calRequest->CompensationMatrix[4] = FX_FLTTOFIX_Q16(calInfo->compMatrix[0]);
  106. calRequest->CompensationMatrix[5] = FX_FLTTOFIX_Q16(-calInfo->compMatrix[2]);
  107. calRequest->CompensationMatrix[6] = FX_FLTTOFIX_Q16(-calInfo->compMatrix[7]);
  108. calRequest->CompensationMatrix[7] = FX_FLTTOFIX_Q16(-calInfo->compMatrix[6]);
  109. calRequest->CompensationMatrix[8] = FX_FLTTOFIX_Q16(calInfo->compMatrix[8]);
  110. calRequest->CalibrationAccuracy_valid = true;
  111. calRequest->CalibrationAccuracy = calInfo->accuracy;
  112. }
  113. } // namespace
  114. DLL_EXPORT bool ashSetCalibration(uint8_t sensorType,
  115. const struct ashCalInfo *calInfo) {
  116. bool success = false;
  117. if (!isCalibrationSupported(sensorType)) {
  118. LOGE("Attempting to set calibration of sensor %" PRIu8, sensorType);
  119. } else {
  120. // Allocate request and response for sensor calibraton.
  121. auto calRequest = MakeUniqueZeroFill<sns_smgr_sensor_cal_req_msg_v01>();
  122. auto calResponse = MakeUnique<sns_smgr_sensor_cal_resp_msg_v01>();
  123. if (calRequest.isNull() || calResponse.isNull()) {
  124. LOGE("Failed to allocated sensor cal memory");
  125. } else {
  126. populateCalRequest(sensorType, calInfo, calRequest.get());
  127. smr_err status = getSmrHelper()->sendReqSync(
  128. getSensorServiceSmrClientHandle(), SNS_SMGR_CAL_REQ_V01,
  129. &calRequest, &calResponse);
  130. if (status != SMR_NO_ERR) {
  131. LOGE("Error setting sensor calibration: status %d", status);
  132. } else if (calResponse->Resp.sns_result_t != SNS_RESULT_SUCCESS_V01) {
  133. LOGE("Setting sensor calibration failed with error: %" PRIu8,
  134. calResponse->Resp.sns_err_t);
  135. } else {
  136. success = true;
  137. }
  138. }
  139. }
  140. return success;
  141. }