Home | History | Annotate | Download | only in core
      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