• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 <stdarg.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include <cpu.h>
24 #include <cpu/cpuMath.h>
25 #include <heap.h>
26 #include <sensors.h>
27 #include <sensors_priv.h>
28 #include <seos.h>
29 #include <seos_priv.h>
30 #include <syscall.h>
31 #include <timer.h>
32 #include <util.h>
33 
34 #include <chre.h>
35 #include <chreApi.h>
36 
37 #define MINIMUM_INTERVAL_DEFAULT_HZ SENSOR_HZ(1.0f)
38 
39 /*
40  * This is to ensure that message size and some extra headers will stay representable with 1 byte
41  * Code relies on that in many places.
42  */
43 C_STATIC_ASSERT(max_chre_msg_size, CHRE_MESSAGE_TO_HOST_MAX_SIZE <= 240);
44 
45 /*
46  * Many syscalls rely on the property that uintptr_t can hold uint32_t without data loss
47  * This is enforced by static assertion in chreApi.h
48  * None of the methods returning uint32_t are cast to uintptr_t
49  * This is done in order to let compiler warn us if our assumption is not safe for some reason
50  */
51 
osChreGetAppId(void)52 static inline uint64_t osChreGetAppId(void)
53 {
54     struct Task *task = osGetCurrentTask();
55     const struct AppHdr *app = task ? task->app : NULL;
56 
57     return app ? app->hdr.appId : 0;
58 }
59 
osChreApiGetAppId(uintptr_t * retValP,va_list args)60 static void osChreApiGetAppId(uintptr_t *retValP, va_list args)
61 {
62     uint64_t *appId = va_arg(args, uint64_t *);
63     if (appId)
64         *appId = osChreGetAppId();
65 }
66 
osChreApiGetInstanceId(uintptr_t * retValP,va_list args)67 static void osChreApiGetInstanceId(uintptr_t *retValP, va_list args)
68 {
69     *retValP = osGetCurrentTid();
70 }
71 
osChreApiLogLogv(uintptr_t * retValP,va_list args)72 static void osChreApiLogLogv(uintptr_t *retValP, va_list args)
73 {
74     va_list innerArgs;
75     enum chreLogLevel level = va_arg(args, int /* enums promoted to ints in va_args in C */);
76     const static char levels[] = "EWIDV";
77     char clevel = level > CHRE_LOG_DEBUG || level < 0 ? 'V' : levels[level];
78     const char *str = va_arg(args, const char*);
79     uintptr_t inner = va_arg(args, uintptr_t);
80 
81     va_copy(innerArgs, INTEGER_TO_VA_LIST(inner));
82     osLogv(clevel, str, innerArgs);
83     va_end(innerArgs);
84 }
85 
osChreApiGetTime(uintptr_t * retValP,va_list args)86 static void osChreApiGetTime(uintptr_t *retValP, va_list args)
87 {
88     uint64_t *timeNanos = va_arg(args, uint64_t *);
89     if (timeNanos)
90         *timeNanos = timGetTime();
91 }
92 
osChreTimerSet(uint64_t duration,const void * cookie,bool oneShot)93 static inline uint32_t osChreTimerSet(uint64_t duration, const void* cookie, bool oneShot)
94 {
95     uint32_t timId = timTimerSetNew(duration, cookie, oneShot);
96 
97     return timId == 0 ? CHRE_TIMER_INVALID : timId;
98 }
99 
osChreApiTimerSet(uintptr_t * retValP,va_list args)100 static void osChreApiTimerSet(uintptr_t *retValP, va_list args)
101 {
102     uint32_t length_lo = va_arg(args, uint32_t);
103     uint32_t length_hi = va_arg(args, uint32_t);
104     void *cookie = va_arg(args, void *);
105     bool oneshot = va_arg(args, int);
106     uint64_t length = (((uint64_t)length_hi) << 32) | length_lo;
107 
108     *retValP = osChreTimerSet(length, cookie, oneshot);
109 }
110 
osChreApiTimerCancel(uintptr_t * retValP,va_list args)111 static void osChreApiTimerCancel(uintptr_t *retValP, va_list args)
112 {
113     uint32_t timerId = va_arg(args, uint32_t);
114     *retValP = timTimerCancelEx(timerId, true);
115 }
116 
osChreAbort(uint32_t abortCode)117 static inline void osChreAbort(uint32_t abortCode)
118 {
119     struct Task *task = osGetCurrentTask();
120     osLog(LOG_ERROR, "APP ID=0x%" PRIX64 " TID=0x%" PRIX16 " aborted [code 0x%" PRIX32 "]",
121           task->app->hdr.appId, task->tid, abortCode);
122     osTaskAbort(task);
123 }
124 
osChreApiAbort(uintptr_t * retValP,va_list args)125 static void osChreApiAbort(uintptr_t *retValP, va_list args)
126 {
127     uint32_t code = va_arg(args, uint32_t);
128     osChreAbort(code);
129 }
130 
osChreApiHeapAlloc(uintptr_t * retValP,va_list args)131 static void osChreApiHeapAlloc(uintptr_t *retValP, va_list args)
132 {
133     uint32_t size = va_arg(args, uint32_t);
134     *retValP = (uintptr_t)heapAlloc(size);
135 }
136 
osChreApiHeapFree(uintptr_t * retValP,va_list args)137 static void osChreApiHeapFree(uintptr_t *retValP, va_list args)
138 {
139     void *ptr = va_arg(args, void *);
140     heapFree(ptr);
141 }
142 
143 /*
144  * we have no way to verify if this is a CHRE event; just trust the caller to do the right thing
145  */
osChreFreeEvent(uint32_t tid,chreEventCompleteFunction * cbFreeEvt,uint32_t evtType,void * evtData)146 void osChreFreeEvent(uint32_t tid, chreEventCompleteFunction *cbFreeEvt, uint32_t evtType, void * evtData)
147 {
148     struct Task *chreTask = osTaskFindByTid(tid);
149     struct Task *preempted = osSetCurrentTask(chreTask);
150     if (chreTask && osTaskIsChre(chreTask))
151         osTaskInvokeEventFreeCallback(chreTask, cbFreeEvt, evtType, evtData);
152     osSetCurrentTask(preempted);
153 }
154 
osChreSendEvent(uint16_t evtType,void * evtData,chreEventCompleteFunction * evtFreeCallback,uint32_t toTid)155 static bool osChreSendEvent(uint16_t evtType, void *evtData,
156                             chreEventCompleteFunction *evtFreeCallback,
157                             uint32_t toTid)
158 {
159     /*
160      * this primitive may only be used for USER CHRE events;
161      * system events come from the OS itself through different path,
162      * and are interpreted by the CHRE app compatibility library.
163      * therefore, we have to enforce the evtType >= CHRE_EVENT_FIRST_USER_VALUE.
164      */
165     if (evtType < CHRE_EVENT_FIRST_USER_VALUE) {
166         osChreFreeEvent(osGetCurrentTid(), evtFreeCallback, evtType, evtData);
167         return false;
168     }
169     return osEnqueuePrivateEvtNew(evtType, evtData, evtFreeCallback, toTid);
170 }
171 
osChreApiSendEvent(uintptr_t * retValP,va_list args)172 static void osChreApiSendEvent(uintptr_t *retValP, va_list args)
173 {
174     uint16_t evtType = va_arg(args, uint32_t); // stored as 32-bit
175     void *evtData = va_arg(args, void *);
176     chreEventCompleteFunction *freeCallback = va_arg(args, chreEventCompleteFunction *);
177     uint32_t toTid = va_arg(args, uint32_t);
178     *retValP = osChreSendEvent(evtType, evtData, freeCallback, toTid);
179 }
180 
osChreSendMessageToHost(void * message,uint32_t messageSize,uint32_t reservedMessageType,chreMessageFreeFunction * freeCallback)181 static bool osChreSendMessageToHost(void *message, uint32_t messageSize,
182                            uint32_t reservedMessageType,
183                            chreMessageFreeFunction *freeCallback)
184 {
185     bool result = false;
186     struct HostHubRawPacket *hostMsg = NULL;
187 
188     if (messageSize > CHRE_MESSAGE_TO_HOST_MAX_SIZE || (messageSize && !message))
189         goto out;
190 
191     hostMsg = heapAlloc(sizeof(*hostMsg) + messageSize);
192     if (!hostMsg)
193         goto out;
194 
195     if (messageSize)
196         memcpy(hostMsg+1, message, messageSize);
197 
198     hostMsg->appId = osChreGetAppId();
199     hostMsg->dataLen = messageSize;
200     result = osEnqueueEvtOrFree(EVT_APP_TO_HOST, hostMsg, heapFree);
201 
202 out:
203     if (freeCallback)
204         osTaskInvokeMessageFreeCallback(osGetCurrentTask(), freeCallback, message, messageSize);
205     return result;
206 }
207 
osChreApiSendMessageToHost(uintptr_t * retValP,va_list args)208 static void osChreApiSendMessageToHost(uintptr_t *retValP, va_list args)
209 {
210     void *message = va_arg(args, void *);
211     uint32_t messageSize = va_arg(args, uint32_t);
212     uint32_t reservedMessageType = va_arg(args, uint32_t);
213     chreMessageFreeFunction *freeCallback = va_arg(args, chreMessageFreeFunction *);
214 
215     *retValP = osChreSendMessageToHost(message, messageSize, reservedMessageType, freeCallback);
216 }
217 
osChreSensorFindDefault(uint8_t sensorType,uint32_t * pHandle)218 static bool osChreSensorFindDefault(uint8_t sensorType, uint32_t *pHandle)
219 {
220     if (!pHandle)
221         return false;
222 
223     const struct SensorInfo *info = sensorFind(sensorType, 0, pHandle);
224 
225     return info != NULL;
226 }
227 
osChreApiSensorFindDefault(uintptr_t * retValP,va_list args)228 static void osChreApiSensorFindDefault(uintptr_t *retValP, va_list args)
229 {
230     uint8_t sensorType = va_arg(args, uint32_t);
231     uint32_t *pHandle = va_arg(args, uint32_t *);
232     *retValP = osChreSensorFindDefault(sensorType, pHandle);
233 }
234 
osChreSensorGetInfo(uint32_t sensorHandle,struct chreSensorInfo * info)235 static bool osChreSensorGetInfo(uint32_t sensorHandle, struct chreSensorInfo *info)
236 {
237     struct Sensor *s = sensorFindByHandle(sensorHandle);
238     if (!s || !info)
239         return false;
240     const struct SensorInfo *si = s->si;
241     info->sensorName = si->sensorName;
242     info->sensorType = si->sensorType;
243     info->unusedFlags = 0;
244 
245     if (si->sensorType == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT
246         || si->sensorType == CHRE_SENSOR_TYPE_STATIONARY_DETECT)
247         info->isOneShot = true;
248     else
249         info->isOneShot = false;
250     info->isOnChange = s->hasOnchange;
251 
252     return true;
253 }
254 
osChreApiSensorGetInfo(uintptr_t * retValP,va_list args)255 static void osChreApiSensorGetInfo(uintptr_t *retValP, va_list args)
256 {
257     uint32_t sensorHandle = va_arg(args, uint32_t);
258     struct chreSensorInfo *info = va_arg(args, struct chreSensorInfo *);
259     *retValP = osChreSensorGetInfo(sensorHandle, info);
260 }
261 
osChreSensorGetSamplingStatus(uint32_t sensorHandle,struct chreSensorSamplingStatus * status)262 static bool osChreSensorGetSamplingStatus(uint32_t sensorHandle,
263                                  struct chreSensorSamplingStatus *status)
264 {
265     struct Sensor *s = sensorFindByHandle(sensorHandle);
266     if (!s || !status)
267         return false;
268 
269     if (s->currentRate == SENSOR_RATE_OFF
270         || s->currentRate >= SENSOR_RATE_POWERING_ON) {
271         status->enabled = 0;
272         status->interval = 0;
273         status->latency = 0;
274     } else {
275         status->enabled = true;
276         if (s->currentRate == SENSOR_RATE_ONDEMAND
277             || s->currentRate == SENSOR_RATE_ONCHANGE
278             || s->currentRate == SENSOR_RATE_ONESHOT)
279             status->interval = CHRE_SENSOR_INTERVAL_DEFAULT;
280         else
281             status->interval = (UINT32_C(1024000000) / s->currentRate) * UINT64_C(1000);
282 
283         if (s->currentLatency == SENSOR_LATENCY_NODATA)
284             status->latency = CHRE_SENSOR_INTERVAL_DEFAULT;
285         else
286             status->latency = s->currentLatency;
287     }
288 
289     return true;
290 }
291 
osChreApiSensorGetStatus(uintptr_t * retValP,va_list args)292 static void osChreApiSensorGetStatus(uintptr_t *retValP, va_list args)
293 {
294     uint32_t sensorHandle = va_arg(args, uint32_t);
295     struct chreSensorSamplingStatus *status = va_arg(args, struct chreSensorSamplingStatus *);
296     *retValP = osChreSensorGetSamplingStatus(sensorHandle, status);
297 }
298 
osChreSensorConfigure(uint32_t sensorHandle,enum chreSensorConfigureMode mode,uint64_t interval,uint64_t latency)299 static bool osChreSensorConfigure(uint32_t sensorHandle,
300                          enum chreSensorConfigureMode mode,
301                          uint64_t interval, uint64_t latency)
302 {
303     uint32_t rate, interval_us;
304     bool ret;
305     struct Sensor *s = sensorFindByHandle(sensorHandle);
306     int i;
307     if (!s)
308         return false;
309 
310     if (mode & CHRE_SENSOR_CONFIGURE_RAW_POWER_ON) {
311         if (interval == CHRE_SENSOR_INTERVAL_DEFAULT) {
312             // use first rate in supported rates list > minimum (if avaliable)
313             const struct SensorInfo *si = s->si;
314             if (!si)
315                 return false;
316 
317             if (!si->supportedRates || si->supportedRates[0] == 0)
318                 rate = SENSOR_RATE_ONCHANGE;
319             else {
320                 for (i = 0; si->supportedRates[i] != 0; i++) {
321                     rate = si->supportedRates[i];
322                     if (rate >= MINIMUM_INTERVAL_DEFAULT_HZ)
323                         break;
324                 }
325             }
326         } else {
327             interval_us = U64_DIV_BY_CONST_U16(interval, 1000);
328             rate = UINT32_C(1024000000) / interval_us;
329         }
330         if (!rate) // 0 is a reserved value. minimum is 1
331             rate = 1;
332         if (latency == CHRE_SENSOR_LATENCY_DEFAULT)
333             latency = 0ULL;
334         if (sensorGetReqRate(sensorHandle) == SENSOR_RATE_OFF) {
335             if ((ret = sensorRequest(0, sensorHandle, rate, latency))) {
336                 if (!(ret = osEventsSubscribe(2, sensorGetMyEventType(s->si->sensorType), sensorGetMyCfgEventType(s->si->sensorType))))
337                     sensorRelease(0, sensorHandle);
338             }
339         } else {
340             ret = sensorRequestRateChange(0, sensorHandle, rate, latency);
341         }
342     } else if (mode & (CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS|CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT)) {
343         if (interval != CHRE_SENSOR_INTERVAL_DEFAULT
344             || latency != CHRE_SENSOR_LATENCY_DEFAULT)
345             ret = false;
346         else if (sensorGetReqRate(sensorHandle) == SENSOR_RATE_OFF)
347             ret = osEventsSubscribe(2, sensorGetMyEventType(s->si->sensorType), sensorGetMyCfgEventType(s->si->sensorType));
348         else
349             ret = true;
350     } else {
351         if (sensorGetReqRate(sensorHandle) != SENSOR_RATE_OFF) {
352             if ((ret = sensorRelease(0, sensorHandle)))
353                 ret = osEventsUnsubscribe(2, sensorGetMyEventType(s->si->sensorType), sensorGetMyCfgEventType(s->si->sensorType));
354         } else {
355             ret = osEventsUnsubscribe(2, sensorGetMyEventType(s->si->sensorType), sensorGetMyCfgEventType(s->si->sensorType));
356         }
357     }
358 
359     return ret;
360 }
361 
osChreApiSensorConfig(uintptr_t * retValP,va_list args)362 static void osChreApiSensorConfig(uintptr_t *retValP, va_list args)
363 {
364     uint32_t sensorHandle = va_arg(args, uint32_t);
365     enum chreSensorConfigureMode mode = va_arg(args, int);
366     uint64_t interval = va_arg(args, uint32_t);
367     uint32_t interval_hi = va_arg(args, uint32_t);
368     uint64_t latency = va_arg(args, uint32_t);
369     uint32_t latency_hi = va_arg(args, uint32_t);
370 
371     interval |= ((uint64_t)interval_hi) << 32;
372     latency  |= ((uint64_t)latency_hi) << 32;
373 
374     *retValP = osChreSensorConfigure(sensorHandle, mode, interval, latency);
375 }
376 
osChreGetApiVersion(void)377 static uint32_t osChreGetApiVersion(void)
378 {
379     return CHRE_API_VERSION;
380 }
381 
osChreApiChreApiVersion(uintptr_t * retValP,va_list args)382 static void osChreApiChreApiVersion(uintptr_t *retValP, va_list args)
383 {
384     *retValP = osChreGetApiVersion();
385 }
386 
osChreGetVersion(void)387 static uint32_t osChreGetVersion(void)
388 {
389     return CHRE_API_VERSION | NANOHUB_OS_PATCH_LEVEL;
390 }
391 
osChreApiChreOsVersion(uintptr_t * retValP,va_list args)392 static void osChreApiChreOsVersion(uintptr_t *retValP, va_list args)
393 {
394     *retValP = (uintptr_t)osChreGetVersion();
395 }
396 
osChreGetPlatformId(void)397 static uint64_t osChreGetPlatformId(void)
398 {
399     return HW_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0);
400 }
401 
osChreApiPlatformId(uintptr_t * retValP,va_list args)402 static void osChreApiPlatformId(uintptr_t *retValP, va_list args)
403 {
404     uint64_t *pHwId = va_arg(args, uint64_t*);
405     if (pHwId)
406         *pHwId = osChreGetPlatformId();
407 }
408 
409 static const struct SyscallTable chreMainApiTable = {
410     .numEntries = SYSCALL_CHRE_MAIN_API_LAST,
411     .entry = {
412         [SYSCALL_CHRE_MAIN_API_LOG]                     = { .func = osChreApiLogLogv },
413         [SYSCALL_CHRE_MAIN_API_GET_APP_ID]              = { .func = osChreApiGetAppId },
414         [SYSCALL_CHRE_MAIN_API_GET_INST_ID]             = { .func = osChreApiGetInstanceId },
415         [SYSCALL_CHRE_MAIN_API_GET_TIME]                = { .func = osChreApiGetTime },
416         [SYSCALL_CHRE_MAIN_API_TIMER_SET]               = { .func = osChreApiTimerSet },
417         [SYSCALL_CHRE_MAIN_API_TIMER_CANCEL]            = { .func = osChreApiTimerCancel },
418         [SYSCALL_CHRE_MAIN_API_ABORT]                   = { .func = osChreApiAbort },
419         [SYSCALL_CHRE_MAIN_API_HEAP_ALLOC]              = { .func = osChreApiHeapAlloc },
420         [SYSCALL_CHRE_MAIN_API_HEAP_FREE]               = { .func = osChreApiHeapFree },
421         [SYSCALL_CHRE_MAIN_API_SEND_EVENT]              = { .func = osChreApiSendEvent },
422         [SYSCALL_CHRE_MAIN_API_SEND_MSG]                = { .func = osChreApiSendMessageToHost },
423         [SYSCALL_CHRE_MAIN_API_SENSOR_FIND_DEFAULT]     = { .func = osChreApiSensorFindDefault },
424         [SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO]         = { .func = osChreApiSensorGetInfo },
425         [SYSCALL_CHRE_MAIN_API_SENSOR_GET_STATUS]       = { .func = osChreApiSensorGetStatus },
426         [SYSCALL_CHRE_MAIN_API_SENSOR_CONFIG]           = { .func = osChreApiSensorConfig },
427         [SYSCALL_CHRE_MAIN_API_GET_OS_API_VERSION]      = { .func = osChreApiChreApiVersion },
428         [SYSCALL_CHRE_MAIN_API_GET_OS_VERSION]          = { .func = osChreApiChreOsVersion },
429         [SYSCALL_CHRE_MAIN_API_GET_PLATFORM_ID]         = { .func = osChreApiPlatformId },
430     },
431 };
432 
433 static const struct SyscallTable chreMainTable = {
434     .numEntries = SYSCALL_CHRE_MAIN_LAST,
435     .entry = {
436         [SYSCALL_CHRE_MAIN_API]     = { .subtable = (struct SyscallTable*)&chreMainApiTable,     },
437     },
438 };
439 
440 static const struct SyscallTable chreTable = {
441     .numEntries = SYSCALL_CHRE_LAST,
442     .entry = {
443         [SYSCALL_CHRE_MAIN]    = { .subtable = (struct SyscallTable*)&chreMainTable,    },
444     },
445 };
446 
osChreApiExport()447 void osChreApiExport()
448 {
449     if (!syscallAddTable(SYSCALL_NO(SYSCALL_DOMAIN_CHRE,0,0,0), 1, (struct SyscallTable*)&chreTable))
450             osLog(LOG_ERROR, "Failed to export CHRE OS API");
451 }
452