1/*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "sensor_channel.h"
17#include <securec.h>
18#include "hdf_io_service_if.h"
19#include "osal_mutex.h"
20#include "osal_time.h"
21#include "sensor_common.h"
22#include "sensor_manager.h"
23#include "sensor_type.h"
24
25#define HDF_LOG_TAG    uhdf_sensor_service
26
27#define ACCEL_ACCURACY    ((HDI_SENSOR_GRAVITY) / (HDI_SENSOR_UNITS) / (HDI_SENSOR_UNITS))
28#define GYRO_ACCURACY     ((1 / (HDI_SENSOR_FLOAT_UNITS)) * ((HDI_SENSOR_PI) / (HDI_SENSOR_SEMICIRCLE)))
29#define BAROMETER_BAROMETER_ACCURACY (1 / (HDI_SENSOR_FLOAT_HUN_UNITS))
30#define BAROMETER_TEMPERATURE_ACCURACY (1 / (HDI_SENSOR_FLOAT_TEN_UNITS))
31#define MAGNETIC_ACCURACY    (1 / (HDI_SENSOR_FLOAT_UNITS))
32#define ALS_ACCURACY     (1 / (HDI_SENSOR_FLOAT_UNITS))
33#define HALL_ACCURACY     ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
34#define PROXIMITY_ACCURACY     ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
35#define PEDOMETER_ACCURACY     ((HDI_SENSOR_FLOAT_TEN_UNITS) / (HDI_SENSOR_FLOAT_TEN_UNITS))
36#define TEMPERATURE_ACCURACY     (1 / (HDI_SENSOR_FLOAT_TEN_UNITS))
37#define HUMIDITY_ACCURACY     (1 / (HDI_SENSOR_FLOAT_HUN_UNITS))
38
39static struct SensorCovertCoff g_sensorCovertCoff[] = {
40    { SENSOR_TYPE_NONE, 0, DATA_X, { ACCEL_ACCURACY } },
41    { SENSOR_TYPE_ACCELEROMETER, SENSOR_TYPE_MAX, DATA_XYZ, { ACCEL_ACCURACY, ACCEL_ACCURACY, ACCEL_ACCURACY } },
42    { SENSOR_TYPE_GRAVITY, SENSOR_TYPE_MAX, DATA_XYZ, { ACCEL_ACCURACY, ACCEL_ACCURACY, ACCEL_ACCURACY } },
43    { SENSOR_TYPE_GYROSCOPE, SENSOR_TYPE_MAX, DATA_XYZ, { GYRO_ACCURACY, GYRO_ACCURACY, GYRO_ACCURACY } },
44    { SENSOR_TYPE_BAROMETER, SENSOR_TYPE_MAX, DATA_XY,
45        { BAROMETER_BAROMETER_ACCURACY, BAROMETER_TEMPERATURE_ACCURACY } },
46    { SENSOR_TYPE_MAGNETIC_FIELD, SENSOR_TYPE_MAX, DATA_XYZ,
47        { MAGNETIC_ACCURACY, MAGNETIC_ACCURACY, MAGNETIC_ACCURACY } },
48    { SENSOR_TYPE_AMBIENT_LIGHT, SENSOR_TYPE_MAX, DATA_XYZA,
49        { ALS_ACCURACY, ALS_ACCURACY, ALS_ACCURACY, ALS_ACCURACY } },
50    { SENSOR_TYPE_PEDOMETER, SENSOR_TYPE_MAX, DATA_X, { PEDOMETER_ACCURACY } },
51    { SENSOR_TYPE_HALL, SENSOR_TYPE_MAX, DATA_X, { HALL_ACCURACY } },
52    { SENSOR_TYPE_PROXIMITY, SENSOR_TYPE_MAX, DATA_X, { PROXIMITY_ACCURACY } },
53    { SENSOR_TYPE_TEMPERATURE, SENSOR_TYPE_MAX, DATA_X, { TEMPERATURE_ACCURACY } },
54    { SENSOR_TYPE_HUMIDITY, SENSOR_TYPE_MAX, DATA_X, { HUMIDITY_ACCURACY } },
55};
56
57static struct SensorDumpDate g_dumpDate = { 0 };
58static struct SensorDatePack g_listDump = { 0 };
59
60struct SensorDatePack *GetEventData(void)
61{
62    return &g_listDump;
63}
64
65void SetSensorIdBySensorType(enum SensorTypeTag type, int32_t sensorId)
66{
67    uint32_t count = sizeof(g_sensorCovertCoff) / sizeof(g_sensorCovertCoff[0]);
68
69    for (uint32_t i = 0; i < count; ++i) {
70        if (g_sensorCovertCoff[i].sensorTypeId == (int32_t)type) {
71            g_sensorCovertCoff[i].sensorId = sensorId;
72            break;
73        }
74    }
75}
76
77void CopyEventData(struct SensorEvents *event)
78{
79    if (event == NULL || event->data == NULL) {
80        HDF_LOGE("%{public}s: event==NULL || event->data==NULL !", __func__);
81        return;
82    }
83
84    for (uint32_t i = 0; i < event->dataLen; i++) {
85        g_dumpDate.data[i] = event->data[i];
86    }
87    g_dumpDate.dataLen = event->dataLen;
88    g_dumpDate.sensorId = event->sensorId;
89    g_dumpDate.version = event->version;
90    g_dumpDate.timestamp = event->timestamp;
91    g_dumpDate.option = event->option;
92    g_dumpDate.mode = event->mode;
93
94    if (g_listDump.pos < 0 || g_listDump.pos >= MAX_DUMP_DATA_SIZE) {
95        HDF_LOGE("%{public}s: g_listDump is invalid", __func__);
96        return;
97    }
98    g_listDump.listDumpArr[g_listDump.pos] = g_dumpDate;
99
100    if (g_listDump.pos + 1 >= MAX_DUMP_DATA_SIZE) {
101        g_listDump.pos = 0;
102    } else {
103        g_listDump.pos++;
104    }
105    if (g_listDump.count < MAX_DUMP_DATA_SIZE) {
106        g_listDump.count++;
107    }
108}
109
110void ConvertSensorData(struct SensorEvents *event)
111{
112    uint32_t dataLen;
113    uint32_t axis;
114    int32_t *data = NULL;
115    float *value = NULL;
116
117    data = (int32_t *)event->data;
118    value = (float *)event->data;
119
120    for (uint32_t i = 0; i < sizeof(g_sensorCovertCoff) / sizeof(g_sensorCovertCoff[0]); ++i) {
121        if ((g_sensorCovertCoff[i].sensorId == event->sensorId) && (g_sensorCovertCoff[i].dim != 0)) {
122            dataLen = event->dataLen / sizeof(int32_t);
123            for (uint32_t j = 0; j < dataLen; ++j) {
124                axis = j % g_sensorCovertCoff[i].dim;
125                value[j] = (float)(data[j] * g_sensorCovertCoff[i].coff[axis]);
126            }
127        }
128    }
129}
130
131static int OnSensorEventReceived(struct HdfDevEventlistener *listener,
132    struct HdfIoService *service, uint32_t id, struct HdfSBuf *data)
133{
134    uint32_t len;
135    struct SensorEvents *event = NULL;
136    struct SensorDevManager *manager = GetSensorDevManager();
137    (void)listener;
138    (void)service;
139    (void)id;
140
141    (void)OsalMutexLock(&manager->eventMutex);
142    if (!HdfSbufReadBuffer(data, (const void **)&event, &len) || event == NULL) {
143        HDF_LOGE("%{public}s: Read sensor event fail!", __func__);
144        (void)OsalMutexUnlock(&manager->eventMutex);
145        return SENSOR_FAILURE;
146    }
147
148    uint8_t *buf = NULL;
149    if (!HdfSbufReadBuffer(data, (const void **)&buf, &len) || buf == NULL) {
150        (void)OsalMutexUnlock(&manager->eventMutex);
151        HDF_LOGE("%{public}s: Read sensor data fail!", __func__);
152        return SENSOR_FAILURE;
153    } else {
154        event->data = buf;
155        event->dataLen = len;
156    }
157
158    enum SensorGroupType groupType;
159    if (event->sensorId >= SENSOR_TYPE_MEDICAL_BEGIN && event->sensorId < SENSOR_TYPE_MEDICAL_END) {
160        groupType = MEDICAL_SENSOR_TYPE;
161    } else {
162        groupType = TRADITIONAL_SENSOR_TYPE;
163    }
164    event->option = SENSOR_STATUS_ACCURACY_HIGH;
165
166    ConvertSensorData(event);
167    CopyEventData(event);
168
169    if (manager->recordDataCb[groupType] != NULL) {
170        manager->recordDataCb[groupType](event);
171    }
172
173    (void)OsalMutexUnlock(&manager->eventMutex);
174
175    return SENSOR_SUCCESS;
176}
177
178static struct HdfDevEventlistener g_listener = {
179    .onReceive = OnSensorEventReceived,
180    .priv = "hdi_sensor"
181};
182
183struct HdfDevEventlistener *GetSensorListener(void)
184{
185    return &g_listener;
186}
187
188static int32_t AddSensorDevServiceGroup(void)
189{
190    struct SensorManagerNode *pos = NULL;
191    struct SensorDevManager *manager = GetSensorDevManager();
192
193    manager->serviceGroup = HdfIoServiceGroupObtain();
194    if (manager->serviceGroup == NULL) {
195        return SENSOR_FAILURE;
196    }
197
198    DLIST_FOR_EACH_ENTRY(pos, &manager->managerHead, struct SensorManagerNode, node) {
199        if ((pos->ioService != NULL) &&
200            (HdfIoServiceGroupAddService(manager->serviceGroup, pos->ioService) != SENSOR_SUCCESS)) {
201            HdfIoServiceGroupRecycle(manager->serviceGroup);
202            manager->serviceGroup = NULL;
203            HDF_LOGE("%{public}s: Add service to group failed", __func__);
204            return SENSOR_INVALID_SERVICE;
205        }
206    }
207
208    int32_t ret = HdfIoServiceGroupRegisterListener(manager->serviceGroup, &g_listener);
209    if (ret != SENSOR_SUCCESS) {
210        HDF_LOGE("%{public}s: Register listener to group failed", __func__);
211        HdfIoServiceGroupRecycle(manager->serviceGroup);
212        manager->serviceGroup = NULL;
213        return ret;
214    }
215
216    return SENSOR_SUCCESS;
217}
218
219int32_t Register(int32_t groupId, RecordDataCallback cb)
220{
221    if (groupId < TRADITIONAL_SENSOR_TYPE || groupId > MEDICAL_SENSOR_TYPE) {
222        HDF_LOGE("%{public}s: groupId [%{public}d] out of range", __func__, groupId);
223        return SENSOR_INVALID_PARAM;
224    }
225    struct SensorDevManager *manager = NULL;
226    CHECK_NULL_PTR_RETURN_VALUE(cb, SENSOR_NULL_PTR);
227    manager = GetSensorDevManager();
228    (void)OsalMutexLock(&manager->eventMutex);
229    if (manager->recordDataCb[groupId] != NULL) {
230        HDF_LOGE("%{public}s: groupId [%{public}d] callback already exists", __func__, groupId);
231        (void)OsalMutexUnlock(&manager->eventMutex);
232        return SENSOR_FAILURE;
233    }
234
235    if (manager->serviceGroup != NULL) {
236        manager->recordDataCb[groupId] = cb;
237        (void)OsalMutexUnlock(&manager->eventMutex);
238        return SENSOR_SUCCESS;
239    }
240    int32_t ret = AddSensorDevServiceGroup();
241    if (ret == SENSOR_SUCCESS) {
242        manager->recordDataCb[groupId] = cb;
243    }
244    (void)OsalMutexUnlock(&manager->eventMutex);
245    return ret;
246}
247
248int32_t Unregister(int32_t groupId, RecordDataCallback cb)
249{
250    if (groupId < TRADITIONAL_SENSOR_TYPE || groupId > MEDICAL_SENSOR_TYPE) {
251        HDF_LOGE("%{public}s: groupId [%{public}d] out of range", __func__, groupId);
252        return SENSOR_INVALID_PARAM;
253    }
254    CHECK_NULL_PTR_RETURN_VALUE(cb, SENSOR_NULL_PTR);
255    struct SensorDevManager *manager = GetSensorDevManager();
256
257    (void)OsalMutexLock(&manager->eventMutex);
258    if (manager->recordDataCb[groupId] != cb) {
259        HDF_LOGE("%{public}s: groupId [%{public}d] cb not same with registered", __func__, groupId);
260        (void)OsalMutexUnlock(&manager->eventMutex);
261        return SENSOR_FAILURE;
262    }
263
264    if (manager->recordDataCb[TRADITIONAL_SENSOR_TYPE] != NULL &&
265        manager->recordDataCb[MEDICAL_SENSOR_TYPE] != NULL) {
266        manager->recordDataCb[groupId] = NULL;
267        (void)OsalMutexUnlock(&manager->eventMutex);
268        return SENSOR_SUCCESS;
269    }
270
271    int32_t ret = HdfIoServiceGroupUnregisterListener(manager->serviceGroup, &g_listener);
272    if (ret != SENSOR_SUCCESS) {
273        HDF_LOGE("%{public}s: Sensor unregister listener failed", __func__);
274        (void)OsalMutexUnlock(&manager->eventMutex);
275        return ret;
276    }
277
278    manager->hasSensorListener = false;
279    HdfIoServiceGroupRecycle(manager->serviceGroup);
280    manager->serviceGroup = NULL;
281    manager->recordDataCb[groupId] = NULL;
282    (void)OsalMutexUnlock(&manager->eventMutex);
283
284    return SENSOR_SUCCESS;
285}
286