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
17#include <eventnums.h>
18#include <seos.h>
19#include <timer.h>
20#include <toolchain.h>
21#include <crt_priv.h>
22#include <string.h>
23
24#include <chre.h>
25#include <sensors.h>
26#include <syscallDo.h>
27#include <hostIntf.h>
28
29#define SENSOR_TYPE(x)      ((x) & 0xFF)
30
31/*
32 * Common CHRE App support code
33 */
34
35static bool chreappStart(uint32_t tid)
36{
37    __crt_init();
38    return nanoappStart();
39}
40
41static void chreappEnd(void)
42{
43    nanoappEnd();
44    __crt_exit();
45}
46
47static void initDataHeader(struct chreSensorDataHeader *header, uint64_t timestamp, uint32_t sensorHandle) {
48    header->baseTimestamp = timestamp;
49    header->sensorHandle = sensorHandle;
50    header->readingCount = 1;
51    header->reserved[0] = header->reserved[1] = 0;
52}
53
54static void processTripleAxisData(const struct TripleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType)
55{
56    int i;
57    struct chreSensorThreeAxisData three;
58
59    initDataHeader(&three.header, src->referenceTime, sensorHandle);
60    three.readings[0].timestampDelta = 0;
61
62    for (i=0; i<src->samples[0].firstSample.numSamples; i++) {
63        if (i > 0)
64            three.header.baseTimestamp += src->samples[i].deltaTime;
65        three.readings[0].x = src->samples[i].x;
66        three.readings[0].y = src->samples[i].y;
67        three.readings[0].z = src->samples[i].z;
68
69        nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &three);
70    }
71}
72
73static void processSingleAxisData(const struct SingleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType)
74{
75    int i;
76
77    switch (sensorType) {
78    case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT:
79    case CHRE_SENSOR_TYPE_STATIONARY_DETECT: {
80        struct chreSensorOccurrenceData occ;
81
82        initDataHeader(&occ.header, src->referenceTime, sensorHandle);
83        occ.readings[0].timestampDelta = 0;
84
85        for (i=0; i<src->samples[0].firstSample.numSamples; i++) {
86            if (i > 0)
87                occ.header.baseTimestamp += src->samples[i].deltaTime;
88
89            nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ);
90        }
91        break;
92    }
93    case CHRE_SENSOR_TYPE_LIGHT:
94    case CHRE_SENSOR_TYPE_PRESSURE: {
95        struct chreSensorFloatData flt;
96
97        initDataHeader(&flt.header, src->referenceTime, sensorHandle);
98        flt.readings[0].timestampDelta = 0;
99
100        for (i=0; i<src->samples[0].firstSample.numSamples; i++) {
101            if (i > 0)
102                flt.header.baseTimestamp += src->samples[i].deltaTime;
103            flt.readings[0].value = src->samples[i].fdata;
104
105            nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt);
106        }
107        break;
108    }
109    case CHRE_SENSOR_TYPE_PROXIMITY: {
110        struct chreSensorByteData byte;
111
112        initDataHeader(&byte.header, src->referenceTime, sensorHandle);
113        byte.readings[0].timestampDelta = 0;
114
115        for (i=0; i<src->samples[0].firstSample.numSamples; i++) {
116            if (i > 0)
117                byte.header.baseTimestamp += src->samples[i].deltaTime;
118            byte.readings[0].isNear = src->samples[i].fdata == 0.0f;
119            byte.readings[0].invalid = false;
120            byte.readings[0].padding0 = 0;
121
122            nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte);
123        }
124        break;
125    }
126    }
127}
128
129static void processEmbeddedData(const void *src, uint32_t sensorHandle, uint8_t sensorType)
130{
131    union EmbeddedDataPoint data = (union EmbeddedDataPoint)((void *)src);
132
133    switch (sensorType) {
134    case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT:
135    case CHRE_SENSOR_TYPE_STATIONARY_DETECT: {
136        struct chreSensorOccurrenceData occ;
137
138        initDataHeader(&occ.header, eOsSensorGetTime(), sensorHandle);
139        occ.readings[0].timestampDelta = 0;
140
141        nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ);
142        break;
143    }
144    case CHRE_SENSOR_TYPE_LIGHT:
145    case CHRE_SENSOR_TYPE_PRESSURE: {
146        struct chreSensorFloatData flt;
147
148        initDataHeader(&flt.header, eOsSensorGetTime(), sensorHandle);
149        flt.readings[0].timestampDelta = 0;
150        flt.readings[0].value = data.fdata;
151
152        nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt);
153        break;
154    }
155    case CHRE_SENSOR_TYPE_PROXIMITY: {
156        struct chreSensorByteData byte;
157
158        initDataHeader(&byte.header, eOsSensorGetTime(), sensorHandle);
159        byte.readings[0].timestampDelta = 0;
160        byte.readings[0].isNear = data.fdata == 0.0f;
161        byte.readings[0].invalid = false;
162        byte.readings[0].padding0 = 0;
163
164        nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte);
165        break;
166    }
167    }
168}
169
170static void chreappProcessSensorData(uint16_t evt, const void *eventData)
171{
172    const struct SensorInfo *si;
173    uint32_t sensorHandle;
174
175    if (eventData == SENSOR_DATA_EVENT_FLUSH)
176        return;
177
178    si = eOsSensorFind(SENSOR_TYPE(evt), 0, &sensorHandle);
179    if (si && eOsSensorGetReqRate(sensorHandle)) {
180        switch (si->numAxis) {
181        case NUM_AXIS_EMBEDDED:
182            processEmbeddedData(eventData, sensorHandle, SENSOR_TYPE(evt));
183            break;
184        case NUM_AXIS_ONE:
185            processSingleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt));
186            break;
187        case NUM_AXIS_THREE:
188            processTripleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt));
189            break;
190        }
191
192        if (SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT
193            || SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_STATIONARY_DETECT) {
194            // one-shot, disable after receiving sample
195            chreSensorConfigure(sensorHandle, CHRE_SENSOR_CONFIGURE_MODE_DONE, CHRE_SENSOR_INTERVAL_DEFAULT, CHRE_SENSOR_LATENCY_DEFAULT);
196        }
197    }
198}
199
200static void chreappProcessConfigEvt(uint16_t evt, const void *eventData)
201{
202    const struct SensorRateChangeEvent *msg = eventData;
203    struct chreSensorSamplingStatusEvent change;
204
205    change.sensorHandle = msg->sensorHandle;
206    if (!msg->newRate) {
207        change.status.enabled = 0;
208        change.status.interval = 0;
209        change.status.latency = 0;
210    } else {
211        change.status.enabled = true;
212        if (msg->newRate == SENSOR_RATE_ONDEMAND
213            || msg->newRate == SENSOR_RATE_ONCHANGE
214            || msg->newRate == SENSOR_RATE_ONESHOT)
215            change.status.interval = CHRE_SENSOR_INTERVAL_DEFAULT;
216        else
217            change.status.interval = (UINT32_C(1024000000) / msg->newRate) * UINT64_C(1000);
218
219        if (msg->newLatency == SENSOR_LATENCY_NODATA)
220            change.status.latency = CHRE_SENSOR_INTERVAL_DEFAULT;
221        else
222            change.status.latency = msg->newLatency;
223    }
224
225    nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_SAMPLING_CHANGE, &change);
226}
227
228static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData)
229{
230    uint16_t evt = eventTypeAndTid;
231    uint16_t srcTid = eventTypeAndTid >> 16;
232    const void *data = eventData;
233
234    union EventLocalData {
235        struct chreMessageFromHostData msg;
236        struct chreNanoappInfo info;
237    } u;
238
239    switch(evt) {
240    case EVT_APP_TIMER:
241        evt = CHRE_EVENT_TIMER;
242        data = ((struct TimerEvent *)eventData)->data;
243        break;
244    case EVT_APP_FROM_HOST:
245        srcTid = CHRE_INSTANCE_ID;
246        evt = CHRE_EVENT_MESSAGE_FROM_HOST;
247        data = &u.msg;
248        u.msg.message = (uint8_t*)eventData + 1;
249        u.msg.messageType = 0;
250        u.msg.messageSize = *(uint8_t*)eventData;
251        u.msg.hostEndpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED;
252        break;
253    case EVT_APP_FROM_HOST_CHRE:
254    {
255        if (chreGetApiVersion() == CHRE_API_VERSION_1_0) {
256            const struct NanohubMsgChreHdrV10 *hdr = eventData;
257            srcTid = CHRE_INSTANCE_ID;
258            evt = CHRE_EVENT_MESSAGE_FROM_HOST;
259            data = &u.msg;
260            u.msg.message = hdr + 1;
261            u.msg.messageType = hdr->appEvent;
262            u.msg.messageSize = hdr->size;
263            u.msg.hostEndpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED;
264        } else {
265            const struct NanohubMsgChreHdr *hdr = eventData;
266            srcTid = CHRE_INSTANCE_ID;
267            evt = CHRE_EVENT_MESSAGE_FROM_HOST;
268            data = &u.msg;
269            u.msg.message = hdr + 1;
270            u.msg.messageType = hdr->appEvent;
271            u.msg.messageSize = hdr->size;
272            u.msg.hostEndpoint = hdr->endpoint;
273        }
274        break;
275    }
276    case EVT_APP_STARTED:
277    case EVT_APP_STOPPED:
278    {
279        const struct AppEventStartStop *msg = eventData;
280        srcTid = CHRE_INSTANCE_ID;
281        if (evt == EVT_APP_STARTED)
282            evt = CHRE_EVENT_NANOAPP_STARTED;
283        else
284            evt = CHRE_EVENT_NANOAPP_STOPPED;
285        data = &u.info;
286        u.info.appId = msg->appId;
287        u.info.version = msg->version;
288        u.info.instanceId = msg->tid;
289        break;
290    }
291    case EVT_APP_SENSOR_SELF_TEST:
292    case EVT_APP_SENSOR_MARSHALL:
293    case EVT_APP_SENSOR_SEND_ONE_DIR_EVT:
294    case EVT_APP_SENSOR_CFG_DATA:
295    case EVT_APP_SENSOR_CALIBRATE:
296    case EVT_APP_SENSOR_TRIGGER:
297    case EVT_APP_SENSOR_FLUSH:
298    case EVT_APP_SENSOR_SET_RATE:
299    case EVT_APP_SENSOR_FW_UPLD:
300    case EVT_APP_SENSOR_POWER:
301        // sensor events; pass through
302        break;
303    default:
304        // ignore any other system events; OS may send them to any app
305        if (evt < EVT_NO_FIRST_USER_EVENT)
306            return;
307        else if (evt > EVT_NO_FIRST_SENSOR_EVENT && evt < EVT_NO_SENSOR_CONFIG_EVENT) {
308            return chreappProcessSensorData(evt, data);
309        } else if (evt > EVT_NO_SENSOR_CONFIG_EVENT && evt < EVT_APP_START) {
310            return chreappProcessConfigEvt(evt, data);
311        }
312    }
313    nanoappHandleEvent(srcTid, evt, data);
314}
315
316// Collect entry points
317const struct AppFuncs SET_EXTERNAL_APP_ATTRIBUTES(used, section (".app_init"),visibility("default")) _mAppFuncs = {
318    .init   = chreappStart,
319    .end    = chreappEnd,
320    .handle = chreappHandle,
321};
322
323// declare version for compatibility with current runtime
324const uint32_t SET_EXTERNAL_APP_VERSION(used, section (".app_version"), visibility("default")) _mAppVer = 0;
325