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 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 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 67 static void osChreApiGetInstanceId(uintptr_t *retValP, va_list args) 68 { 69 *retValP = osGetCurrentTid(); 70 } 71 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 377 static uint32_t osChreGetApiVersion(void) 378 { 379 return CHRE_API_VERSION; 380 } 381 382 static void osChreApiChreApiVersion(uintptr_t *retValP, va_list args) 383 { 384 *retValP = osChreGetApiVersion(); 385 } 386 387 static uint32_t osChreGetVersion(void) 388 { 389 return CHRE_API_VERSION | NANOHUB_OS_PATCH_LEVEL; 390 } 391 392 static void osChreApiChreOsVersion(uintptr_t *retValP, va_list args) 393 { 394 *retValP = (uintptr_t)osChreGetVersion(); 395 } 396 397 static uint64_t osChreGetPlatformId(void) 398 { 399 return HW_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0); 400 } 401 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 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