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