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 
chreappStart(uint32_t tid)35 static bool chreappStart(uint32_t tid)
36 {
37     __crt_init();
38     return nanoappStart();
39 }
40 
chreappEnd(void)41 static void chreappEnd(void)
42 {
43     nanoappEnd();
44     __crt_exit();
45 }
46 
initDataHeader(struct chreSensorDataHeader * header,uint64_t timestamp,uint32_t sensorHandle)47 static 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 
processTripleAxisData(const struct TripleAxisDataEvent * src,uint32_t sensorHandle,uint8_t sensorType)54 static 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 
processSingleAxisData(const struct SingleAxisDataEvent * src,uint32_t sensorHandle,uint8_t sensorType)73 static 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 
processEmbeddedData(const void * src,uint32_t sensorHandle,uint8_t sensorType)129 static 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 
chreappProcessSensorData(uint16_t evt,const void * eventData)170 static 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 
chreappProcessConfigEvt(uint16_t evt,const void * eventData)200 static 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 
chreappHandle(uint32_t eventTypeAndTid,const void * eventData)228 static 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
317 const 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
324 const uint32_t SET_EXTERNAL_APP_VERSION(used, section (".app_version"), visibility("default")) _mAppVer = 0;
325