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