* Copyright (c) 2021-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "sensor_channel.h"
#include <securec.h>
#include "hdf_io_service_if.h"
#include "osal_mutex.h"
#include "osal_time.h"
#include "sensor_common.h"
#include "sensor_manager.h"
#include "sensor_type.h"
#define HDF_LOG_TAG uhdf_sensor_service
#define ACCEL_ACCURACY ((HDI_SENSOR_GRAVITY) / (HDI_SENSOR_UNITS) / (HDI_SENSOR_UNITS))
#define GYRO_ACCURACY ((1 / (HDI_SENSOR_FLOAT_UNITS)) * ((HDI_SENSOR_PI) / (HDI_SENSOR_SEMICIRCLE)))
#define BAROMETER_BAROMETER_ACCURACY (1 / (HDI_SENSOR_FLOAT_HUN_UNITS))
#define DEPTH_DEPTH_ACCURACY (1 / (HDI_SENSOR_FLOAT_HUN_UNITS))
#define BAROMETER_TEMPERATURE_ACCURACY (1 / (HDI_SENSOR_FLOAT_TEN_UNITS))
#define MAGNETIC_ACCURACY (1 / (HDI_SENSOR_FLOAT_UNITS))
#define ALS_ACCURACY (1 / (HDI_SENSOR_FLOAT_UNITS))
#define HALL_ACCURACY ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
#define PROXIMITY_ACCURACY ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
#define PEDOMETER_ACCURACY ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
#define TEMPERATURE_ACCURACY (1 / (HDI_SENSOR_FLOAT_TEN_UNITS))
#define HUMIDITY_ACCURACY (1 / (HDI_SENSOR_FLOAT_HUN_UNITS))
static struct SensorCovertCoff g_sensorCovertCoff[] = {
{ SENSOR_TYPE_NONE, 0, DATA_X, { ACCEL_ACCURACY } },
{ SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_MAX, DATA_XYZ, { ACCEL_ACCURACY, ACCEL_ACCURACY, ACCEL_ACCURACY } },
{ SENSOR_TYPE_GRAVITY, SENSOR_TYPE_MAX, DATA_XYZ, { ACCEL_ACCURACY, ACCEL_ACCURACY, ACCEL_ACCURACY } },
{ SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAX, DATA_XYZ, { GYRO_ACCURACY, GYRO_ACCURACY, GYRO_ACCURACY } },
{ SENSOR_TYPE_BAROMETER, SENSOR_TYPE_MAX, DATA_XY,
{ BAROMETER_BAROMETER_ACCURACY, BAROMETER_TEMPERATURE_ACCURACY } },
{ SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_MAX, DATA_XYZ,
{ MAGNETIC_ACCURACY, MAGNETIC_ACCURACY, MAGNETIC_ACCURACY } },
{ SENSOR_TYPE_AMBIENT_LIGHT, SENSOR_TYPE_MAX, DATA_XYZA,
{ ALS_ACCURACY, ALS_ACCURACY, ALS_ACCURACY, ALS_ACCURACY } },
{ SENSOR_TYPE_PEDOMETER, SENSOR_TYPE_MAX, DATA_X, { PEDOMETER_ACCURACY } },
{ SENSOR_TYPE_HALL, SENSOR_TYPE_MAX, DATA_X, { HALL_ACCURACY } },
{ SENSOR_TYPE_PROXIMITY, SENSOR_TYPE_MAX, DATA_X, { PROXIMITY_ACCURACY } },
{ SENSOR_TYPE_TEMPERATURE, SENSOR_TYPE_MAX, DATA_X, { TEMPERATURE_ACCURACY } },
{ SENSOR_TYPE_HUMIDITY, SENSOR_TYPE_MAX, DATA_X, { HUMIDITY_ACCURACY } },
{ SENSOR_TYPE_DEPTH, SENSOR_TYPE_MAX, DATA_XY, { DEPTH_DEPTH_ACCURACY, BAROMETER_TEMPERATURE_ACCURACY } },
};
static struct SensorDumpDate g_dumpDate = { 0 };
static struct SensorDatePack g_listDump = { 0 };
struct SensorDatePack *GetEventData(void)
{
return &g_listDump;
}
void SetSensorIdBySensorType(enum SensorTypeTag type, int32_t sensorId)
{
uint32_t count = sizeof(g_sensorCovertCoff) / sizeof(g_sensorCovertCoff[0]);
for (uint32_t i = 0; i < count; ++i) {
if (g_sensorCovertCoff[i].sensorTypeId == (int32_t)type) {
g_sensorCovertCoff[i].sensorId = sensorId;
break;
}
}
}
void CopyEventData(struct SensorEvents *event)
{
if (event == NULL || event->data == NULL) {
HDF_LOGE("%{public}s: event==NULL || event->data==NULL !", __func__);
return;
}
for (uint32_t i = 0; i < event->dataLen; i++) {
g_dumpDate.data[i] = event->data[i];
}
g_dumpDate.dataLen = event->dataLen;
g_dumpDate.sensorId = event->sensorId;
g_dumpDate.version = event->version;
g_dumpDate.timestamp = event->timestamp;
g_dumpDate.option = event->option;
g_dumpDate.mode = event->mode;
if (g_listDump.pos < 0 || g_listDump.pos >= MAX_DUMP_DATA_SIZE) {
HDF_LOGE("%{public}s: g_listDump is invalid", __func__);
return;
}
g_listDump.listDumpArr[g_listDump.pos] = g_dumpDate;
if (g_listDump.pos + 1 >= MAX_DUMP_DATA_SIZE) {
g_listDump.pos = 0;
} else {
g_listDump.pos++;
}
if (g_listDump.count < MAX_DUMP_DATA_SIZE) {
g_listDump.count++;
}
}
void ConvertSensorData(struct SensorEvents *event)
{
uint32_t dataLen;
uint32_t axis;
int32_t *data = NULL;
float *value = NULL;
data = (int32_t *)event->data;
value = (float *)event->data;
for (uint32_t i = 0; i < sizeof(g_sensorCovertCoff) / sizeof(g_sensorCovertCoff[0]); ++i) {
if ((g_sensorCovertCoff[i].sensorId == event->sensorId) && (g_sensorCovertCoff[i].dim != 0)) {
dataLen = event->dataLen / sizeof(int32_t);
for (uint32_t j = 0; j < dataLen; ++j) {
axis = j % g_sensorCovertCoff[i].dim;
value[j] = (float)(data[j] * g_sensorCovertCoff[i].coff[axis]);
}
}
}
}
static int OnSensorEventReceived(struct HdfDevEventlistener *listener,
struct HdfIoService *service, uint32_t id, struct HdfSBuf *data)
{
uint32_t len;
struct SensorEvents *event = NULL;
struct SensorDevManager *manager = GetSensorDevManager();
(void)listener;
(void)service;
(void)id;
(void)OsalMutexLock(&manager->eventMutex);
if (!HdfSbufReadBuffer(data, (const void **)&event, &len) || event == NULL) {
HDF_LOGE("%{public}s: Read sensor event fail!", __func__);
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_FAILURE;
}
uint8_t *buf = NULL;
if (!HdfSbufReadBuffer(data, (const void **)&buf, &len) || buf == NULL) {
(void)OsalMutexUnlock(&manager->eventMutex);
HDF_LOGE("%{public}s: Read sensor data fail!", __func__);
return SENSOR_FAILURE;
} else {
event->data = buf;
event->dataLen = len;
}
enum SensorGroupType groupType;
if (event->sensorId >= SENSOR_TYPE_MEDICAL_BEGIN && event->sensorId < SENSOR_TYPE_MEDICAL_END) {
groupType = MEDICAL_SENSOR_TYPE;
} else {
groupType = TRADITIONAL_SENSOR_TYPE;
}
event->option = SENSOR_STATUS_ACCURACY_HIGH;
ConvertSensorData(event);
CopyEventData(event);
if (manager->recordDataCb[groupType] != NULL) {
manager->recordDataCb[groupType](event);
}
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_SUCCESS;
}
static struct HdfDevEventlistener g_listener = {
.onReceive = OnSensorEventReceived,
.priv = "hdi_sensor"
};
struct HdfDevEventlistener *GetSensorListener(void)
{
return &g_listener;
}
static int32_t AddSensorDevServiceGroup(void)
{
struct SensorManagerNode *pos = NULL;
struct SensorDevManager *manager = GetSensorDevManager();
manager->serviceGroup = HdfIoServiceGroupObtain();
if (manager->serviceGroup == NULL) {
return SENSOR_FAILURE;
}
DLIST_FOR_EACH_ENTRY(pos, &manager->managerHead, struct SensorManagerNode, node) {
if ((pos->ioService != NULL) &&
(HdfIoServiceGroupAddService(manager->serviceGroup, pos->ioService) != SENSOR_SUCCESS)) {
HdfIoServiceGroupRecycle(manager->serviceGroup);
manager->serviceGroup = NULL;
HDF_LOGE("%{public}s: Add service to group failed", __func__);
return SENSOR_INVALID_SERVICE;
}
}
int32_t ret = HdfIoServiceGroupRegisterListener(manager->serviceGroup, &g_listener);
if (ret != SENSOR_SUCCESS) {
HDF_LOGE("%{public}s: Register listener to group failed", __func__);
HdfIoServiceGroupRecycle(manager->serviceGroup);
manager->serviceGroup = NULL;
return ret;
}
return SENSOR_SUCCESS;
}
int32_t Register(int32_t groupId, RecordDataCallback cb)
{
if (groupId < TRADITIONAL_SENSOR_TYPE || groupId > MEDICAL_SENSOR_TYPE) {
HDF_LOGE("%{public}s: groupId [%{public}d] out of range", __func__, groupId);
return SENSOR_INVALID_PARAM;
}
struct SensorDevManager *manager = NULL;
CHECK_NULL_PTR_RETURN_VALUE(cb, SENSOR_NULL_PTR);
manager = GetSensorDevManager();
(void)OsalMutexLock(&manager->eventMutex);
if (manager->recordDataCb[groupId] != NULL) {
HDF_LOGE("%{public}s: groupId [%{public}d] callback already exists", __func__, groupId);
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_FAILURE;
}
if (manager->serviceGroup != NULL) {
manager->recordDataCb[groupId] = cb;
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_SUCCESS;
}
int32_t ret = AddSensorDevServiceGroup();
if (ret == SENSOR_SUCCESS) {
manager->recordDataCb[groupId] = cb;
}
(void)OsalMutexUnlock(&manager->eventMutex);
return ret;
}
int32_t Unregister(int32_t groupId, RecordDataCallback cb)
{
if (groupId < TRADITIONAL_SENSOR_TYPE || groupId > MEDICAL_SENSOR_TYPE) {
HDF_LOGE("%{public}s: groupId [%{public}d] out of range", __func__, groupId);
return SENSOR_INVALID_PARAM;
}
CHECK_NULL_PTR_RETURN_VALUE(cb, SENSOR_NULL_PTR);
struct SensorDevManager *manager = GetSensorDevManager();
(void)OsalMutexLock(&manager->eventMutex);
if (manager->recordDataCb[groupId] != cb) {
HDF_LOGE("%{public}s: groupId [%{public}d] cb not same with registered", __func__, groupId);
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_FAILURE;
}
if (manager->recordDataCb[TRADITIONAL_SENSOR_TYPE] != NULL &&
manager->recordDataCb[MEDICAL_SENSOR_TYPE] != NULL) {
manager->recordDataCb[groupId] = NULL;
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_SUCCESS;
}
int32_t ret = HdfIoServiceGroupUnregisterListener(manager->serviceGroup, &g_listener);
if (ret != SENSOR_SUCCESS) {
HDF_LOGE("%{public}s: Sensor unregister listener failed", __func__);
(void)OsalMutexUnlock(&manager->eventMutex);
return ret;
}
manager->hasSensorListener = false;
HdfIoServiceGroupRecycle(manager->serviceGroup);
manager->serviceGroup = NULL;
manager->recordDataCb[groupId] = NULL;
(void)OsalMutexUnlock(&manager->eventMutex);
return SENSOR_SUCCESS;
}