diff options
41 files changed, 1489 insertions, 1971 deletions
diff --git a/contexthubhal/nanohubhal.h b/contexthubhal/nanohubhal.h index 68446e46..6a0432c8 100644 --- a/contexthubhal/nanohubhal.h +++ b/contexthubhal/nanohubhal.h @@ -37,7 +37,7 @@ namespace nanohub { void dumpBuffer(const char *pfx, const hub_app_name_t &appId, uint32_t evtId, const void *data, size_t len, int status = 0); struct nano_message_chre { - HostMsgHdrChre hdr; + HostMsgHdrChreV10 hdr; uint8_t data[MAX_RX_PACKET]; } __attribute__((packed)); @@ -115,7 +115,7 @@ class NanoHub { int doSubscribeMessages(uint32_t hub_id, context_hub_callback *cbk, void *cookie); int doSendToNanohub(uint32_t hub_id, const hub_message_t *msg); - int doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len, uint32_t messageType); + int doSendToDevice(const hub_app_name_t name, const void *data, uint32_t len, uint32_t messageType = 0); void doSendToApp(HubMessage &&msg); static constexpr unsigned int FL_MESSAGE_TRACING = 1; @@ -148,7 +148,7 @@ public: } // passes message to kernel driver directly static int sendToDevice(const hub_app_name_t *name, const void *data, uint32_t len) { - return hubInstance()->doSendToDevice(*name, data, len, 0); + return hubInstance()->doSendToDevice(*name, data, len); } // passes message to APP via callback static void sendToApp(HubMessage &&msg) { diff --git a/contexthubhal/system_comms.cpp b/contexthubhal/system_comms.cpp index 4a67a669..b0e4bc9b 100644 --- a/contexthubhal/system_comms.cpp +++ b/contexthubhal/system_comms.cpp @@ -90,7 +90,10 @@ NanohubRsp::NanohubRsp(MessageBuf &buf, bool no_status) } else if (no_status) { status = 0; } else { - status = buf.readU32(); + if (cmd == NANOHUB_START_UPLOAD || cmd == NANOHUB_CONT_UPLOAD || cmd == NANOHUB_FINISH_UPLOAD) + status = buf.readU8(); + else + status = buf.readU32(); } } @@ -273,6 +276,8 @@ int SystemComm::AppMgmtSession::setup(const hub_message_t *appMsg) mCmd = appMsg->message_type; mLen = appMsg->message_len; mPos = 0; + mNextPos = 0; + mErrCnt = 0; switch (mCmd) { case CONTEXT_HUB_APPS_ENABLE: @@ -361,10 +366,20 @@ int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp) char data[MAX_RX_PACKET]; MessageBuf buf(data, sizeof(data)); + const bool success = rsp.status != 0; static_assert(NANOHUB_UPLOAD_CHUNK_SZ_MAX <= (MAX_RX_PACKET-5), "Invalid chunk size"); + if (success) { + mPos = mNextPos; + mErrCnt = 0; + } else if (mErrCnt > 5) { + mPos = mLen; + } else { + mErrCnt ++; + } + if (mPos < mLen) { uint32_t chunkSize = mLen - mPos; @@ -375,7 +390,7 @@ int SystemComm::AppMgmtSession::handleTransfer(NanohubRsp &rsp) buf.writeU8(NANOHUB_CONT_UPLOAD); buf.writeU32(mPos); buf.writeRaw(&mData[mPos], chunkSize); - mPos += chunkSize; + mNextPos = mPos + chunkSize; } else { buf.writeU8(NANOHUB_FINISH_UPLOAD); setState(FINISH); diff --git a/contexthubhal/system_comms.h b/contexthubhal/system_comms.h index e1b08e3e..6991457e 100644 --- a/contexthubhal/system_comms.h +++ b/contexthubhal/system_comms.h @@ -204,6 +204,8 @@ private: std::vector<uint8_t> mData; uint32_t mLen; uint32_t mPos; + uint32_t mNextPos; + uint32_t mErrCnt; hub_app_name_t mAppName; int setupMgmt(const hub_message_t *appMsg, uint32_t cmd); diff --git a/firmware/app/chre/chre.mk b/firmware/app/chre/chre.mk index a1476771..aed3ce78 100644 --- a/firmware/app/chre/chre.mk +++ b/firmware/app/chre/chre.mk @@ -21,12 +21,13 @@ SRCS += $(NANOHUB_DIR)/app/chre/common/chre_app.c SRCS += $(NANOHUB_DIR)/app/chre/common/chre_app_syscalls.c -CFLAGS += -I$(NANOHUB_DIR)/../inc include $(NANOHUB_DIR)/firmware_conf.mk CFLAGS += $(COMMON_FLAGS) -BIN_POSTPROCESS_ARGS := -f 0x10 +# CHRE API 1.1 +BIN_POSTPROCESS_ARGS := -c 0x0101 +CFLAGS += -I$(NANOHUB_DIR)/../../../../system/chre/chre_api/include/chre_api include $(NANOHUB_DIR)/app/app.mk diff --git a/firmware/app/chre/chre10.mk b/firmware/app/chre/chre10.mk new file mode 100644 index 00000000..f09d1849 --- /dev/null +++ b/firmware/app/chre/chre10.mk @@ -0,0 +1,33 @@ +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +# +# NanoApp C/C++ Makefile Utils +# +################################################################################ + +SRCS += $(NANOHUB_DIR)/app/chre/common/chre10_app.c +SRCS += $(NANOHUB_DIR)/app/chre/common/chre10_app_syscalls.c + +include $(NANOHUB_DIR)/firmware_conf.mk + +CFLAGS += $(COMMON_FLAGS) + +# CHRE API 1.0 +BIN_POSTPROCESS_ARGS := -c 0x0100 +CFLAGS += -I$(NANOHUB_DIR)/../../../../system/chre/chre_api/legacy/v1_0 + +include $(NANOHUB_DIR)/app/app.mk diff --git a/firmware/app/chre/chre_test0.app/main.c b/firmware/app/chre/chre_test0.app/main.c index acdba524..03e6d8d8 100644 --- a/firmware/app/chre/chre_test0.app/main.c +++ b/firmware/app/chre/chre_test0.app/main.c @@ -39,7 +39,7 @@ static const uint64_t kOneSecond = UINT64_C(1000000000); // in nanoseconds static uint32_t mMyTid; static uint64_t mMyAppId; -static int cnt; +static int mCnt; static struct MyTimer mTimer; static void nanoappFreeEvent(uint16_t eventType, void *data) @@ -60,7 +60,7 @@ bool nanoappStart(void) { mMyAppId = chreGetAppId(); mMyTid = chreGetInstanceId(); - cnt = 3; + mCnt = 3; chreSendEvent(EVT_LOCAL_SETUP, (void*)0x87654321, nanoappFreeEvent, mMyTid); chreLog(CHRE_LOG_INFO, CHRE_APP_TAG "init\n"); return true; @@ -86,11 +86,11 @@ void nanoappHandleEvent(uint32_t srcTid, uint16_t evtType, const void* evtData) chreLog(CHRE_LOG_INFO, CHRE_APP_TAG "received timer %" PRIu32 " (TIME: %" PRIu64 - ") cnt: %d\n", t->timerId, chreGetTime(), cnt); + ") cnt: %d\n", t->timerId, chreGetTime(), mCnt); extMsg->msg = 0x01; - extMsg->val = cnt; + extMsg->val = mCnt; chreSendMessageToHost(extMsg, sizeof(*extMsg), 0, nanoappFreeMessage); - if (cnt-- <= 0) + if (mCnt-- <= 0) chreTimerCancel(t->timerId); break; } diff --git a/firmware/app/chre/chre_test1.app/main.cpp b/firmware/app/chre/chre_test1.app/main.cpp index 22a33ce6..201448a9 100644 --- a/firmware/app/chre/chre_test1.app/main.cpp +++ b/firmware/app/chre/chre_test1.app/main.cpp @@ -39,7 +39,7 @@ static const uint64_t kOneSecond = UINT64_C(1000000000); // in nanoseconds static uint32_t mMyTid; static uint64_t mMyAppId; -static int cnt; +static int mCnt; static struct MyTimer mTimer; // Default implementation for message free @@ -52,7 +52,7 @@ bool nanoappStart(void) { mMyAppId = chreGetAppId(); mMyTid = chreGetInstanceId(); - cnt = 3; + mCnt = 3; chreSendEvent(EVT_LOCAL_SETUP, NULL, NULL, mMyTid); chreLog(CHRE_LOG_INFO, APP_LABEL "init"); return true; @@ -99,11 +99,11 @@ void nanoappHandleEvent(uint32_t srcTid, uint16_t evtType, const void* evtData) chreLog(CHRE_LOG_INFO, APP_LABEL "received timer %" PRIu32 " (TIME: %" PRIu64 - ") cnt: %d\n", t->timerId, chreGetTime(), cnt); + ") cnt: %d\n", t->timerId, chreGetTime(), mCnt); extMsg->msg = 0x01; - extMsg->val = cnt; + extMsg->val = mCnt; chreSendMessageToHost(extMsg, sizeof(*extMsg), 0, nanoappFreeMessage); - if (cnt-- <= 0) + if (mCnt-- <= 0) chreTimerCancel(t->timerId); break; } diff --git a/firmware/app/chre/chre_test2.app/Android.mk b/firmware/app/chre/chre_test2.app/Android.mk new file mode 100644 index 00000000..0a471f19 --- /dev/null +++ b/firmware/app/chre/chre_test2.app/Android.mk @@ -0,0 +1,31 @@ +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_NANO_VARS) + +LOCAL_MODULE := chre_test2 +LOCAL_MODULE_TAGS := optional + +# Googl + T + 0x9002 +LOCAL_NANO_APP_ID := 476f6f676c549002 +LOCAL_NANO_APP_VERSION := 0 + +LOCAL_SRC_FILES := \ + main.cpp \ + +include $(BUILD_NANOHUB_APP_CHRE_EXECUTABLE) diff --git a/firmware/app/chre/chre_test2.app/Makefile b/firmware/app/chre/chre_test2.app/Makefile new file mode 100644 index 00000000..45819ffa --- /dev/null +++ b/firmware/app/chre/chre_test2.app/Makefile @@ -0,0 +1,38 @@ +# +# Copyright (C) 2016 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +################################################################################ +# +# test NanoApp Makefile +# +################################################################################ + + +SRCS := main.cpp +BIN := chre_test2 +APP_ID := 476f6f676c549002 +APP_VERSION := 0 + +# Nanohub relative path +NANOHUB_DIR := ../../.. + +# Device configuration ######################################################### + +# select device variant for this app +TARGET_PRODUCT ?= nucleo +VARIANT := $(TARGET_PRODUCT) + +include $(NANOHUB_DIR)/app/chre/chre.mk diff --git a/firmware/app/chre/chre_test2.app/main.cpp b/firmware/app/chre/chre_test2.app/main.cpp new file mode 100644 index 00000000..427221fb --- /dev/null +++ b/firmware/app/chre/chre_test2.app/main.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <inttypes.h> +#include <chre.h> + +#define APP_LABEL "CHRE App 2: " + +/* chre.h does not define printf format attribute for chreLog() */ +void chreLog(enum chreLogLevel level, const char *str, ...) __attribute__ ((__format__ (__printf__, 2, 3))); + +#define EVT_LOCAL_SETUP CHRE_EVENT_FIRST_USER_VALUE + +struct MyTimer { + uint64_t startTime; + uint32_t timerId; +}; + +struct ExtMsg +{ + uint8_t msg; + uint32_t val; +} __attribute__((packed)); + +static const uint64_t kOneSecond = UINT64_C(1000000000); // in nanoseconds + +static uint32_t mMyTid; +static uint64_t mMyAppId; +static int mCnt; +static struct MyTimer mTimer; + +bool nanoappStart(void) +{ + mMyAppId = chreGetAppId(); + mMyTid = chreGetInstanceId(); + mCnt = 3; + chreSendEvent(EVT_LOCAL_SETUP, NULL, NULL, mMyTid); + chreLog(CHRE_LOG_INFO, APP_LABEL "init: offset: %" PRId64, chreGetEstimatedHostTimeOffset()); + chreConfigureNanoappInfoEvents(true); + return true; +} + +void nanoappEnd(void) +{ + chreLog(CHRE_LOG_INFO, APP_LABEL "terminating"); +} + +void nanoappHandleEvent(uint32_t srcTid, uint16_t evtType, const void* evtData) +{ + switch (evtType) { + case EVT_LOCAL_SETUP: + { + uint32_t instanceId = chreGetInstanceId(); + uint64_t appId = chreGetAppId(); + struct chreNanoappInfo info; + + mTimer.startTime = chreGetTime(); + mTimer.timerId = chreTimerSet(kOneSecond, &mTimer, false); + chreLog(CHRE_LOG_INFO, APP_LABEL "started with tid %04" PRIX32 + " timerid %" PRIu32 + "\n", mMyTid, mTimer.timerId); + chreLog(CHRE_LOG_INFO, APP_LABEL "appId=%016llx; instanceId=%ld", + appId, instanceId); + if (chreGetNanoappInfoByInstanceId(instanceId, &info)) { + chreLog(CHRE_LOG_INFO, APP_LABEL "info by instanceId; appId=%08llx; version=%ld; instanceId=%ld", + info.appId, info.version, info.instanceId); + } else { + chreLog(CHRE_LOG_INFO, APP_LABEL "error getting info by instance id"); + } + if (chreGetNanoappInfoByAppId(appId, &info)) { + chreLog(CHRE_LOG_INFO, APP_LABEL "info by appId; appId=%08llx; version=%ld; instanceId=%ld", + info.appId, info.version, info.instanceId); + } else { + chreLog(CHRE_LOG_INFO, APP_LABEL "error getting info by app id"); + } + break; + } + case CHRE_EVENT_TIMER: + { + const struct MyTimer *t = (const struct MyTimer *)evtData; + + chreLog(CHRE_LOG_INFO, APP_LABEL "received timer %" PRIu32 + " (START: %" PRIu64 " TIME: %" PRIu64 " OFFSET: %" PRId64 + ") cnt: %d\n", t->timerId, t->startTime, chreGetTime(), + chreGetEstimatedHostTimeOffset(), mCnt); + if (mCnt-- <= 0) { + chreTimerCancel(t->timerId); + chreAbort(0x0001); + chreAbort(0x0002); + } + break; + } + case CHRE_EVENT_MESSAGE_FROM_HOST: + { + const struct chreMessageFromHostData *msg = (const struct chreMessageFromHostData *)evtData; + const uint8_t *data = (const uint8_t *)msg->message; + const size_t size = msg->messageSize; + const uint32_t type = msg->messageType; + const uint16_t endpoint = msg->hostEndpoint; + chreLog(CHRE_LOG_INFO, APP_LABEL "message=%p; code=%d; size=%zu; type=%ld; endpoint=%d", + data, (data && size) ? data[0] : 0, size, type, endpoint); + break; + } + case CHRE_EVENT_NANOAPP_STARTED: + { + const struct chreNanoappInfo *msg = (const struct chreNanoappInfo *)evtData; + const uint64_t appId = msg->appId; + const uint32_t version = msg->version; + const uint32_t instanceId = msg->instanceId; + chreLog(CHRE_LOG_INFO, APP_LABEL "app started; appId=%08llx; version=%ld; instanceId=%ld", + appId, version, instanceId); + break; + } + case CHRE_EVENT_NANOAPP_STOPPED: + { + const struct chreNanoappInfo *msg = (const struct chreNanoappInfo *)evtData; + const uint64_t appId = msg->appId; + const uint32_t version = msg->version; + const uint32_t instanceId = msg->instanceId; + chreLog(CHRE_LOG_INFO, APP_LABEL "app stopped; appId=%08llx; version=%ld; instanceId=%ld", + appId, version, instanceId); + break; + } + } +} diff --git a/firmware/app/chre/common/chre10_app.c b/firmware/app/chre/common/chre10_app.c new file mode 100644 index 00000000..55bbdf2f --- /dev/null +++ b/firmware/app/chre/common/chre10_app.c @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <eventnums.h> +#include <seos.h> +#include <timer.h> +#include <toolchain.h> +#include <crt_priv.h> +#include <string.h> + +#include <chre.h> +#include <sensors.h> +#include <syscallDo.h> +#include <hostIntf.h> + +#define SENSOR_TYPE(x) ((x) & 0xFF) + +/* + * Common CHRE App support code + */ + +static bool chreappStart(uint32_t tid) +{ + __crt_init(); + return nanoappStart(); +} + +static void chreappEnd(void) +{ + nanoappEnd(); + __crt_exit(); +} + +static void initDataHeader(struct chreSensorDataHeader *header, uint64_t timestamp, uint32_t sensorHandle) { + header->baseTimestamp = timestamp; + header->sensorHandle = sensorHandle; + header->readingCount = 1; + header->reserved[0] = header->reserved[1] = 0; +} + +static void processTripleAxisData(const struct TripleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType) +{ + int i; + struct chreSensorThreeAxisData three; + + initDataHeader(&three.header, src->referenceTime, sensorHandle); + three.readings[0].timestampDelta = 0; + + for (i=0; i<src->samples[0].firstSample.numSamples; i++) { + if (i > 0) + three.header.baseTimestamp += src->samples[i].deltaTime; + three.readings[0].x = src->samples[i].x; + three.readings[0].y = src->samples[i].y; + three.readings[0].z = src->samples[i].z; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &three); + } +} + +static void processSingleAxisData(const struct SingleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType) +{ + int i; + + switch (sensorType) { + case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT: + case CHRE_SENSOR_TYPE_STATIONARY_DETECT: { + struct chreSensorOccurrenceData occ; + + initDataHeader(&occ.header, src->referenceTime, sensorHandle); + occ.readings[0].timestampDelta = 0; + + for (i=0; i<src->samples[0].firstSample.numSamples; i++) { + if (i > 0) + occ.header.baseTimestamp += src->samples[i].deltaTime; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ); + } + break; + } + case CHRE_SENSOR_TYPE_LIGHT: + case CHRE_SENSOR_TYPE_PRESSURE: { + struct chreSensorFloatData flt; + + initDataHeader(&flt.header, src->referenceTime, sensorHandle); + flt.readings[0].timestampDelta = 0; + + for (i=0; i<src->samples[0].firstSample.numSamples; i++) { + if (i > 0) + flt.header.baseTimestamp += src->samples[i].deltaTime; + flt.readings[0].value = src->samples[i].fdata; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt); + } + break; + } + case CHRE_SENSOR_TYPE_PROXIMITY: { + struct chreSensorByteData byte; + + initDataHeader(&byte.header, src->referenceTime, sensorHandle); + byte.readings[0].timestampDelta = 0; + + for (i=0; i<src->samples[0].firstSample.numSamples; i++) { + if (i > 0) + byte.header.baseTimestamp += src->samples[i].deltaTime; + byte.readings[0].isNear = src->samples[i].fdata == 0.0f; + byte.readings[0].invalid = false; + byte.readings[0].padding0 = 0; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte); + } + break; + } + } +} + +static void processEmbeddedData(const void *src, uint32_t sensorHandle, uint8_t sensorType) +{ + union EmbeddedDataPoint data = (union EmbeddedDataPoint)((void *)src); + + switch (sensorType) { + case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT: + case CHRE_SENSOR_TYPE_STATIONARY_DETECT: { + struct chreSensorOccurrenceData occ; + + initDataHeader(&occ.header, eOsSensorGetTime(), sensorHandle); + occ.readings[0].timestampDelta = 0; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ); + break; + } + case CHRE_SENSOR_TYPE_LIGHT: + case CHRE_SENSOR_TYPE_PRESSURE: { + struct chreSensorFloatData flt; + + initDataHeader(&flt.header, eOsSensorGetTime(), sensorHandle); + flt.readings[0].timestampDelta = 0; + flt.readings[0].value = data.fdata; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt); + break; + } + case CHRE_SENSOR_TYPE_PROXIMITY: { + struct chreSensorByteData byte; + + initDataHeader(&byte.header, eOsSensorGetTime(), sensorHandle); + byte.readings[0].timestampDelta = 0; + byte.readings[0].isNear = data.fdata == 0.0f; + byte.readings[0].invalid = false; + byte.readings[0].padding0 = 0; + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte); + break; + } + } +} + +static void chreappProcessSensorData(uint16_t evt, const void *eventData) +{ + const struct SensorInfo *si; + uint32_t sensorHandle; + + if (eventData == SENSOR_DATA_EVENT_FLUSH) + return; + + si = eOsSensorFind(SENSOR_TYPE(evt), 0, &sensorHandle); + if (si && eOsSensorGetReqRate(sensorHandle)) { + switch (si->numAxis) { + case NUM_AXIS_EMBEDDED: + processEmbeddedData(eventData, sensorHandle, SENSOR_TYPE(evt)); + break; + case NUM_AXIS_ONE: + processSingleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt)); + break; + case NUM_AXIS_THREE: + processTripleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt)); + break; + } + + if (SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT + || SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_STATIONARY_DETECT) { + // one-shot, disable after receiving sample + chreSensorConfigure(sensorHandle, CHRE_SENSOR_CONFIGURE_MODE_DONE, CHRE_SENSOR_INTERVAL_DEFAULT, CHRE_SENSOR_LATENCY_DEFAULT); + } + } +} + +static void chreappProcessConfigEvt(uint16_t evt, const void *eventData) +{ + const struct SensorRateChangeEvent *msg = eventData; + struct chreSensorSamplingStatusEvent change; + + change.sensorHandle = msg->sensorHandle; + if (!msg->newRate) { + change.status.enabled = 0; + change.status.interval = 0; + change.status.latency = 0; + } else { + change.status.enabled = true; + if (msg->newRate == SENSOR_RATE_ONDEMAND + || msg->newRate == SENSOR_RATE_ONCHANGE + || msg->newRate == SENSOR_RATE_ONESHOT) + change.status.interval = CHRE_SENSOR_INTERVAL_DEFAULT; + else + change.status.interval = (UINT32_C(1024000000) / msg->newRate) * UINT64_C(1000); + + if (msg->newLatency == SENSOR_LATENCY_NODATA) + change.status.latency = CHRE_SENSOR_INTERVAL_DEFAULT; + else + change.status.latency = msg->newLatency; + } + + nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_SAMPLING_CHANGE, &change); +} + +static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData) +{ + uint16_t evt = eventTypeAndTid; + uint16_t srcTid = eventTypeAndTid >> 16; + const void *data = eventData; + + union EventLocalData { + struct chreMessageFromHostData msg; + } u; + + switch(evt) { + case EVT_APP_TIMER: + evt = CHRE_EVENT_TIMER; + data = ((struct TimerEvent *)eventData)->data; + break; + case EVT_APP_FROM_HOST: + srcTid = CHRE_INSTANCE_ID; + evt = CHRE_EVENT_MESSAGE_FROM_HOST; + data = &u.msg; + u.msg.message = (uint8_t*)eventData + 1; + u.msg.reservedMessageType = 0; + u.msg.messageSize = *(uint8_t*)eventData; + break; + case EVT_APP_FROM_HOST_CHRE: + { + const struct NanohubMsgChreHdr *hdr = eventData; + srcTid = CHRE_INSTANCE_ID; + evt = CHRE_EVENT_MESSAGE_FROM_HOST; + data = &u.msg; + u.msg.message = hdr + 1; + u.msg.reservedMessageType = hdr->appEvent; + u.msg.messageSize = hdr->size; + break; + } + case EVT_APP_SENSOR_SELF_TEST: + case EVT_APP_SENSOR_MARSHALL: + case EVT_APP_SENSOR_SEND_ONE_DIR_EVT: + case EVT_APP_SENSOR_CFG_DATA: + case EVT_APP_SENSOR_CALIBRATE: + case EVT_APP_SENSOR_TRIGGER: + case EVT_APP_SENSOR_FLUSH: + case EVT_APP_SENSOR_SET_RATE: + case EVT_APP_SENSOR_FW_UPLD: + case EVT_APP_SENSOR_POWER: + // sensor events; pass through + break; + default: + // ignore any other system events; OS may send them to any app + if (evt < EVT_NO_FIRST_USER_EVENT) + return; + else if (evt > EVT_NO_FIRST_SENSOR_EVENT && evt < EVT_NO_SENSOR_CONFIG_EVENT) { + return chreappProcessSensorData(evt, data); + } else if (evt > EVT_NO_SENSOR_CONFIG_EVENT && evt < EVT_APP_START) { + return chreappProcessConfigEvt(evt, data); + } + } + nanoappHandleEvent(srcTid, evt, data); +} + +// Collect entry points +const struct AppFuncs SET_EXTERNAL_APP_ATTRIBUTES(used, section (".app_init"),visibility("default")) _mAppFuncs = { + .init = chreappStart, + .end = chreappEnd, + .handle = chreappHandle, +}; + +// declare version for compatibility with current runtime +const uint32_t SET_EXTERNAL_APP_VERSION(used, section (".app_version"), visibility("default")) _mAppVer = 0; diff --git a/firmware/app/chre/common/chre10_app_syscalls.c b/firmware/app/chre/common/chre10_app_syscalls.c new file mode 100644 index 00000000..666bdaed --- /dev/null +++ b/firmware/app/chre/common/chre10_app_syscalls.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdarg.h> + +#include <gpio.h> +#include <osApi.h> +#include <sensors.h> +#include <seos.h> +#include <util.h> + +/* CHRE syscalls */ +#include <chre.h> +#include <chreApi.h> +#include <syscall.h> +#include <syscall_defs.h> + +#define SYSCALL_CHRE_API(name) \ + SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_API, SYSCALL_CHRE_MAIN_API_ ## name) + +uint64_t chreGetAppId(void) +{ + uint64_t appId = 0; + (void)syscallDo1P(SYSCALL_CHRE_API(GET_APP_ID), &appId); + return appId; +} + +uint32_t chreGetInstanceId(void) +{ + return syscallDo0P(SYSCALL_CHRE_API(GET_INST_ID)); +} + +uint64_t chreGetTime(void) { + uint64_t time_ns = 0; + (void)syscallDo1P(SYSCALL_CHRE_API(GET_TIME), &time_ns); + return time_ns; +} + +void chreLog(enum chreLogLevel level, const char *str, ...) +{ + va_list vl; + + va_start(vl, str); + (void)syscallDo3P(SYSCALL_CHRE_API(LOG), level, str, VA_LIST_TO_INTEGER(vl)); + va_end(vl); +} + +uint32_t chreTimerSet(uint64_t duration, const void* cookie, bool oneShot) +{ + uint32_t dur_lo = duration; + uint32_t dur_hi = duration >> 32; + return syscallDo4P(SYSCALL_CHRE_API(TIMER_SET), dur_lo, dur_hi, cookie, oneShot); +} + +bool chreTimerCancel(uint32_t timerId) +{ + return syscallDo1P(SYSCALL_CHRE_API(TIMER_CANCEL), timerId); +} + +void chreAbort(uint32_t abortCode) +{ + (void)syscallDo1P(SYSCALL_CHRE_API(ABORT), abortCode); +} + +void* chreHeapAlloc(uint32_t bytes) +{ + return (void *)syscallDo1P(SYSCALL_CHRE_API(HEAP_ALLOC), bytes); +} + +void chreHeapFree(void* ptr) +{ + (void)syscallDo1P(SYSCALL_CHRE_API(HEAP_FREE), ptr); +} + +bool chreSensorFindDefault(uint8_t sensorType, uint32_t *handle) +{ + return syscallDo2P(SYSCALL_CHRE_API(SENSOR_FIND_DEFAULT), sensorType, handle); +} + +bool chreGetSensorInfo(uint32_t sensorHandle, struct chreSensorInfo *info) +{ + return syscallDo2P(SYSCALL_CHRE_API(SENSOR_GET_INFO), sensorHandle, info); +} + +bool chreGetSensorSamplingStatus(uint32_t sensorHandle, + struct chreSensorSamplingStatus *status) +{ + return syscallDo2P(SYSCALL_CHRE_API(SENSOR_GET_STATUS), sensorHandle, status); +} + +bool chreSensorConfigure(uint32_t sensorHandle, + enum chreSensorConfigureMode mode, + uint64_t interval, uint64_t latency) +{ + uint32_t interval_lo = interval; + uint32_t interval_hi = interval >> 32; + uint32_t latency_lo = latency; + uint32_t latency_hi = latency >> 32; + return syscallDo6P(SYSCALL_CHRE_API(SENSOR_CONFIG), sensorHandle, mode, + interval_lo, interval_hi, latency_lo, latency_hi); +} + +bool chreSendEvent(uint16_t eventType, void *eventData, + chreEventCompleteFunction *freeCallback, + uint32_t targetInstanceId) +{ + return syscallDo4P(SYSCALL_CHRE_API(SEND_EVENT), eventType, eventData, freeCallback, targetInstanceId); +} + +bool chreSendMessageToHost(void *message, uint32_t messageSize, + uint32_t reservedMessageType, + chreMessageFreeFunction *freeCallback) +{ + return syscallDo4P(SYSCALL_CHRE_API(SEND_MSG), message, messageSize, reservedMessageType, freeCallback); +} + +uint32_t chreGetApiVersion(void) +{ + return syscallDo0P(SYSCALL_CHRE_API(GET_OS_API_VERSION)); +} + +uint32_t chreGetVersion(void) +{ + return syscallDo0P(SYSCALL_CHRE_API(GET_OS_VERSION)); +} + +uint64_t chreGetPlatformId(void) +{ + uint64_t plat = 0; + (void)syscallDo1P(SYSCALL_CHRE_API(GET_PLATFORM_ID), &plat); + return plat; +} diff --git a/firmware/app/chre/common/chre_app.c b/firmware/app/chre/common/chre_app.c index 55bbdf2f..0eba2394 100644 --- a/firmware/app/chre/common/chre_app.c +++ b/firmware/app/chre/common/chre_app.c @@ -232,7 +232,8 @@ static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData) const void *data = eventData; union EventLocalData { - struct chreMessageFromHostData msg; + struct chreMessageFromHostData msg; + struct chreNanoappInfo info; } u; switch(evt) { @@ -245,18 +246,46 @@ static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData) evt = CHRE_EVENT_MESSAGE_FROM_HOST; data = &u.msg; u.msg.message = (uint8_t*)eventData + 1; - u.msg.reservedMessageType = 0; + u.msg.messageType = 0; u.msg.messageSize = *(uint8_t*)eventData; + u.msg.hostEndpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED; break; case EVT_APP_FROM_HOST_CHRE: { - const struct NanohubMsgChreHdr *hdr = eventData; + if (chreGetApiVersion() == CHRE_API_VERSION_1_0) { + const struct NanohubMsgChreHdrV10 *hdr = eventData; + srcTid = CHRE_INSTANCE_ID; + evt = CHRE_EVENT_MESSAGE_FROM_HOST; + data = &u.msg; + u.msg.message = hdr + 1; + u.msg.messageType = hdr->appEvent; + u.msg.messageSize = hdr->size; + u.msg.hostEndpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED; + } else { + const struct NanohubMsgChreHdr *hdr = eventData; + srcTid = CHRE_INSTANCE_ID; + evt = CHRE_EVENT_MESSAGE_FROM_HOST; + data = &u.msg; + u.msg.message = hdr + 1; + u.msg.messageType = hdr->appEvent; + u.msg.messageSize = hdr->size; + u.msg.hostEndpoint = hdr->endpoint; + } + break; + } + case EVT_APP_STARTED: + case EVT_APP_STOPPED: + { + const struct AppEventStartStop *msg = eventData; srcTid = CHRE_INSTANCE_ID; - evt = CHRE_EVENT_MESSAGE_FROM_HOST; - data = &u.msg; - u.msg.message = hdr + 1; - u.msg.reservedMessageType = hdr->appEvent; - u.msg.messageSize = hdr->size; + if (evt == EVT_APP_STARTED) + evt = CHRE_EVENT_NANOAPP_STARTED; + else + evt = CHRE_EVENT_NANOAPP_STOPPED; + data = &u.info; + u.info.appId = msg->appId; + u.info.version = msg->version; + u.info.instanceId = msg->tid; break; } case EVT_APP_SENSOR_SELF_TEST: diff --git a/firmware/app/chre/common/chre_app_syscalls.c b/firmware/app/chre/common/chre_app_syscalls.c index 666bdaed..fc1bc8c3 100644 --- a/firmware/app/chre/common/chre_app_syscalls.c +++ b/firmware/app/chre/common/chre_app_syscalls.c @@ -49,6 +49,12 @@ uint64_t chreGetTime(void) { return time_ns; } +int64_t chreGetEstimatedHostTimeOffset(void) { + int64_t time_ns = 0; + (void)syscallDo1P(SYSCALL_CHRE_API(GET_HOST_TIME_OFFSET), &time_ns); + return time_ns; +} + void chreLog(enum chreLogLevel level, const char *str, ...) { va_list vl; @@ -113,33 +119,116 @@ bool chreSensorConfigure(uint32_t sensorHandle, interval_lo, interval_hi, latency_lo, latency_hi); } +uint32_t chreGetApiVersion(void) +{ + static uint32_t apiVersion = 0; + if (!apiVersion) + apiVersion = syscallDo0P(SYSCALL_CHRE_API(GET_OS_API_VERSION)); + return apiVersion; +} + +uint32_t chreGetVersion(void) +{ + return syscallDo0P(SYSCALL_CHRE_API(GET_OS_VERSION)); +} + +uint64_t chreGetPlatformId(void) +{ + uint64_t plat = 0; + (void)syscallDo1P(SYSCALL_CHRE_API(GET_PLATFORM_ID), &plat); + return plat; +} + bool chreSendEvent(uint16_t eventType, void *eventData, chreEventCompleteFunction *freeCallback, uint32_t targetInstanceId) { - return syscallDo4P(SYSCALL_CHRE_API(SEND_EVENT), eventType, eventData, freeCallback, targetInstanceId); + if (chreGetApiVersion() == CHRE_API_VERSION_1_0) + return syscallDo4P(SYSCALL_CHRE_API(SEND_EVENT), eventType, eventData, freeCallback, targetInstanceId); + else + return syscallDo4P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_SEND_EVENT), eventType, eventData, freeCallback, targetInstanceId); } bool chreSendMessageToHost(void *message, uint32_t messageSize, - uint32_t reservedMessageType, + uint32_t messageType, chreMessageFreeFunction *freeCallback) { - return syscallDo4P(SYSCALL_CHRE_API(SEND_MSG), message, messageSize, reservedMessageType, freeCallback); + if (chreGetApiVersion() == CHRE_API_VERSION_1_0) + return syscallDo4P(SYSCALL_CHRE_API(SEND_MSG), message, messageSize, messageType, freeCallback); + else + return syscallDo5P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_SEND_MSG), message, messageSize, messageType, CHRE_HOST_ENDPOINT_BROADCAST, freeCallback); } -uint32_t chreGetApiVersion(void) +bool chreSendMessageToHostEndpoint(void *message, size_t messageSize, + uint32_t messageType, uint16_t hostEndpoint, + chreMessageFreeFunction *freeCallback) { - return syscallDo0P(SYSCALL_CHRE_API(GET_OS_API_VERSION)); + return syscallDo5P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_SEND_MSG), message, messageSize, messageType, hostEndpoint, freeCallback); } -uint32_t chreGetVersion(void) +bool chreGetNanoappInfoByAppId(uint64_t appId, struct chreNanoappInfo *info) { - return syscallDo0P(SYSCALL_CHRE_API(GET_OS_VERSION)); + uint32_t app_lo = appId; + uint32_t app_hi = appId >> 32; + return syscallDo3P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_INFO_BY_APP_ID), app_lo, app_hi, info); } -uint64_t chreGetPlatformId(void) +bool chreGetNanoappInfoByInstanceId(uint32_t instanceId, struct chreNanoappInfo *info) { - uint64_t plat = 0; - (void)syscallDo1P(SYSCALL_CHRE_API(GET_PLATFORM_ID), &plat); - return plat; + return syscallDo2P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_INFO_BY_INST_ID), instanceId, info); +} + +void chreConfigureNanoappInfoEvents(bool enable) +{ + syscallDo1P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_MAIN, SYSCALL_CHRE_MAIN_EVENT, SYSCALL_CHRE_MAIN_EVENT_CFG_INFO), enable); +} + +uint32_t chreGnssGetCapabilities(void) +{ + return syscallDo0P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_GNSS, SYSCALL_CHRE_DRV_GNSS_GET_CAP)); +} + +bool chreGnssLocationSessionStartAsync(uint32_t minIntervalMs, uint32_t minTimeToNextFixMs, const void *cookie) +{ + return syscallDo3P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_GNSS, SYSCALL_CHRE_DRV_GNSS_LOC_START_ASYNC), minIntervalMs, minTimeToNextFixMs, cookie); +} + +bool chreGnssLocationSessionStopAsync(const void *cookie) +{ + return syscallDo1P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_GNSS, SYSCALL_CHRE_DRV_GNSS_LOC_STOP_ASYNC), cookie); +} + +bool chreGnssMeasurementSessionStartAsync(uint32_t minIntervalMs, const void *cookie) +{ + return syscallDo2P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_GNSS, SYSCALL_CHRE_DRV_GNSS_MEAS_START_ASYNC), minIntervalMs, cookie); +} + +bool chreGnssMeasurementSessionStopAsync(const void *cookie) +{ + return syscallDo1P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_GNSS, SYSCALL_CHRE_DRV_GNSS_MEAS_STOP_ASYNC), cookie); +} + +uint32_t chreWifiGetCapabilities(void) +{ + return syscallDo0P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_WIFI, SYSCALL_CHRE_DRV_WIFI_GET_CAP)); +} + +bool chreWifiConfigureScanMonitorAsync(bool enable, const void *cookie) +{ + return syscallDo2P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_WIFI, SYSCALL_CHRE_DRV_WIFI_CONF_SCAN_MON_ASYNC), enable, cookie); +} + +bool chreWifiRequestScanAsync(const struct chreWifiScanParams *params, const void *cookie) +{ + return syscallDo2P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_WIFI, SYSCALL_CHRE_DRV_WIFI_REQ_SCAN_ASYNC), params, cookie); +} + +uint32_t chreWwanGetCapabilities(void) +{ + return syscallDo0P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_WWAN, SYSCALL_CHRE_DRV_WWAN_GET_CAP)); +} + +bool chreWwanGetCellInfoAsync(const void *cookie) +{ + return syscallDo1P(SYSCALL_NO(SYSCALL_DOMAIN_CHRE, SYSCALL_CHRE_DRIVERS, SYSCALL_CHRE_DRV_WWAN, SYSCALL_CHRE_DRV_WWAN_GET_CELL_INFO_ASYNC), cookie); } diff --git a/firmware/build/app_chre_executable.mk b/firmware/build/app_chre_executable.mk index 01696993..009dc15c 100644 --- a/firmware/build/app_chre_executable.mk +++ b/firmware/build/app_chre_executable.mk @@ -24,8 +24,8 @@ ifeq ($(strip $(my_variants)),) my_variants := $(AUX_OS_VARIANT_LIST_$(NANO_OS)) endif -# mark the app as CHRE nanoapp -LOCAL_NANO_APP_POSTPROCESS_FLAGS += -f 0x10 +# mark the app as CHRE 1.1 nanoapp +LOCAL_NANO_APP_POSTPROCESS_FLAGS += -c 0x0101 # add app-side CHRE implementation LOCAL_WHOLE_STATIC_LIBRARIES += \ diff --git a/firmware/build/app_config.mk b/firmware/build/app_config.mk index 1bb4177d..e7734cfc 100644 --- a/firmware/build/app_config.mk +++ b/firmware/build/app_config.mk @@ -27,7 +27,9 @@ LOCAL_OBJCOPY_SECT_cortexm4 := .flash .data .relocs .dynsym LOCAL_FORCE_STATIC_EXECUTABLE := false LOCAL_CFLAGS += \ + -DNANOAPP_ID=0x$(LOCAL_NANO_APP_ID) \ -DAPP_ID=$(LOCAL_NANO_APP_ID) \ + -DNANOAPP_VERSION=$(LOCAL_NANO_APP_VERSION) \ -DAPP_VERSION=$(LOCAL_NANO_APP_VERSION) \ -D__NANOHUB__ \ diff --git a/firmware/build/config_internal.mk b/firmware/build/config_internal.mk index 533d38f5..3a015041 100644 --- a/firmware/build/config_internal.mk +++ b/firmware/build/config_internal.mk @@ -19,7 +19,7 @@ LOCAL_C_INCLUDES += \ $(NANOHUB_OS_PATH)/os/platform/$(AUX_ARCH)/inc \ $(NANOHUB_OS_PATH)/os/cpu/$(AUX_CPU)/inc \ $(NANOHUB_OS_PATH)/../lib/include \ - $(NANOHUB_OS_PATH)/../inc \ + system/chre/chre_api/include/chre_api \ LOCAL_WHOLE_STATIC_LIBRARIES_BL += libnanohub_bl_$(AUX_CPU) LOCAL_WHOLE_STATIC_LIBRARIES_BL += libnanohub_bl_$(AUX_ARCH) diff --git a/firmware/firmware.mk b/firmware/firmware.mk index eeda9b1a..246e03ec 100644 --- a/firmware/firmware.mk +++ b/firmware/firmware.mk @@ -56,7 +56,6 @@ FLAGS += -Ios/platform/$(PLATFORM)/inc FLAGS += -I$(VARIANT_PATH)/inc FLAGS += -Iexternal/freebsd/inc FLAGS += -I../lib/include -FLAGS += -I../inc FLAGS += -Wall -Werror #help avoid commmon embedded C mistakes diff --git a/firmware/os/core/appSec.c b/firmware/os/core/appSec.c index 94cfedac..b1974f0c 100644 --- a/firmware/os/core/appSec.c +++ b/firmware/os/core/appSec.c @@ -310,9 +310,21 @@ static AppSecErr appSecProcessIncomingHdr(struct AppSecState *state, uint32_t *n .fwFlags = image->layout.flags, .appVer = aosp->app_version, .payInfoType = image->layout.payload, - .rfu = { 0xFF, 0xFF }, + .chreApiMajor = 0xFF, + .chreApiMinor = 0xFF, }; + if (image->layout.flags & FL_APP_HDR_CHRE) { + if (aosp->chre_api_major || aosp->chre_api_minor) { + common.chreApiMajor = aosp->chre_api_major; + common.chreApiMinor = aosp->chre_api_minor; + } else { + // fields not defined prior to CHRE 1.1 + common.chreApiMajor = 0x01; + common.chreApiMinor = 0x00; + } + } + // check to see if this is special system types of payload switch(image->layout.payload) { case LAYOUT_APP: diff --git a/firmware/os/core/nanohubCommand.c b/firmware/os/core/nanohubCommand.c index 439f3dc6..b7611c34 100644 --- a/firmware/os/core/nanohubCommand.c +++ b/firmware/os/core/nanohubCommand.c @@ -50,6 +50,8 @@ #include <cpu/cpuMath.h> #include <algos/ap_hub_sync.h> +#include <chre.h> + #define NANOHUB_COMMAND(_reason, _fastHandler, _handler, _minReqType, _maxReqType) \ { .reason = _reason, .fastHandler = _fastHandler, .handler = _handler, \ .minDataLen = sizeof(_minReqType), .maxDataLen = sizeof(_maxReqType) } @@ -563,7 +565,7 @@ static uint32_t doFirmwareChunk(uint8_t *data, uint32_t offset, uint32_t len, vo if (mDownloadState->erase == true) { reply = NANOHUB_FIRMWARE_CHUNK_REPLY_WAIT; if (!mDownloadState->eraseScheduled) { - ret = osExtAppStopApps(APP_ID_ANY); + ret = osExtAppStopAppsByAppId(APP_ID_ANY); osLog(LOG_INFO, "%s: unloaded apps, ret=%08lx\n", __func__, ret); mDownloadState->eraseScheduled = osDefer(firmwareErase, NULL, false); } @@ -664,12 +666,26 @@ static uint32_t unmaskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t tim return sizeof(*resp); } +static void nanohubDelayStartApps(void *cookie) +{ + uint32_t status = 0; + status = osExtAppStartAppsDelayed(); + osLog(LOG_DEBUG, "Started delayed apps; EXT status: %08" PRIX32 "\n", status); +} + static void addDelta(struct ApHubSync *sync, uint64_t apTime, uint64_t hubTime) { + static bool delayStart = false; + #if DEBUG_APHUB_TIME_SYNC syncDebugAdd(apTime, hubTime); #endif apHubSyncAddDelta(sync, apTime, hubTime); + + if (!delayStart) { + delayStart = true; + osDefer(nanohubDelayStartApps, NULL, false); + } } static int64_t getAvgDelta(struct ApHubSync *sync) @@ -930,13 +946,23 @@ static uint32_t writeEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestam } } else if (event == EVT_APP_FROM_HOST_CHRE) { // new version of HAL; full support for CHRE apps + struct HostMsgHdrChreV10 *hostPacketV10 = rx; struct HostMsgHdrChre *hostPacket = rx; if (rx_len >= sizeof(struct HostMsgHdrChre) && rx_len == sizeof(struct HostMsgHdrChre) + hostPacket->len && osTidById(&hostPacket->appId, &tid)) { - if (osAppIsChre(tid)) { + if (osAppChreVersion(tid) == CHRE_API_VERSION_1_1) { struct NanohubMsgChreHdr hdr = { .size = hostPacket->len, + .endpoint = hostPacket->endpoint, + .appEvent = hostPacket->appEventId, + }; + // CHRE app receives message in new format + resp->accepted = forwardPacket(event, hostPacket + 1, hostPacket->len, + &hdr, sizeof(hdr), tid); + } else if (osAppChreVersion(tid) == CHRE_API_VERSION_1_0) { + struct NanohubMsgChreHdrV10 hdr = { + .size = hostPacket->len, .appEvent = hostPacket->appEventId, }; // CHRE app receives message in new format @@ -947,6 +973,31 @@ static uint32_t writeEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestam resp->accepted = forwardPacket(EVT_APP_FROM_HOST, hostPacket + 1, hostPacket->len, &hostPacket->len, sizeof(hostPacket->len), tid); } + } else if (rx_len >= sizeof(struct HostMsgHdrChreV10) && + rx_len == sizeof(struct HostMsgHdrChreV10) + hostPacketV10->len && + osTidById(&hostPacketV10->appId, &tid)) { + if (osAppChreVersion(tid) == CHRE_API_VERSION_1_1) { + struct NanohubMsgChreHdr hdr = { + .size = hostPacketV10->len, + .endpoint = CHRE_HOST_ENDPOINT_UNSPECIFIED, + .appEvent = hostPacketV10->appEventId, + }; + // CHRE app receives message in new format + resp->accepted = forwardPacket(event, hostPacketV10 + 1, hostPacketV10->len, + &hdr, sizeof(hdr), tid); + } else if (osAppChreVersion(tid) == CHRE_API_VERSION_1_0) { + struct NanohubMsgChreHdrV10 hdr = { + .size = hostPacketV10->len, + .appEvent = hostPacketV10->appEventId, + }; + // CHRE app receives message in new format + resp->accepted = forwardPacket(event, hostPacketV10 + 1, hostPacketV10->len, + &hdr, sizeof(hdr), tid); + } else { + // legacy app receives message in old format + resp->accepted = forwardPacket(EVT_APP_FROM_HOST, hostPacketV10 + 1, hostPacketV10->len, + &hostPacketV10->len, sizeof(hostPacketV10->len), tid); + } } else { resp->accepted = false; } @@ -1049,21 +1100,21 @@ static void halExtAppsOn(void *rx, uint8_t rx_len) { struct NanohubHalMgmtRx *req = rx; - halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_ON, osExtAppStartApps(le64toh(unaligned_u64(&req->appId)))); + halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_ON, osExtAppStartAppsByAppId(le64toh(unaligned_u64(&req->appId)))); } static void halExtAppsOff(void *rx, uint8_t rx_len) { struct NanohubHalMgmtRx *req = rx; - halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_OFF, osExtAppStopApps(le64toh(unaligned_u64(&req->appId)))); + halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_OFF, osExtAppStopAppsByAppId(le64toh(unaligned_u64(&req->appId)))); } static void halExtAppDelete(void *rx, uint8_t rx_len) { struct NanohubHalMgmtRx *req = rx; - halSendMgmtResponse(NANOHUB_HAL_EXT_APP_DELETE, osExtAppEraseApps(le64toh(unaligned_u64(&req->appId)))); + halSendMgmtResponse(NANOHUB_HAL_EXT_APP_DELETE, osExtAppEraseAppsByAppId(le64toh(unaligned_u64(&req->appId)))); } static void halQueryMemInfo(void *rx, uint8_t rx_len) @@ -1238,6 +1289,16 @@ const struct NanohubHalCommand *nanohubHalFindCommand(uint8_t msg) return NULL; } +int64_t hostGetTimeDelta(void) +{ + int64_t delta = getAvgDelta(&mTimeSync); + + if (delta == INT64_MIN) + return 0ULL; + else + return delta; +} + uint64_t hostGetTime(void) { int64_t delta = getAvgDelta(&mTimeSync); diff --git a/firmware/os/core/nanohub_chre.c b/firmware/os/core/nanohub_chre.c index f23f860d..5ed419b6 100644 --- a/firmware/os/core/nanohub_chre.c +++ b/firmware/os/core/nanohub_chre.c @@ -31,6 +31,7 @@ #include <timer.h> #include <util.h> #include <printf.h> +#include <nanohubCommand.h> #include <chre.h> #include <chreApi.h> @@ -105,6 +106,13 @@ static void osChreApiGetTime(uintptr_t *retValP, va_list args) *timeNanos = sensorGetTime(); } +static void osChreApiGetHostTimeOffset(uintptr_t *retValP, va_list args) +{ + uint64_t *timeNanos = va_arg(args, uint64_t *); + if (timeNanos) + *timeNanos = hostGetTimeDelta(); +} + static inline uint32_t osChreTimerSet(uint64_t duration, const void* cookie, bool oneShot) { uint32_t timId = timTimerSetNew(duration, cookie, oneShot); @@ -132,9 +140,19 @@ static void osChreApiTimerCancel(uintptr_t *retValP, va_list args) static inline void osChreAbort(uint32_t abortCode) { struct Task *task = osGetCurrentTask(); - osLog(LOG_ERROR, "APP ID=0x%" PRIX64 " TID=0x%" PRIX16 " aborted [code 0x%" PRIX32 "]", - task->app->hdr.appId, task->tid, abortCode); - osTaskAbort(task); + if (task) { + if (task->app) { + osLog(LOG_ERROR, "APP ID=0x%" PRIX64 " TID=0x%" PRIX16 " aborted [code 0x%" PRIX32 "]", + task->app->hdr.appId, task->tid, abortCode); + } else { + osLog(LOG_ERROR, "APP ID=NULL TID=0x%" PRIX16 " aborted [code 0x%" PRIX32 "]", + task->tid, abortCode); + } + osTaskAbort(task); + } else { + osLog(LOG_ERROR, "osChreAbort called with no current task [code 0x%" PRIX32 "]", + abortCode); + } } static void osChreApiAbort(uintptr_t *retValP, va_list args) @@ -184,17 +202,8 @@ static bool osChreSendEvent(uint16_t evtType, void *evtData, return osEnqueuePrivateEvtNew(evtType, evtData, evtFreeCallback, toTid); } -static void osChreApiSendEvent(uintptr_t *retValP, va_list args) -{ - uint16_t evtType = va_arg(args, uint32_t); // stored as 32-bit - void *evtData = va_arg(args, void *); - chreEventCompleteFunction *freeCallback = va_arg(args, chreEventCompleteFunction *); - uint32_t toTid = va_arg(args, uint32_t); - *retValP = osChreSendEvent(evtType, evtData, freeCallback, toTid); -} - static bool osChreSendMessageToHost(void *message, uint32_t messageSize, - uint32_t reservedMessageType, + uint32_t messageType, uint16_t hostEndpoint, chreMessageFreeFunction *freeCallback) { bool result = false; @@ -224,10 +233,10 @@ static void osChreApiSendMessageToHost(uintptr_t *retValP, va_list args) { void *message = va_arg(args, void *); uint32_t messageSize = va_arg(args, uint32_t); - uint32_t reservedMessageType = va_arg(args, uint32_t); + uint32_t messageType = va_arg(args, uint32_t); chreMessageFreeFunction *freeCallback = va_arg(args, chreMessageFreeFunction *); - *retValP = osChreSendMessageToHost(message, messageSize, reservedMessageType, freeCallback); + *retValP = osChreSendMessageToHost(message, messageSize, messageType, CHRE_HOST_ENDPOINT_BROADCAST, freeCallback); } static bool osChreSensorFindDefault(uint8_t sensorType, uint32_t *pHandle) @@ -247,9 +256,31 @@ static void osChreApiSensorFindDefault(uintptr_t *retValP, va_list args) *retValP = osChreSensorFindDefault(sensorType, pHandle); } +static bool osChreSensorGetInfoOld(uint32_t sensorHandle, struct chreSensorInfo *info) +{ + struct Sensor *s = sensorFindByHandle(sensorHandle); + if (!s || !info) + return false; + const struct SensorInfo *si = s->si; + info->sensorName = si->sensorName; + info->sensorType = si->sensorType; + info->unusedFlags = 0; + + if (si->sensorType == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT + || si->sensorType == CHRE_SENSOR_TYPE_STATIONARY_DETECT) + info->isOneShot = true; + else + info->isOneShot = false; + info->isOnChange = s->hasOnchange; + + return true; +} + static bool osChreSensorGetInfo(uint32_t sensorHandle, struct chreSensorInfo *info) { struct Sensor *s = sensorFindByHandle(sensorHandle); + uint32_t max = 0; + int i; if (!s || !info) return false; const struct SensorInfo *si = s->si; @@ -263,10 +294,30 @@ static bool osChreSensorGetInfo(uint32_t sensorHandle, struct chreSensorInfo *in else info->isOneShot = false; info->isOnChange = s->hasOnchange; + info->minInterval = CHRE_SENSOR_INTERVAL_DEFAULT; + if (si->supportedRates) { + for (i=0; si->supportedRates[i] != 0; i++) { + if (si->supportedRates[i] > max + && si->supportedRates[i] != SENSOR_RATE_ONDEMAND + && si->supportedRates[i] != SENSOR_RATE_ONCHANGE + && si->supportedRates[i] != SENSOR_RATE_ONESHOT) { + max = si->supportedRates[i]; + } + } + if (max) + info->minInterval = (UINT32_C(1024000000) / max) * UINT64_C(1000); + } return true; } +static void osChreApiSensorGetInfoOld(uintptr_t *retValP, va_list args) +{ + uint32_t sensorHandle = va_arg(args, uint32_t); + struct chreSensorInfo *info = va_arg(args, struct chreSensorInfo *); + *retValP = osChreSensorGetInfoOld(sensorHandle, info); +} + static void osChreApiSensorGetInfo(uintptr_t *retValP, va_list args) { uint32_t sensorHandle = va_arg(args, uint32_t); @@ -278,27 +329,32 @@ static bool osChreSensorGetSamplingStatus(uint32_t sensorHandle, struct chreSensorSamplingStatus *status) { struct Sensor *s = sensorFindByHandle(sensorHandle); + uint32_t rate; + uint64_t latency; + if (!s || !status) return false; - if (s->currentRate == SENSOR_RATE_OFF - || s->currentRate >= SENSOR_RATE_POWERING_ON) { + rate = sensorGetHwRate(sensorHandle); + latency = sensorGetHwLatency(sensorHandle); + + if (rate == SENSOR_RATE_OFF) { status->enabled = 0; status->interval = 0; status->latency = 0; } else { status->enabled = true; - if (s->currentRate == SENSOR_RATE_ONDEMAND - || s->currentRate == SENSOR_RATE_ONCHANGE - || s->currentRate == SENSOR_RATE_ONESHOT) + if (rate == SENSOR_RATE_ONDEMAND + || rate == SENSOR_RATE_ONCHANGE + || rate == SENSOR_RATE_ONESHOT) status->interval = CHRE_SENSOR_INTERVAL_DEFAULT; else - status->interval = (UINT32_C(1024000000) / s->currentRate) * UINT64_C(1000); + status->interval = (UINT32_C(1024000000) / rate) * UINT64_C(1000); - if (s->currentLatency == SENSOR_LATENCY_NODATA) + if (latency == SENSOR_LATENCY_NODATA) status->latency = CHRE_SENSOR_INTERVAL_DEFAULT; else - status->latency = s->currentLatency; + status->latency = latency; } return true; @@ -355,10 +411,7 @@ static bool osChreSensorConfigure(uint32_t sensorHandle, ret = sensorRequestRateChange(0, sensorHandle, rate, latency); } } else if (mode & (CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS|CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT)) { - if (interval != CHRE_SENSOR_INTERVAL_DEFAULT - || latency != CHRE_SENSOR_LATENCY_DEFAULT) - ret = false; - else if (sensorGetReqRate(sensorHandle) == SENSOR_RATE_OFF) + if (sensorGetReqRate(sensorHandle) == SENSOR_RATE_OFF) ret = osEventsSubscribe(2, sensorGetMyEventType(s->si->sensorType), sensorGetMyCfgEventType(s->si->sensorType)); else ret = true; @@ -421,6 +474,132 @@ static void osChreApiPlatformId(uintptr_t *retValP, va_list args) *pHwId = osChreGetPlatformId(); } +static void osChreEventSendEvent(uintptr_t *retValP, va_list args) +{ + uint16_t evtType = va_arg(args, uint32_t); // stored as 32-bit + void *evtData = va_arg(args, void *); + chreEventCompleteFunction *freeCallback = va_arg(args, chreEventCompleteFunction *); + uint32_t toTid = va_arg(args, uint32_t); + *retValP = osChreSendEvent(evtType, evtData, freeCallback, toTid); +} + +static void osChreEventSendMessageToHost(uintptr_t *retValP, va_list args) +{ + void *message = va_arg(args, void *); + uint32_t messageSize = va_arg(args, size_t); + uint32_t messageType = va_arg(args, uint32_t); + uint16_t hostEndpoint = va_arg(args, uint32_t); + chreMessageFreeFunction *freeCallback = va_arg(args, chreMessageFreeFunction *); + + *retValP = osChreSendMessageToHost(message, messageSize, messageType, hostEndpoint, freeCallback); +} + +static bool chreInfoByTid(uint32_t tid, struct chreNanoappInfo *info) +{ + struct Task *task = osTaskFindByTid(tid); + if (task) { + info->appId = task->app->hdr.appId; + info->version = task->app->hdr.appVer; + info->instanceId = tid; + return true; + } else { + return false; + } +} + +static void osChreEventInfoByAppId(uintptr_t *retValP, va_list args) +{ + uint32_t app_lo = va_arg(args, uint32_t); + uint32_t app_hi = va_arg(args, uint32_t); + struct chreNanoappInfo *info = va_arg(args, struct chreNanoappInfo *); + uint64_t appId = (((uint64_t)app_hi) << 32) | app_lo; + uint32_t tid; + + if (osTidById(&appId, &tid)) + *retValP = chreInfoByTid(tid, info); + else + *retValP = false; +} + +static void osChreEeventInfoByInstId(uintptr_t *retValP, va_list args) +{ + uint32_t tid = va_arg(args, uint32_t); + struct chreNanoappInfo *info = va_arg(args, struct chreNanoappInfo *); + + *retValP = chreInfoByTid(tid, info); +} + +static void osChreEventCfgInfo(uintptr_t *retValP, va_list args) +{ + bool enable = va_arg(args, int); + if (enable) + osEventsSubscribe(2, EVT_APP_STARTED, EVT_APP_STOPPED); + else + osEventsUnsubscribe(2, EVT_APP_STARTED, EVT_APP_STOPPED); +} + +static void osChreDrvGnssGetCap(uintptr_t *retValP, va_list args) +{ + *retValP = CHRE_GNSS_CAPABILITIES_NONE; +} + +static void osChreDrvGnssLocStartAsync(uintptr_t *retValP, va_list args) +{ + // uint32_t minIntervalMs = va_args(args, uint32_t); + // uint32_t minTimeToNextFixMs = va_args(args, uint32_t); + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvGnssLocStopAsync(uintptr_t *retValP, va_list args) +{ + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvGnssMeasStartAsync(uintptr_t *retValP, va_list args) +{ + // uint32_t minIntervalMs = va_args(args, uint32_t); + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvGnssMeasStopAsync(uintptr_t *retValP, va_list args) +{ + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvWifiGetCap(uintptr_t *retValP, va_list args) +{ + *retValP = CHRE_WIFI_CAPABILITIES_NONE; +} + +static void osChreDrvWifiConfScanMonAsync(uintptr_t *retValP, va_list args) +{ + // bool enable = va_args(args, int); + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvWifiReqScanAsync(uintptr_t *retValP, va_list args) +{ + // const struct chreWifiScanParams *params = va_args(args, struct chreWifiScanParams *); + // const void *cookie = va_args(args, void *); + *retValP = false; +} + +static void osChreDrvWwanGetCap(uintptr_t *retValP, va_list args) +{ + *retValP = CHRE_WWAN_CAPABILITIES_NONE; +} + +static void osChreDrvWwanGetCallInfoAsync(uintptr_t *retValP, va_list args) +{ + // const void *cookie = va_args(args, void *); + *retValP = false; +} + static const struct SyscallTable chreMainApiTable = { .numEntries = SYSCALL_CHRE_MAIN_API_LAST, .entry = { @@ -429,15 +608,17 @@ static const struct SyscallTable chreMainApiTable = { [SYSCALL_CHRE_MAIN_API_GET_APP_ID] = { .func = osChreApiGetAppId }, [SYSCALL_CHRE_MAIN_API_GET_INST_ID] = { .func = osChreApiGetInstanceId }, [SYSCALL_CHRE_MAIN_API_GET_TIME] = { .func = osChreApiGetTime }, + [SYSCALL_CHRE_MAIN_API_GET_HOST_TIME_OFFSET] = { .func = osChreApiGetHostTimeOffset }, [SYSCALL_CHRE_MAIN_API_TIMER_SET] = { .func = osChreApiTimerSet }, [SYSCALL_CHRE_MAIN_API_TIMER_CANCEL] = { .func = osChreApiTimerCancel }, [SYSCALL_CHRE_MAIN_API_ABORT] = { .func = osChreApiAbort }, [SYSCALL_CHRE_MAIN_API_HEAP_ALLOC] = { .func = osChreApiHeapAlloc }, [SYSCALL_CHRE_MAIN_API_HEAP_FREE] = { .func = osChreApiHeapFree }, - [SYSCALL_CHRE_MAIN_API_SEND_EVENT] = { .func = osChreApiSendEvent }, + [SYSCALL_CHRE_MAIN_API_SEND_EVENT] = { .func = osChreEventSendEvent }, [SYSCALL_CHRE_MAIN_API_SEND_MSG] = { .func = osChreApiSendMessageToHost }, [SYSCALL_CHRE_MAIN_API_SENSOR_FIND_DEFAULT] = { .func = osChreApiSensorFindDefault }, - [SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO] = { .func = osChreApiSensorGetInfo }, + [SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO_OLD] = { .func = osChreApiSensorGetInfoOld }, + [SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO] = { .func = osChreApiSensorGetInfo }, [SYSCALL_CHRE_MAIN_API_SENSOR_GET_STATUS] = { .func = osChreApiSensorGetStatus }, [SYSCALL_CHRE_MAIN_API_SENSOR_CONFIG] = { .func = osChreApiSensorConfig }, [SYSCALL_CHRE_MAIN_API_GET_OS_API_VERSION] = { .func = osChreApiChreApiVersion }, @@ -446,10 +627,59 @@ static const struct SyscallTable chreMainApiTable = { }, }; +static const struct SyscallTable chreMainEventTable = { + .numEntries = SYSCALL_CHRE_MAIN_EVENT_LAST, + .entry = { + [SYSCALL_CHRE_MAIN_EVENT_SEND_EVENT] = { .func = osChreEventSendEvent }, + [SYSCALL_CHRE_MAIN_EVENT_SEND_MSG] = { .func = osChreEventSendMessageToHost }, + [SYSCALL_CHRE_MAIN_EVENT_INFO_BY_APP_ID] = { .func = osChreEventInfoByAppId }, + [SYSCALL_CHRE_MAIN_EVENT_INFO_BY_INST_ID] = { .func = osChreEeventInfoByInstId }, + [SYSCALL_CHRE_MAIN_EVENT_CFG_INFO] = { .func = osChreEventCfgInfo }, + }, +}; + static const struct SyscallTable chreMainTable = { .numEntries = SYSCALL_CHRE_MAIN_LAST, .entry = { [SYSCALL_CHRE_MAIN_API] = { .subtable = (struct SyscallTable*)&chreMainApiTable, }, + [SYSCALL_CHRE_MAIN_EVENT] = { .subtable = (struct SyscallTable*)&chreMainEventTable, }, + }, +}; + +static const struct SyscallTable chreDrvGnssTable = { + .numEntries = SYSCALL_CHRE_DRV_GNSS_LAST, + .entry = { + [SYSCALL_CHRE_DRV_GNSS_GET_CAP] = { .func = osChreDrvGnssGetCap }, + [SYSCALL_CHRE_DRV_GNSS_LOC_START_ASYNC] = { .func = osChreDrvGnssLocStartAsync }, + [SYSCALL_CHRE_DRV_GNSS_LOC_STOP_ASYNC] = { .func = osChreDrvGnssLocStopAsync }, + [SYSCALL_CHRE_DRV_GNSS_MEAS_START_ASYNC] = { .func = osChreDrvGnssMeasStartAsync }, + [SYSCALL_CHRE_DRV_GNSS_MEAS_STOP_ASYNC] = { .func = osChreDrvGnssMeasStopAsync }, + }, +}; + +static const struct SyscallTable chreDrvWifiTable = { + .numEntries = SYSCALL_CHRE_DRV_WIFI_LAST, + .entry = { + [SYSCALL_CHRE_DRV_WIFI_GET_CAP] = { .func = osChreDrvWifiGetCap }, + [SYSCALL_CHRE_DRV_WIFI_CONF_SCAN_MON_ASYNC] = { .func = osChreDrvWifiConfScanMonAsync }, + [SYSCALL_CHRE_DRV_WIFI_REQ_SCAN_ASYNC] = { .func = osChreDrvWifiReqScanAsync }, + }, +}; + +static const struct SyscallTable chreDrvWwanTable = { + .numEntries = SYSCALL_CHRE_DRV_WWAN_LAST, + .entry = { + [SYSCALL_CHRE_DRV_WWAN_GET_CAP] = { .func = osChreDrvWwanGetCap }, + [SYSCALL_CHRE_DRV_WWAN_GET_CELL_INFO_ASYNC] = { .func = osChreDrvWwanGetCallInfoAsync }, + }, +}; + +static const struct SyscallTable chreDriversTable = { + .numEntries = SYSCALL_CHRE_DRV_LAST, + .entry = { + [SYSCALL_CHRE_DRV_GNSS] = { .subtable = (struct SyscallTable*)&chreDrvGnssTable, }, + [SYSCALL_CHRE_DRV_WIFI] = { .subtable = (struct SyscallTable*)&chreDrvWifiTable, }, + [SYSCALL_CHRE_DRV_WWAN] = { .subtable = (struct SyscallTable*)&chreDrvWwanTable, }, }, }; @@ -457,6 +687,7 @@ static const struct SyscallTable chreTable = { .numEntries = SYSCALL_CHRE_LAST, .entry = { [SYSCALL_CHRE_MAIN] = { .subtable = (struct SyscallTable*)&chreMainTable, }, + [SYSCALL_CHRE_DRIVERS] = { .subtable = (struct SyscallTable*)&chreDriversTable, }, }, }; diff --git a/firmware/os/core/osApi.c b/firmware/os/core/osApi.c index 8361d9ae..098e2dc1 100644 --- a/firmware/os/core/osApi.c +++ b/firmware/os/core/osApi.c @@ -28,6 +28,7 @@ #include <heap.h> #include <i2c.h> #include <nanohubCommand.h> +#include <seos_priv.h> static struct SlabAllocator *mSlabAllocator; diff --git a/firmware/os/core/sensors.c b/firmware/os/core/sensors.c index d96fdc68..781afb88 100644 --- a/firmware/os/core/sensors.c +++ b/firmware/os/core/sensors.c @@ -816,6 +816,20 @@ uint64_t sensorGetCurLatency(uint32_t sensorHandle) return s ? s->currentLatency : SENSOR_LATENCY_INVALID; } +uint32_t sensorGetHwRate(uint32_t sensorHandle) +{ + struct Sensor* s = sensorFindByHandle(sensorHandle); + + return s ? sensorCalcHwRate(s, 0, 0) : SENSOR_RATE_OFF; +} + +uint64_t sensorGetHwLatency(uint32_t sensorHandle) +{ + struct Sensor* s = sensorFindByHandle(sensorHandle); + + return s ? sensorCalcHwLatency(s) : SENSOR_LATENCY_INVALID; +} + uint32_t sensorGetReqRate(uint32_t sensorHandle) { struct SensorsClientRequest *req = sensorClientRequestFind(sensorHandle, osGetCurrentTid()); diff --git a/firmware/os/core/seos.c b/firmware/os/core/seos.c index 8d100f56..98c05ea5 100644 --- a/firmware/os/core/seos.c +++ b/firmware/os/core/seos.c @@ -97,6 +97,16 @@ bool osAppIsChre(uint16_t tid) return task && osTaskIsChre(task); } +uint32_t osAppChreVersion(uint16_t tid) +{ + struct Task *task = osTaskFindByTid(tid); + + if (task) + return osTaskChreVersion(task); + else + return 0; +} + static inline uint32_t osTaskClrSetFlags(struct Task *task, uint32_t clrMask, uint32_t setMask) { while (true) { @@ -290,27 +300,26 @@ static inline bool osTaskInit(struct Task *task) static void osTaskRelease(struct Task *task) { - uint16_t tid = task->tid; - - osSetCurrentTask(mSystemTask); + uint32_t task_tid = task->tid; - platFreeResources(tid); // HW resources cleanup (IRQ, DMA etc) - sensorFreeAll(tid); - timTimerCancelAll(tid); - heapFreeAll(tid); + platFreeResources(task_tid); // HW resources cleanup (IRQ, DMA etc) + sensorFreeAll(task_tid); + timTimerCancelAll(task_tid); + heapFreeAll(task_tid); } static inline void osTaskEnd(struct Task *task) { - struct Task *preempted = osSetCurrentTask(task); - - cpuAppEnd(task->app, &task->platInfo); + if (!osTaskTestFlags(task, FL_TASK_ABORTED)) { + struct Task *preempted = osSetCurrentTask(task); + cpuAppEnd(task->app, &task->platInfo); + osSetCurrentTask(preempted); + } // task was supposed to release it's resources, // but we do our cleanup anyway - osTaskRelease(task); // NOTE: we don't need to unsubscribe from events - osSetCurrentTask(preempted); + osTaskRelease(task); } static inline void osTaskHandle(struct Task *task, uint16_t evtType, uint16_t fromTid, const void* evtData) @@ -722,48 +731,79 @@ static bool osStartApp(const struct AppHdr *app) osUnloadApp(task); } else { osAddTask(task); + (void)osEnqueueEvt(EVT_APP_BEGIN, task, NULL); } } return done; } -static bool osStopTask(struct Task *task) +static bool osStopTask(struct Task *task, bool abort) { + struct Task *preempted; + if (!task) return false; + if (osTaskTestFlags(task, FL_TASK_STOPPED)) + return true; + + preempted = osSetCurrentTask(mSystemTask); osRemoveTask(task); + osTaskClrSetFlags(task, 0, FL_TASK_STOPPED); - if (osTaskGetIoCount(task)) - { + if (abort) + osTaskClrSetFlags(task, 0, FL_TASK_ABORTED); + else if (osTaskGetIoCount(task)) osTaskHandle(task, EVT_APP_STOP, OS_SYSTEM_TID, NULL); - osEnqueueEvt(EVT_APP_END, task, NULL); - } else { - osTaskEnd(task); // calls app END() and Release() - osUnloadApp(task); - } + osEnqueueEvt(EVT_APP_END, task, NULL); + + osSetCurrentTask(preempted); - osTaskClrSetFlags(task, 0, FL_TASK_STOPPED); return true; } void osTaskAbort(struct Task *task) { - if (!task) - return; + osStopTask(task, true); +} + +static bool matchDelayStart(const void *cookie, const struct AppHdr *app) +{ + bool match = (bool)cookie; - osRemoveTask(task); // remove from active task list - // do not call app END() - osTaskRelease(task); // release all system resources - osUnloadApp(task); // destroy platform app object in RAM + if (app->hdr.fwFlags & FL_APP_HDR_CHRE) { + if (app->hdr.chreApiMajor == 0xFF && app->hdr.chreApiMinor == 0xFF) + return !match; + else if ((app->hdr.chreApiMajor < 0x01) || + (app->hdr.chreApiMajor == 0x01 && app->hdr.chreApiMinor < 0x01)) + return !match; + else + return match; + } else { + return !match; + } } -static bool osExtAppFind(struct SegmentIterator *it, uint64_t appId) +static bool matchAppId(const void *data, const struct AppHdr *app) +{ + uint64_t appId, vendor, seqId, curAppId; + + memcpy(&appId, data, sizeof(appId)); + vendor = APP_ID_GET_VENDOR(appId); + seqId = APP_ID_GET_SEQ_ID(appId); + curAppId = app->hdr.appId; + + if ((vendor == APP_VENDOR_ANY || vendor == APP_ID_GET_VENDOR(curAppId)) && + (seqId == APP_SEQ_ID_ANY || seqId == APP_ID_GET_SEQ_ID(curAppId))) { + return true; + } else { + return false; + } +} + +static bool osExtAppFind(struct SegmentIterator *it, appMatchFunc func, const void *data) { - uint64_t vendor = APP_ID_GET_VENDOR(appId); - uint64_t seqId = APP_ID_GET_SEQ_ID(appId); - uint64_t curAppId; const struct AppHdr *app; const struct Segment *seg; @@ -776,17 +816,14 @@ static bool osExtAppFind(struct SegmentIterator *it, uint64_t appId) if (seg->state != SEG_ST_VALID) continue; app = osSegmentGetData(seg); - curAppId = app->hdr.appId; - - if ((vendor == APP_VENDOR_ANY || vendor == APP_ID_GET_VENDOR(curAppId)) && - (seqId == APP_SEQ_ID_ANY || seqId == APP_ID_GET_SEQ_ID(curAppId))) + if (func(data, app)) return true; } return false; } -static uint32_t osExtAppStopEraseApps(uint64_t appId, bool doErase) +static uint32_t osExtAppStopEraseApps(appMatchFunc func, const void *data, bool doErase) { const struct AppHdr *app; int32_t len; @@ -799,7 +836,7 @@ static uint32_t osExtAppStopEraseApps(uint64_t appId, bool doErase) struct Task *task; osSegmentIteratorInit(&it); - while (osExtAppFind(&it, appId)) { + while (osExtAppFind(&it, func, data)) { app = osSegmentGetData(it.seg); len = osSegmentGetSize(it.seg); if (!osExtAppIsValid(app, len)) @@ -813,7 +850,7 @@ static uint32_t osExtAppStopEraseApps(uint64_t appId, bool doErase) task = osTaskFindByAppID(app->hdr.appId); if (task) { taskCount++; - if (osStopTask(task)) + if (osStopTask(task, false)) stopCount++; } } @@ -825,14 +862,14 @@ static uint32_t osExtAppStopEraseApps(uint64_t appId, bool doErase) return stat.value; } -uint32_t osExtAppStopApps(uint64_t appId) +uint32_t osExtAppStopAppsByAppId(uint64_t appId) { - return osExtAppStopEraseApps(appId, false); + return osExtAppStopEraseApps(matchAppId, &appId, false); } -uint32_t osExtAppEraseApps(uint64_t appId) +uint32_t osExtAppEraseAppsByAppId(uint64_t appId) { - return osExtAppStopEraseApps(appId, true); + return osExtAppStopEraseApps(matchAppId, &appId, true); } static void osScanExternal() @@ -859,7 +896,7 @@ static void osScanExternal() } } -uint32_t osExtAppStartApps(uint64_t appId) +static uint32_t osExtAppStartApps(appMatchFunc func, void *data) { const struct AppHdr *app; int32_t len; @@ -874,7 +911,7 @@ uint32_t osExtAppStartApps(uint64_t appId) osScanExternal(); osSegmentIteratorInit(&it); - while (osExtAppFind(&it, appId)) { + while (osExtAppFind(&it, func, data)) { app = osSegmentGetData(it.seg); len = osSegmentGetSize(it.seg); @@ -885,7 +922,7 @@ uint32_t osExtAppStartApps(uint64_t appId) appCount++; checkIt = it; // find the most recent copy - while (osExtAppFind(&checkIt, app->hdr.appId)) { + while (osExtAppFind(&checkIt, matchAppId, &app->hdr.appId)) { if (osExtAppErase(app)) // erase the old one, so we skip it next time eraseCount++; app = osSegmentGetData(checkIt.seg); @@ -909,6 +946,16 @@ uint32_t osExtAppStartApps(uint64_t appId) return stat.value; } +uint32_t osExtAppStartAppsByAppId(uint64_t appId) +{ + return osExtAppStartApps(matchAppId, &appId); +} + +uint32_t osExtAppStartAppsDelayed() +{ + return osExtAppStartApps(matchDelayStart, (void *)true); +} + static void osStartTasks(void) { const struct AppHdr *app; @@ -959,19 +1006,20 @@ static void osStartTasks(void) } osLog(LOG_DEBUG, "Starting external apps...\n"); - status = osExtAppStartApps(APP_ID_ANY); + status = osExtAppStartApps(matchDelayStart, (void *)false); osLog(LOG_DEBUG, "Started %" PRIu32 " internal apps; EXT status: %08" PRIX32 "\n", taskCnt, status); } static void osInternalEvtHandle(uint32_t evtType, void *evtData) { union SeosInternalSlabData *da = (union SeosInternalSlabData*)evtData; - struct Task *task; + struct Task *task, *ssTask; uint32_t i, j; uint16_t tid = EVENT_GET_ORIGIN(evtType); - uint16_t evt = EVENT_GET_EVENT(evtType); + uint16_t evt = EVENT_GET_EVENT(evtType), newEvt; struct Task *srcTask = osTaskFindByTid(tid); struct Task *preempted = osSetCurrentTask(srcTask); + struct AppEventStartStop ssMsg; switch (evt) { case EVT_SUBSCRIBE_TO_EVT: @@ -1008,10 +1056,31 @@ static void osInternalEvtHandle(uint32_t evtType, void *evtData) } break; + case EVT_APP_BEGIN: case EVT_APP_END: - task = evtData; - osTaskEnd(task); - osUnloadApp(task); + ssTask = evtData; + ssMsg.appId = ssTask->app->hdr.appId; + ssMsg.version = ssTask->app->hdr.appVer; + ssMsg.tid = ssTask->tid; + if (evt == EVT_APP_BEGIN) { + newEvt = EVT_APP_STARTED; + } else { + newEvt = EVT_APP_STOPPED; + osTaskEnd(ssTask); + osUnloadApp(ssTask); + } + + /* send this event to all tasks who want it */ + for_each_task(&mTasks, task) { + if (task != ssTask) { + for (i = 0; i < task->subbedEvtCount; i++) { + if (task->subbedEvents[i] == newEvt) { + osTaskHandle(task, newEvt, OS_SYSTEM_TID, &ssMsg); + break; + } + } + } + } break; case EVT_DEFERRED_CALLBACK: diff --git a/firmware/os/core/timer.c b/firmware/os/core/timer.c index 76df80bb..ace80723 100644 --- a/firmware/os/core/timer.c +++ b/firmware/os/core/timer.c @@ -31,6 +31,8 @@ #define MAX_INTERNAL_EVENTS 32 //also used for external app timer() calls +#define MAX_TIMER_ID 0xFF + #define INFO_PRINT(fmt, ...) do { \ osLog(LOG_INFO, "%s " fmt, "[timer]", ##__VA_ARGS__); \ } while (0); @@ -40,7 +42,8 @@ struct Timer { uint64_t expires; /* time of next expiration */ uint64_t period; /* 0 for oneshot */ - uint16_t id; /* 0 for disabled */ + uint8_t id; /* 0 for disabled */ + uint8_t useRtc; /* 1 for rtc, 0 for tim */ uint16_t tid; /* we need TID always, for system management */ uint32_t jitterPpm; uint32_t driftPpm; @@ -102,7 +105,7 @@ static bool timFireAsNeededAndUpdateAlarms(void) { uint32_t maxDrift = 0, maxJitter = 0, maxErrTotal = 0; bool somethingDone, totalSomethingDone = false; - uint64_t nextTimer; + uint64_t nextTimer, expires; uint32_t i; struct Timer *tim; @@ -118,7 +121,7 @@ static bool timFireAsNeededAndUpdateAlarms(void) if (!tim->id) continue; - if (tim->expires <= timGetTime()) { + if ((!tim->useRtc && tim->expires <= timGetTime()) || (tim->useRtc && tim->expires <= rtcGetTime())) { somethingDone = true; if (tim->period) { tim->expires += tim->period; @@ -136,8 +139,12 @@ static bool timFireAsNeededAndUpdateAlarms(void) maxDrift = tim->driftPpm; if (tim->driftPpm + tim->jitterPpm > maxErrTotal) maxErrTotal = tim->driftPpm + tim->jitterPpm; - if (!nextTimer || nextTimer > tim->expires) - nextTimer = tim->expires; + if (tim->useRtc) + expires = tim->expires - rtcGetTime() + timGetTime(); + else + expires = tim->expires; + if (!nextTimer || nextTimer > expires) + nextTimer = expires; } } @@ -155,9 +162,9 @@ static bool timFireAsNeededAndUpdateAlarms(void) return totalSomethingDone; } -static uint32_t timTimerSetEx(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, TaggedPtr info, void* data, bool oneShot) +static uint32_t timTimerSetEx(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, TaggedPtr info, void* data, bool oneShot, bool useRtc) { - uint64_t curTime = timGetTime(); + uint64_t curTime = useRtc ? rtcGetTime() : timGetTime(); int32_t idx = atomicBitsetFindClearAndSet(mTimersValid); struct Timer *t; uint16_t timId; @@ -169,7 +176,7 @@ static uint32_t timTimerSetEx(uint64_t length, uint32_t jitterPpm, uint32_t drif /* generate next timer ID */ do { - timId = atomicAdd32bits(&mNextTimerId, 1); + timId = atomicAdd32bits(&mNextTimerId, 1) & MAX_TIMER_ID; } while (!timId || timFindTimerById(timId)); /* grab our struct & fill it in */ @@ -180,10 +187,11 @@ static uint32_t timTimerSetEx(uint64_t length, uint32_t jitterPpm, uint32_t drif t->driftPpm = driftPpm; t->callInfo = info; t->callData = data; + t->useRtc = useRtc; + t->tid = osGetCurrentTid(); /* as soon as we write timer Id, it becomes valid and might fire */ t->id = timId; - t->tid = osGetCurrentTid(); /* fire as needed & recalc alarms*/ timFireAsNeededAndUpdateAlarms(); @@ -194,17 +202,17 @@ static uint32_t timTimerSetEx(uint64_t length, uint32_t jitterPpm, uint32_t drif uint32_t timTimerSet(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, TimTimerCbkF cbk, void* data, bool oneShot) { - return timTimerSetEx(length, jitterPpm, driftPpm, taggedPtrMakeFromPtr(cbk), data, oneShot); + return timTimerSetEx(length, jitterPpm, driftPpm, taggedPtrMakeFromPtr(cbk), data, oneShot, false); } uint32_t timTimerSetAsApp(uint64_t length, uint32_t jitterPpm, uint32_t driftPpm, uint32_t tid, void* data, bool oneShot) { - return timTimerSetEx(length, jitterPpm, driftPpm, taggedPtrMakeFromUint(0), data, oneShot); + return timTimerSetEx(length, jitterPpm, driftPpm, taggedPtrMakeFromUint(0), data, oneShot, false); } uint32_t timTimerSetNew(uint64_t length, const void* data, bool oneShot) { - return timTimerSetEx(length, 0, 0, taggedPtrMakeFromUint(0), (void *)data, oneShot); + return timTimerSetEx(length, 0, 50, taggedPtrMakeFromUint(0), (void *)data, oneShot, true); } static bool timerEventMatch(uint32_t evtType, const void *evtData, void *context) diff --git a/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c b/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c index e8d88422..054faa8c 100644 --- a/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c +++ b/firmware/os/drivers/bosch_bmi160/bosch_bmi160.c @@ -258,6 +258,18 @@ #define MAX_NUM_COMMS_EVENT_SAMPLES 15 +#ifndef BMI160_ACC_SAMPLES +#define BMI160_ACC_SAMPLES 3000 +#endif + +#ifndef BMI160_GYRO_SAMPLES +#define BMI160_GYRO_SAMPLES 20 +#endif + +#ifndef BMI160_MAG_SAMPLES +#define BMI160_MAG_SAMPLES 600 +#endif + // Default accel range is 8g #ifndef BMI160_ACC_RANGE_G #define BMI160_ACC_RANGE_G 8 @@ -748,18 +760,19 @@ static const struct SensorInfo mSensorInfo[NUM_OF_SENSOR] = { #ifdef ACCEL_CAL_ENABLED { DEC_INFO_RATE_RAW_BIAS("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE, - NANOHUB_INT_NONWAKEUP, 3000, SENS_TYPE_ACCEL_RAW, 1.0/kScale_acc, - SENS_TYPE_ACCEL_BIAS) }, + NANOHUB_INT_NONWAKEUP, BMI160_ACC_SAMPLES, SENS_TYPE_ACCEL_RAW, + 1.0/kScale_acc, SENS_TYPE_ACCEL_BIAS) }, #else { DEC_INFO_RATE_RAW("Accelerometer", AccRates, SENS_TYPE_ACCEL, NUM_AXIS_THREE, - NANOHUB_INT_NONWAKEUP, 3000, SENS_TYPE_ACCEL_RAW, 1.0/kScale_acc) }, + NANOHUB_INT_NONWAKEUP, BMI160_ACC_SAMPLES, SENS_TYPE_ACCEL_RAW, + 1.0/kScale_acc) }, #endif { DEC_INFO_RATE_BIAS("Gyroscope", GyrRates, SENS_TYPE_GYRO, NUM_AXIS_THREE, - NANOHUB_INT_NONWAKEUP, 20, SENS_TYPE_GYRO_BIAS) }, + NANOHUB_INT_NONWAKEUP, BMI160_GYRO_SAMPLES, SENS_TYPE_GYRO_BIAS) }, #ifdef MAG_SLAVE_PRESENT { DEC_INFO_RATE_RAW_BIAS("Magnetometer", MagRates, SENS_TYPE_MAG, NUM_AXIS_THREE, - NANOHUB_INT_NONWAKEUP, 600, SENS_TYPE_MAG_RAW, 1.0/kScale_mag, - SENS_TYPE_MAG_BIAS) }, + NANOHUB_INT_NONWAKEUP, BMI160_MAG_SAMPLES, SENS_TYPE_MAG_RAW, + 1.0/kScale_mag, SENS_TYPE_MAG_BIAS) }, #endif { DEC_INFO("Step Detector", SENS_TYPE_STEP_DETECT, NUM_AXIS_EMBEDDED, NANOHUB_INT_NONWAKEUP, 100) }, diff --git a/firmware/os/inc/chreApi.h b/firmware/os/inc/chreApi.h index cf9bd499..e355ed5a 100644 --- a/firmware/os/inc/chreApi.h +++ b/firmware/os/inc/chreApi.h @@ -34,12 +34,17 @@ C_STATIC_ASSERT(va_list_size, sizeof(va_list) == sizeof(uint32_t)); C_STATIC_ASSERT(uintptr_size, sizeof(uintptr_t) >= sizeof(uint32_t)); //EXTERNAL API +//level 1 indices in the CHRE table #define SYSCALL_CHRE_MAIN 0 -#define SYSCALL_CHRE_LAST 1 +#define SYSCALL_CHRE_DRIVERS 1 +#define SYSCALL_CHRE_LAST 2 // always last. holes are allowed, but not immediately before this +//level 2 indices in the CHRE.main table #define SYSCALL_CHRE_MAIN_API 0 -#define SYSCALL_CHRE_MAIN_LAST 1 +#define SYSCALL_CHRE_MAIN_EVENT 1 +#define SYSCALL_CHRE_MAIN_LAST 2 // always last. holes are allowed, but not immediately before this +//level 3 indices in the CHRE.main.api table #define SYSCALL_CHRE_MAIN_API_GET_APP_ID 0 // (void) -> uint64_t #define SYSCALL_CHRE_MAIN_API_GET_INST_ID 1 // (void) -> uint32_t #define SYSCALL_CHRE_MAIN_API_LOG_OLD 2 // (enum LogLevel, const char *, uintptr_t) -> void @@ -52,14 +57,49 @@ C_STATIC_ASSERT(uintptr_size, sizeof(uintptr_t) >= sizeof(uint32_t)); #define SYSCALL_CHRE_MAIN_API_SEND_EVENT 9 // (uint32_t, void *, chreEventCompleteFunction*, uint32_t) -> bool #define SYSCALL_CHRE_MAIN_API_SEND_MSG 10 // (void *, uint32_t, uint32_t, chreMessageFreeFunction *) -> bool #define SYSCALL_CHRE_MAIN_API_SENSOR_FIND_DEFAULT 11 // -#define SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO 12 // +#define SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO_OLD 12 // #define SYSCALL_CHRE_MAIN_API_SENSOR_GET_STATUS 13 // #define SYSCALL_CHRE_MAIN_API_SENSOR_CONFIG 14 // #define SYSCALL_CHRE_MAIN_API_GET_OS_API_VERSION 15 // #define SYSCALL_CHRE_MAIN_API_GET_OS_VERSION 16 // #define SYSCALL_CHRE_MAIN_API_GET_PLATFORM_ID 17 // #define SYSCALL_CHRE_MAIN_API_LOG 18 // (enum LogLevel, const char *, uintptr_t) -> void -#define SYSCALL_CHRE_MAIN_API_LAST 19 // always last. holes are allowed, but not immediately before this +#define SYSCALL_CHRE_MAIN_API_SENSOR_GET_INFO 19 // +#define SYSCALL_CHRE_MAIN_API_GET_HOST_TIME_OFFSET 20 // (void) -> int64_t +#define SYSCALL_CHRE_MAIN_API_LAST 21 // always last. holes are allowed, but not immediately before this + +//level 3 indices in the CHRE.main.event table +#define SYSCALL_CHRE_MAIN_EVENT_SEND_EVENT 0 // (uint32_t, void *, chreEventCompleteFunction*, uint32_t) -> bool +#define SYSCALL_CHRE_MAIN_EVENT_SEND_MSG 1 // (void *, size_t, uint32_t, uint16_t, chreMessageFreeFunction *) -> bool +#define SYSCALL_CHRE_MAIN_EVENT_INFO_BY_APP_ID 2 // (uint64_t, struct chreNanoappInfo *) -> bool +#define SYSCALL_CHRE_MAIN_EVENT_INFO_BY_INST_ID 3 // (uint32_t, struct chreNanoappInfo *) -> bool +#define SYSCALL_CHRE_MAIN_EVENT_CFG_INFO 4 // (bool) -> void +#define SYSCALL_CHRE_MAIN_EVENT_LAST 5 // always last. holes are allowed, but not immediately before this + +//level 2 indices in the CHRE.drivers table +#define SYSCALL_CHRE_DRV_GNSS 0 +#define SYSCALL_CHRE_DRV_WIFI 1 +#define SYSCALL_CHRE_DRV_WWAN 2 +#define SYSCALL_CHRE_DRV_LAST 3 // always last. holes are allowed, but not immediately before this + +//level 3 indices in the CHRE.drivers.gnss table +#define SYSCALL_CHRE_DRV_GNSS_GET_CAP 0 // (void) -> uint32_t +#define SYSCALL_CHRE_DRV_GNSS_LOC_START_ASYNC 1 // (uint32_t, uint32_t const void *) -> bool +#define SYSCALL_CHRE_DRV_GNSS_LOC_STOP_ASYNC 2 // (const void *) -> bool +#define SYSCALL_CHRE_DRV_GNSS_MEAS_START_ASYNC 3 // (uint32_t, const void *) -> bool +#define SYSCALL_CHRE_DRV_GNSS_MEAS_STOP_ASYNC 4 // (const void *) -> bool +#define SYSCALL_CHRE_DRV_GNSS_LAST 5 // always last. holes are allowed, but not immediately before this + +//level 3 indices in the CHRE.drivers.wifi table +#define SYSCALL_CHRE_DRV_WIFI_GET_CAP 0 // (void) -> uint32_t +#define SYSCALL_CHRE_DRV_WIFI_CONF_SCAN_MON_ASYNC 1 // (bool, const void *) -> bool +#define SYSCALL_CHRE_DRV_WIFI_REQ_SCAN_ASYNC 2 // (const struct chreWifiScanParams *, const void *) -> bool +#define SYSCALL_CHRE_DRV_WIFI_LAST 3 // always last. holes are allowed, but not immediately before this + +//level 3 indices in the CHRE.drivers.wwan table +#define SYSCALL_CHRE_DRV_WWAN_GET_CAP 0 // (void) -> uint32_t +#define SYSCALL_CHRE_DRV_WWAN_GET_CELL_INFO_ASYNC 1 // (const void *cookie) -> bool +#define SYSCALL_CHRE_DRV_WWAN_LAST 2 // always last. holes are allowed, but not immediately before this //called by os entry point to export the api void osChreApiExport(void); diff --git a/firmware/os/inc/eventnums.h b/firmware/os/inc/eventnums.h index 246587a3..5746433e 100644 --- a/firmware/os/inc/eventnums.h +++ b/firmware/os/inc/eventnums.h @@ -29,8 +29,10 @@ #define EVT_APP_TO_HOST 0x00000401 //app data to host. Type is struct HostHubRawPacket #define EVT_MARSHALLED_SENSOR_DATA 0x00000402 //marshalled event data. Type is MarshalledUserEventData #define EVT_RESET_REASON 0x00000403 //reset reason to host. -#define EVT_APP_TO_SENSOR_HAL_DATA 0x00000404 // sensor driver out of band data update to sensor hal -#define EVT_DEBUG_LOG 0x00007F01 // send message payload to Linux kernel log +#define EVT_APP_TO_SENSOR_HAL_DATA 0x00000404 //sensor driver out of band data update to sensor hal +#define EVT_APP_STARTED 0x00000405 //sent when a app has successfully started +#define EVT_APP_STOPPED 0x00000406 //sent when a app has stopped +#define EVT_DEBUG_LOG 0x00007F01 //send message payload to Linux kernel log #define EVT_MASK 0x0000FFFF // host-side events are 32-bit @@ -54,9 +56,17 @@ struct HostHubRawPacket { SET_PACKED_STRUCT_MODE_OFF SET_PACKED_STRUCT_MODE_ON +struct NanohubMsgChreHdrV10 { + uint8_t size; + uint32_t appEvent; +}ATTRIBUTE_PACKED; +SET_PACKED_STRUCT_MODE_OFF + +SET_PACKED_STRUCT_MODE_ON struct NanohubMsgChreHdr { uint8_t size; uint32_t appEvent; + uint16_t endpoint; }ATTRIBUTE_PACKED; SET_PACKED_STRUCT_MODE_OFF @@ -103,17 +113,18 @@ SET_PACKED_STRUCT_MODE_OFF //for all apps #define EVT_APP_FREE_EVT_DATA 0x000000FF //sent to an external app when its event has been marked for freeing. Data: struct AppEventFreeData // this event is never enqueued; it goes directly to the app. -// It notifies app that hav outstanding IO, that is is about to end; +// It notifies app that have outstanding IO, that is is about to end; // Expected app behavior is to not send any more events to system; // any events sent after this point will be silently ignored by the system; -// any outstading events will be allowed to proceed to completion. (this is SIG_STOP) +// any outstanding events will be allowed to proceed to completion. (this is SIG_STOP) #define EVT_APP_STOP 0x000000FE // Internal event, with task pointer as event data; // system ends the task unconditionally; no further checks performed (this is SIG_KILL) #define EVT_APP_END 0x000000FD +#define EVT_APP_BEGIN 0x000000FC //for host comms -#define EVT_APP_FROM_HOST 0x000000F8 //host data to an app. Type is struct HostMsgHdr #define EVT_APP_FROM_HOST_CHRE 0x000000F9 //host data to an app. Type is struct HostMsgHdrChre +#define EVT_APP_FROM_HOST 0x000000F8 //host data to an app. Type is struct HostMsgHdr //for apps that use I2C #define EVT_APP_I2C_CBK 0x000000F0 //data pointer points to struct I2cEventData diff --git a/firmware/os/inc/nanohubCommand.h b/firmware/os/inc/nanohubCommand.h index 0c4c5220..408cffdc 100644 --- a/firmware/os/inc/nanohubCommand.h +++ b/firmware/os/inc/nanohubCommand.h @@ -41,5 +41,6 @@ struct NanohubHalCommand { const struct NanohubHalCommand *nanohubHalFindCommand(uint8_t msg); uint64_t hostGetTime(void); +int64_t hostGetTimeDelta(void); #endif /* __NANOHUBCOMMAND_H */ diff --git a/firmware/os/inc/osApi.h b/firmware/os/inc/osApi.h index 77cff48f..03f91264 100644 --- a/firmware/os/inc/osApi.h +++ b/firmware/os/inc/osApi.h @@ -17,11 +17,8 @@ #ifndef _OS_API_H_ #define _OS_API_H_ -#include <stdint.h> #include <slab.h> -#include <seos_priv.h> - //EXTERNAL API //level 1 indices in the OS table #define SYSCALL_OS_MAIN 0 @@ -127,8 +124,5 @@ //called by os entry point to export the api void osApiExport(struct SlabAllocator *mainSlubAllocator); - - - #endif diff --git a/firmware/os/inc/sensors.h b/firmware/os/inc/sensors.h index 7074a258..19fd3ecc 100644 --- a/firmware/os/inc/sensors.h +++ b/firmware/os/inc/sensors.h @@ -281,6 +281,8 @@ bool sensorSelfTest(uint32_t sensorHandle); bool sensorCfgData(uint32_t sensorHandle, void* cfgData); uint32_t sensorGetCurRate(uint32_t sensorHandle); uint64_t sensorGetCurLatency(uint32_t sensorHandle); +uint32_t sensorGetHwRate(uint32_t sensorHandle); +uint64_t sensorGetHwLatency(uint32_t sensorHandle); uint32_t sensorGetReqRate(uint32_t sensorHandle); uint64_t sensorGetReqLatency(uint32_t sensorHandle); uint64_t sensorGetTime(void); diff --git a/firmware/os/inc/seos.h b/firmware/os/inc/seos.h index 7979d762..2b52b5c9 100644 --- a/firmware/os/inc/seos.h +++ b/firmware/os/inc/seos.h @@ -126,6 +126,12 @@ struct AppEventFreeData { //goes with EVT_APP_FREE_EVT_DATA void* evtData; }; +struct AppEventStartStop { + uint64_t appId; + uint32_t version; + uint16_t tid; +}; + typedef void (*OsDeferCbkF)(void *); typedef void (*EventFreeF)(void* event); @@ -262,11 +268,13 @@ bool osEraseShared(); bool osRetainCurrentEvent(TaggedPtr *evtFreeingInfoP); //called from any apps' event handling to retain current event. Only valid for first app that tries. evtFreeingInfoP filled by call and used to free evt later void osFreeRetainedEvent(uint32_t evtType, void *evtData, TaggedPtr *evtFreeingInfoP); -uint32_t osExtAppStopApps(uint64_t appId); -uint32_t osExtAppEraseApps(uint64_t appId); -uint32_t osExtAppStartApps(uint64_t appId); +uint32_t osExtAppStopAppsByAppId(uint64_t appId); +uint32_t osExtAppEraseAppsByAppId(uint64_t appId); +uint32_t osExtAppStartAppsByAppId(uint64_t appId); +uint32_t osExtAppStartAppsDelayed(); bool osAppIsChre(uint16_t tid); +uint32_t osAppChreVersion(uint16_t tid); /* Logging */ enum LogLevel { diff --git a/firmware/os/inc/seos_priv.h b/firmware/os/inc/seos_priv.h index e2dd7643..862d5224 100644 --- a/firmware/os/inc/seos_priv.h +++ b/firmware/os/inc/seos_priv.h @@ -19,6 +19,7 @@ #include <inttypes.h> #include <seos.h> +#include <chre.h> #define NO_NODE (TaskIndex)(-1) #define for_each_task(listHead, task) for (task = osTaskByIdx((listHead)->next); task; task = osTaskByIdx(task->list.next)) @@ -26,6 +27,7 @@ #define TID_TO_TASK_IDX(tid) (tid & TASK_TID_IDX_MASK) #define FL_TASK_STOPPED 1 +#define FL_TASK_ABORTED 2 #define EVT_SUBSCRIBE_TO_EVT 0x00000000 #define EVT_UNSUBSCRIBE_TO_EVT 0x00000001 @@ -108,6 +110,8 @@ union SeosInternalSlabData { union OsApiSlabItem osApiItem; }; +typedef bool (*appMatchFunc)(const void *cookie, const struct AppHdr *); + uint8_t osTaskIndex(struct Task *task); struct Task *osGetCurrentTask(); struct Task *osSetCurrentTask(struct Task *task); @@ -122,6 +126,19 @@ static inline bool osTaskIsChre(const struct Task *task) return task->app && (task->app->hdr.fwFlags & FL_APP_HDR_CHRE) != 0; } +static inline uint32_t osTaskChreVersion(const struct Task *task) +{ + if (osTaskIsChre(task)) { + // Apps loaded on 1.0 stored 0xFF in both rfu bytes + if (task->app->hdr.chreApiMajor == 0xFF && task->app->hdr.chreApiMinor == 0xFF) + return CHRE_API_VERSION_1_0; + else + return task->app->hdr.chreApiMajor << 24 | task->app->hdr.chreApiMinor << 16; + } else { + return 0; + } +} + static inline void osTaskMakeNewTid(struct Task *task) { task->tid = ((task->tid + TASK_TID_INCREMENT) & TASK_TID_COUNTER_MASK) | diff --git a/inc/chre.h b/inc/chre.h deleted file mode 100644 index 5f454984..00000000 --- a/inc/chre.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_H_ -#define _CHRE_H_ - -/** - * This header file includes all the headers which combine to fully defined - * the interface for the Context Hub Runtime Environment (CHRE). This is the - * environment in which a nanoapp runs. - * - * This interface is of interest to both implementors of CHREs and - * authors of nanoapps. The API documentation attempts to address concerns - * of both. - * - * See individual header files for API specific, and general comments below - * for overall platform information. - */ - -#include <chre/event.h> -#include <chre/nanoapp.h> -#include <chre/re.h> -#include <chre/sensor.h> -#include <chre/version.h> - - -/** - * Entry points. - * - * The following entry points are required to be handled by the CHRE - * implementation, and the functions must all be implemented by nanoapps. - * o nanoappStart function (see chre_nanoapp.h) - * o nanoappHandleEvent function (see chre_nanoapp.h) - * o nanoappEnd function (see chre_nanoapp.h) - * o bss section zeroed out (prior to nanoappStart) - * o static variables initialized (prior to nanoappStart) - * o global C++ constructors called (prior to nanoappStart) - * o global C++ destructors called (after nanoappEnd) - */ - - -/** - * Threading model. - * - * A CHRE implementation is free to chose among many different - * threading models, including a single threaded system or a multi-threaded - * system with preemption. The current platform definition is agnostic to this - * underlying choice [1]. - * - * However, the Platform does require that all nanoapps are treated as - * non-reentrant. That is, any of the functions of the nanoapp, including - * the entry points defined above and the memory freeing callbacks defined - * below, cannot be invoked by the CHRE if a previous invocation - * hasn't completed. Note this means no nanoapp function can be invoked - * from an interrupt context. - * - * For example, if a nanoapp is currently in nanoappHandleEvent(), the CHRE is - * not allowed to call nanoappHandleEvent() again, or to call a memory freeing - * callback. Similarly, if a nanoapp is currently in a memory freeing - * callback, the CHRE is not allowed to call nanoappHandleEvent(), or invoke - * another memory freeing callback. - * - * There are two exceptions to this rule: If an invocation of chreSendEvent() - * fails (returns 'false'), it is allowed to immediately invoke the memory - * freeing callback passed into that function. This is a rare case, and one - * where otherwise a CHRE implementation is likely to leak memory. Similarly, - * chreSendMessageToHost() is allowed to invoke the memory freeing callback - * directly, whether it returns 'true' or 'false'. This is because the CHRE - * implementation may copy the message data to its own buffer, and therefore - * wouldn't need the nanoapp-supplied buffer after chreSendMessageToHost() - * returns. - * - * For a nanoapp author, this means no thought needs to be given to - * synchronization issues with global objects, as they will, by definition, - * only be accessed by a single thread at once. - * - * - * [1] Note to CHRE implementors: A future version of the CHRE platform may - * require multi-threading with preemption. This is mentioned as a heads up, - * and to allow implementors deciding between implementation approaches to - * make the most informed choice. - */ - -/** - * Notes on timing. - * - * Nanoapps should expect to be running on a highly constrained system, with - * little memory and little CPU. Any single nanoapp should expect to - * be one of several nanoapps on the system, which also share the CPU with the - * CHRE and possibly other services as well. - * - * Thus, a nanoapp needs to be efficient in its memory and CPU usage. - * Also, as noted in the Threading Model section, a CHRE implementation may - * be single threaded. As a result, all methods invoked in a nanoapp - * (like nanoappStart, nanoappHandleEvent, memory free callbacks, etc.) - * must run "quickly". "Quickly" is difficult to define, as there is a - * diversity of Context Hub hardware. For Android N, there is no firm - * definition of "quickly", but expect this term to gain definition in - * future releases as we get feedback from partners. - * - * In order to write a nanoapp that will be able to adopt to future - * stricter notions of "quickly", all nanoapp methods should be written so - * they execute in a small amount of time. Some nanoapps may have the need - * to occasionally perform a large block of calculations, which may seem - * to violate this. The recommended approach in this case is to - * split up the large block of calculations into smaller batches. In one - * call into the nanoapp, the nanoapp can perform the first batch, and then - * send an event (chreSendEvent()) to itself indicating which batch should be - * done next. This will allow the nanoapp to perform the entire calculation - * over time, without monopolizing system resources. - */ - -/** - * Floating point support. - * - * The C type 'float' is used in this API, and thus a CHRE implementation - * is required to support 'float's. - * - * Support of the C types 'double' and 'long double' is optional for a - * CHRE implementation. Note that if a CHRE decides to support them, unlike - * 'float' support, there is no requirement that this support is particularly - * efficient. So nanoapp authors should be aware this may be inefficient. - * - * If a CHRE implementation choses not to support 'double' or - * 'long double', then the build toolchain setup provided needs to set - * the preprocessor define CHRE_NO_DOUBLE_SUPPORT. - */ - -/** - * CHRE and Nanoapp compatibility. - * - * The Android N release introduces the first version of this API. - * It is anticipated that there will be a lot of feedback from - * Android partners on this initial API. To allow more flexibility - * in addressing that feedback, there is no plan to assure - * binary compatibility between the Android N and Android O CHRE - * implementations and nanoapps. - * - * That is, a nanoapp built with the Android O version of this - * API should not expect to run on a CHRE built with - * the Android N API. Similarly, a nanoapp build with the - * Android N API should not expect to run on a CHRE - * build with the Android O API. Such a nanoapp will need to - * recompiled with the appropriate API in order to work. - */ - -#endif /* _CHRE_H_ */ - diff --git a/inc/chre/event.h b/inc/chre/event.h deleted file mode 100644 index 0f088bb8..00000000 --- a/inc/chre/event.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_EVENT_H_ -#define _CHRE_EVENT_H_ - -/** - * Context Hub Runtime Environment API dealing with events and messages. - */ - - -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The CHRE implementation is required to provide the following - * preprocessor defines via the build system. - * - * CHRE_MESSAGE_TO_HOST_MAX_SIZE: The maximum size, in bytes, allowed for - * a message sent to chreSendMessageToHost(). This must be at least - * CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE. - */ - -#ifndef CHRE_MESSAGE_TO_HOST_MAX_SIZE -#error CHRE_MESSAGE_TO_HOST_MAX_SIZE must be defined by the Context Hub Runtime Environment implementation -#endif - -/** - * The minimum size, in bytes, any CHRE implementation will - * use for CHRE_MESSAGE_TO_HOST_MAX_SIZE. - */ -#define CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE 128 - -#if CHRE_MESSAGE_TO_HOST_MAX_SIZE < CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE -#error CHRE_MESSAGE_TO_HOST_MAX_SIZE is too small. -#endif - -/** - * The lowest numerical value legal for a user-defined event. - * - * The system reserves all event values from 0 to 0x7FFF, inclusive. - * User events may use any value in the range 0x8000 to 0xFFFF, inclusive. - * - * Note that the same event values might be used by different nanoapps - * for different meanings. This is not a concern, as these values only - * have meaning when paired with the originating nanoapp. - */ -#define CHRE_EVENT_FIRST_USER_VALUE UINT16_C(0x8000) - -/** - * nanoappHandleEvent argument: struct chreMessageFromHostData - * - * The format of the 'message' part of this structure is left undefined, - * and it's up to the nanoapp and host to have an established protocol - * beforehand. - */ -#define CHRE_EVENT_MESSAGE_FROM_HOST UINT16_C(0x0001) - -/** - * nanoappHandleEvent argument: 'cookie' given to chreTimerSet() method. - * - * Indicates that a timer has elapsed, in accordance with how chreTimerSet() was - * invoked. - */ -#define CHRE_EVENT_TIMER UINT16_C(0x0002) - -/** - * First possible value for CHRE_EVENT_SENSOR events. - * - * This allows us to separately define our CHRE_EVENT_SENSOR_* events in - * chre_sensor.h, without fear of collision with other event values. - */ -#define CHRE_EVENT_SENSOR_FIRST_EVENT UINT16_C(0x0100) - -/** - * Last possible value for CHRE_EVENT_SENSOR events. - * - * This allows us to separately define our CHRE_EVENT_SENSOR_* events in - * chre_sensor.h, without fear of collision with other event values. - */ -#define CHRE_EVENT_SENSOR_LAST_EVENT UINT16_C(0x02FF) - -/** - * First in a range of values dedicated for internal CHRE implementation usage. - * - * If a CHRE wishes to use events internally, any values within this range - * are assured not to be taken by future CHRE API additions. - */ -#define CHRE_EVENT_INTERNAL_FIRST_EVENT UINT16_C(0x7E00) - -/** - * Last in a range of values dedicated for internal CHRE implementation usage. - * - * If a CHRE wishes to use events internally, any values within this range - * are assured not to be taken by future CHRE API additions. - */ -#define CHRE_EVENT_INTERNAL_LAST_EVENT UINT16_C(0x7FFF) - - -/** - * CHRE_EVENT_MESSAGE_FROM_HOST - */ -struct chreMessageFromHostData { - /** - * Message type (NOTE: not implemented correctly in the Android N release). - * - * In future releases, this will be a message type provided by the host. - */ - uint32_t reservedMessageType; - - /** - * The size, in bytes of the following 'message'. - * - * This can be 0. - */ - uint32_t messageSize; - - /** - * The message from the host. - * - * These contents are of a format that the host and nanoapp must have - * established beforehand. - * - * This data is 'messageSize' bytes in length. Note that if 'messageSize' - * is 0, this might be NULL. - */ - const void *message; -}; - -/** - * Callback which frees data associated with an event. - * - * This callback is (optionally) provided to the chreSendEvent() method as - * a means for freeing the event data and performing any other cleanup - * necessary when the event is completed. When this callback is invoked, - * 'eventData' is no longer needed and can be released. - * - * @param eventType The 'eventType' argument from chreSendEvent(). - * @param eventData The 'eventData' argument from chreSendEvent(). - * - * @see chreSendEvent - */ -typedef void (chreEventCompleteFunction)(uint16_t eventType, void *eventData); - -/** - * Callback which frees a message. - * - * This callback is (optionally) provided to the chreSendMessageToHost() method - * as a means for freeing the message. When this callback is invoked, - * 'message' is no longer needed and can be released. Note that this in - * no way assures that said message did or did not make it to the host, simply - * that this memory is no longer needed. - * - * @param message The 'message' argument from chreSendMessageToHost(). - * @param messageSize The 'messageSize' argument from chreSendMessageToHost(). - * - * @see chreSendMessageToHost - */ -typedef void (chreMessageFreeFunction)(void *message, size_t messageSize); - - - -/** - * Enqueue an event to be sent to another nanoapp. - * - * Note: This version of the API does not give an easy means to discover - * another nanoapp's instance ID. For now, events will need to be sent to/from - * the host to initially discover these IDs. - * - * @param eventType This is a user-defined event type, of at least the - * value CHRE_EVENT_FIRST_USER_VALUE. It is illegal to attempt to use any - * of the CHRE_EVENT_* values reserved for the CHRE. - * @param eventData A pointer value that will be understood by the receiving - * app. Note that NULL is perfectly acceptable. It also is not required - * that this be a valid pointer, although if this nanoapp is intended to - * work on arbitrary CHRE implementations, then the size of a - * pointer cannot be assumed to be a certain size. Note that the caller - * no longer owns this memory after the call. - * @param freeCallback A pointer to a callback function. After the lifetime - * of 'eventData' is over (either through successful delivery or the event - * being dropped), this callback will be invoked. This argument is allowed - * to be NULL, in which case no callback will be invoked. - * @param targetInstanceId The ID of the instance we're delivering this event - * to. Note that this is allowed to be our own instance. - * @returns true if the event was enqueued, false otherwise. Note that even - * if this method returns 'false', the 'freeCallback' will be invoked, - * if non-NULL. Note in the 'false' case, the 'freeCallback' may be - * invoked directly from within chreSendEvent(), so it's necessary - * for nanoapp authors to avoid possible recursion with this. - * - * @see chreEventDataFreeFunction - */ -bool chreSendEvent(uint16_t eventType, void *eventData, - chreEventCompleteFunction *freeCallback, - uint32_t targetInstanceId); - -/** - * Send a message to the host. - * - * This message is by definition arbitrarily defined. Since we're not - * just a passing a pointer to memory around the system, but need to copy - * this into various buffers to send it to the host, the CHRE - * implementation cannot be asked to support an arbitrarily large message - * size. As a result, we have the CHRE implementation define - * CHRE_MESSAGE_TO_HOST_MAX_SIZE. - * - * CHRE_MESSAGE_TO_HOST_MAX_SIZE is not given a value by the Platform API. The - * Platform API does define CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE, and requires - * that CHRE_MESSAGE_TO_HOST_MAX_SIZE is at least that value. - * - * As a result, if your message sizes are all less than - * CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE, then you have no concerns on any - * CHRE implementation. If your message sizes are larger, you'll need to - * come up with a strategy for splitting your message across several calls - * to this method. As long as that strategy works for - * CHRE_MESSAGE_TO_HOST_MINIMUM_MAX_SIZE, it will work across all CHRE - * implementations (although on some implementations less calls to this - * method may be necessary). - * - * @param message Pointer to a block of memory to send to the host. - * NULL is acceptable only if messageSize is 0. If non-NULL, this - * must be a legitimate pointer (that is, unlike chreSendEvent(), a small - * integral value cannot be cast to a pointer for this). Note that the - * caller no longer owns this memory after the call. - * @param messageSize The size, in bytes, of the given message. - * This cannot exceed CHRE_MESSAGE_TO_HOST_MAX_SIZE. - * @param reservedMessageType Message type sent to the app on the host. - * NOTE: In the N release, there is a bug in some HAL implementations - * where this data does not make it to the app running on the host. - * Nanoapps cannot trust this across all platforms for N, but that - * will be fixed in O. - * @param freeCallback A pointer to a callback function. After the lifetime - * of 'message' is over (which does not assure that 'message' made it to - * the host, just that the transport layer no longer needs this memory), - * this callback will be invoked. This argument is allowed - * to be NULL, in which case no callback will be invoked. - * @returns true if the message was accepted for transmission, false otherwise. - * Note that even if this method returns 'false', the 'freeCallback' will - * be invoked, if non-NULL. In either case, the 'freeCallback' may be - * invoked directly from within chreSendMessageToHost(), so it's necessary - * for nanoapp authors to avoid possible recursion with this. - * - * @see chreMessageFreeFunction - */ -bool chreSendMessageToHost(void *message, uint32_t messageSize, - uint32_t reservedMessageType, - chreMessageFreeFunction *freeCallback); - - -#ifdef __cplusplus -} -#endif - -#endif /* _CHRE_EVENT_H_ */ - diff --git a/inc/chre/nanoapp.h b/inc/chre/nanoapp.h deleted file mode 100644 index 78a8accd..00000000 --- a/inc/chre/nanoapp.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_NANOAPP_H_ -#define _CHRE_NANOAPP_H_ - -/** - * Methods in the Context Hub Runtime Environment which must be implemented - * by the nanoapp. - */ - -#include <stdbool.h> -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Method invoked by the CHRE when loading the nanoapp. - * - * Every CHRE method is legal to call from this method. - * - * @returns 'true' if the nanoapp successfully started. 'false' if the nanoapp - * failed to properly initialize itself (for example, could not obtain - * sufficient memory from the heap). If this method returns 'false', the - * nanoapp will be unloaded by the CHRE (and nanoappEnd will - * _not_ be invoked in that case). - * @see nanoappEnd - */ -bool nanoappStart(void); - -/** - * Method invoked by the CHRE when there is an event for this nanoapp. - * - * Every CHRE method is legal to call from this method. - * - * @param senderInstanceId The Instance ID for the source of this event. - * Note that this may be CHRE_INSTANCE_ID, indicating that the event - * was generated by the CHRE. - * @param eventType The event type. This might be one of the CHRE_EVENT_* - * types defined in this API. But it might also be a user-defined event. - * @param eventData The associated data, if any, for this specific type of - * event. From the nanoapp's perspective, this eventData's lifetime ends - * when this method returns, and thus any data the nanoapp wishes to - * retain must be copied. Note that interpretation of event data is - * given by the event type, and for some events may not be a valid - * pointer. See documentation of the specific CHRE_EVENT_* types for how to - * interpret this data for those. Note that for user events, you will - * need to establish what this data means. - */ -void nanoappHandleEvent(uint32_t senderInstanceId, uint16_t eventType, - const void* eventData); - -/** - * Method invoked by the CHRE when unloading the nanoapp. - * - * It is not valid to attempt to send events or messages, or to invoke functions - * which will generate events to this app, within the nanoapp implementation of - * this function. That means it is illegal for the nanoapp invoke any of the - * following: - * - chreSendEvent() - * - chreSendMessageToHost() - * - chreSensorConfigure() - * - chreSensorConfigureModeOnly() - * - chreTimerSet() - * - * @see nanoappStart - */ -void nanoappEnd(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* _CHRE_NANOAPP_H_ */ diff --git a/inc/chre/re.h b/inc/chre/re.h deleted file mode 100644 index 31b0ed7c..00000000 --- a/inc/chre/re.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_RE_H_ -#define _CHRE_RE_H_ - -/** - * Some of the core Runtime Environment utilities of the Context Hub - * Runtime Environment. - * - * This includes functions for memory allocation, logging, and timers. - */ - -#include <stdarg.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdlib.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The instance ID for the CHRE. - * - * This ID is used to identify events generated by the CHRE (as - * opposed to events generated by another nanoapp). - */ -#define CHRE_INSTANCE_ID UINT32_C(0) - -/** - * A timer ID representing an invalid timer. - * - * This valid is returned by chreTimerSet() if a timer cannot be - * started. - */ -#define CHRE_TIMER_INVALID UINT32_C(-1) - - - -/** - * Logging levels used to indicate severity level of logging messages. - * - * CHRE_LOG_ERROR: Something fatal has happened, i.e. something that will have - * user-visible consequences and won't be recoverable without explicitly - * deleting some data, uninstalling applications, wiping the data - * partitions or reflashing the entire phone (or worse). - * CHRE_LOG_WARN: Something that will have user-visible consequences but is - * likely to be recoverable without data loss by performing some explicit - * action, ranging from waiting or restarting an app all the way to - * re-downloading a new version of an application or rebooting the device. - * CHRE_LOG_INFO: Something interesting to most people happened, i.e. when a - * situation is detected that is likely to have widespread impact, though - * isn't necessarily an error. - * CHRE_LOG_DEBUG: Used to further note what is happening on the device that - * could be relevant to investigate and debug unexpected behaviors. You - * should log only what is needed to gather enough information about what - * is going on about your component. - * - * There is currently no API to turn on/off logging by level, but we anticipate - * adding such in future releases. - * - * @see chreLog - */ -enum chreLogLevel { - CHRE_LOG_ERROR, - CHRE_LOG_WARN, - CHRE_LOG_INFO, - CHRE_LOG_DEBUG -}; - - - -/** - * Get the application ID. - * - * The application ID is set by the loader of the nanoapp. This is not - * assured to be unique among all nanoapps running in the system. - * - * @returns The application ID. - */ -uint64_t chreGetAppId(void); - -/** - * Get the instance ID. - * - * The instance ID is the CHRE handle to this nanoapp. This is assured - * to be unique among all nanoapps running in the system, and to be - * different from the CHRE_INSTANCE_ID. This is the ID used to communicate - * between nanoapps. - * - * @returns The instance ID - */ -uint32_t chreGetInstanceId(void); - -/** - * A method for logging information about the system. - * - * A log entry can have a variety of levels (@see LogLevel). This function - * allows a variable number of arguments, in a printf-style format. - * - * A nanoapp needs to be able to rely upon consistent printf format - * recognition across any platform, and thus we establish formats which - * are required to be handled by every CHRE implementation. Some of the - * integral formats may seem obscure, but this API heavily uses types like - * uint32_t and uint16_t. The platform independent macros for those printf - * formats, like PRId32 or PRIx16, end up using some of these "obscure" - * formats on some platforms, and thus are required. - * - * For the initial N release, our emphasis is on correctly getting information - * into the log, and minimizing the requirements for CHRE implementations - * beyond that. We're not as concerned about how the information is visually - * displayed. As a result, there are a number of format sub-specifiers which - * are "OPTIONAL" for the N implementation. "OPTIONAL" in this context means - * that a CHRE implementation is allowed to essentially ignore the specifier, - * but it must understand the specifier enough in order to properly skip it. - * - * For a nanoapp author, an OPTIONAL format means you might not get exactly - * what you want on every CHRE implementation, but you will always get - * something sane. - * - * To be clearer, here's an example with the OPTIONAL 0-padding for integers - * for different hypothetical CHRE implementations. - * Compliant, chose to implement OPTIONAL format: - * chreLog(level, "%04x", 20) ==> "0014" - * Compliant, chose not to implement OPTIONAL format: - * chreLog(level, "%04x", 20) ==> "14" - * Non-compliant, discarded format because the '0' was assumed to be incorrect: - * chreLog(level, "%04x", 20) ==> "" - * - * Note that some of the OPTIONAL specifiers will probably become - * required in future APIs. - * - * We also have NOT_SUPPORTED specifiers. Nanoapp authors should not use any - * NOT_SUPPORTED specifiers, as unexpected things could happen on any given - * CHRE implementation. A CHRE implementation is allowed to support this - * (for example, when using shared code which already supports this), but - * nanoapp authors need to avoid these. - * - * - * Unless specifically noted as OPTIONAL or NOT_SUPPORTED, format - * (sub-)specifiers listed below are required. - * - * OPTIONAL format sub-specifiers: - * - '-' (left-justify within the given field width) - * - '+' (preceed the result with a '+' sign if it is positive) - * - ' ' (preceed the result with a blank space if no sign is going to be - * output) - * - '#' (For 'o', 'x' or 'X', preceed output with "0", "0x" or "0X", - * respectively. For floating point, unconditionally output a decimal - * point.) - * - '0' (left pad the number with zeroes instead of spaces when <width> - * needs padding) - * - <width> (A number representing the minimum number of characters to be - * output, left-padding with blank spaces if needed to meet the - * minimum) - * - '.'<precision> (A number which has different meaning depending on context.) - * - Integer context: Minimum number of digits to output, padding with - * leading zeros if needed to meet the minimum. - * - 'f' context: Number of digits to output after the decimal - * point (to the right of it). - * - 's' context: Maximum number of characters to output. - * - * Integral format specifiers: - * - 'd' (signed) - * - 'u' (unsigned) - * - 'o' (octal) - * - 'x' (hexadecimal, lower case) - * - 'X' (hexadecimal, upper case) - * - * Integral format sub-specifiers (as prefixes to an above integral format): - * - 'hh' (char) - * - 'h' (short) - * - 'l' (long) - * - 'll' (long long) - * - 'z' (size_t) - * - 't' (ptrdiff_t) - * - * Other format specifiers: - * - 'f' (floating point) - * - 'c' (character) - * - 's' (character string, terminated by '\0') - * - 'p' (pointer) - * - '%' (escaping the percent sign (i.e. "%%" becomes "%")) - * - * NOT_SUPPORTED specifiers: - * - 'n' (output nothing, but fill in a given pointer with the number - * of characters written so far) - * - '*' (indicates that the width/precision value comes from one of the - * arguments to the function) - * - 'e', 'E' (scientific notation output) - * - 'g', 'G' (Shortest floating point representation) - * - * @param level The severity level for this message. - * @param formatStr Either the entirety of the message, or a printf-style - * format string of the format documented above. - * @param ... A variable number of arguments necessary for the given - * 'formatStr' (there may be no additional arguments for some 'formatStr's). - */ -void chreLog(enum chreLogLevel level, const char *formatStr, ...); - -/** - * Get the system time. - * - * This returns a time in nanoseconds in reference to some arbitrary - * time in the past. This method is only useful for determining timing - * between events on the system, and is not useful for determining - * any sort of absolute time. - * - * This value must always increase (and must never roll over). This - * value has no meaning across CHRE reboots. - * - * @returns The system time, in nanoseconds. - */ -uint64_t chreGetTime(void); - -/** - * Set a timer. - * - * When the timer fires, nanoappHandleEvent will be invoked with - * CHRE_EVENT_TIMER and with the given 'cookie'. - * - * A CHRE implementation is required to provide at least 32 - * timers. However, there's no assurance there will be any available - * for any given nanoapp (if it's loaded late, etc). - * - * @param duration Time, in nanoseconds, before the timer fires. - * @param cookie Argument that will be sent to nanoappHandleEvent upon the - * timer firing. This is allowed to be NULL and does not need to be - * a valid pointer (assuming the nanoappHandleEvent code is expecting such). - * @param oneShot If true, the timer will just fire once. If false, the - * timer will continue to refire every 'duration', until this timer is - * canceled (@see chreTimerCancel). - * - * @returns The timer ID. If the system is unable to set a timer - * (no more available timers, etc.) then CHRE_TIMER_INVALID will - * be returned. - * - * @see nanoappHandleEvent - */ -uint32_t chreTimerSet(uint64_t duration, const void* cookie, bool oneShot); - -/** - * Cancel a timer. - * - * After this method returns, the CHRE assures there will be no more - * events sent from this timer, and any enqueued events from this timer - * will need to be evicted from the queue by the CHRE. - * - * @param timerId A timer ID obtained by this nanoapp via chreTimerSet(). - * @returns true if the timer was cancelled, false otherwise. We may - * fail to cancel the timer if it's a one shot which (just) fired, - * or if the given timer ID is not owned by the calling app. - */ -bool chreTimerCancel(uint32_t timerId); - -/** - * Terminate this nanoapp. - * - * This takes effect immediately. - * - * The CHRE will no longer execute this nanoapp. The CHRE will not invoke - * nanoappEnd(), nor will it call any memory free callbacks in the nanoapp. - * - * The CHRE will unload/evict this nanoapp's code. - * - * @param abortCode A value indicating the reason for aborting. (Note that - * in this version of the API, there is no way for anyone to access this - * code, but future APIs may expose it.) - * @returns Never. This method does not return, as the CHRE stops nanoapp - * execution immediately. - */ -void chreAbort(uint32_t abortCode); - -/** - * Allocate a given number of bytes from the system heap. - * - * The nanoapp is required to free this memory via chreHeapFree() prior to - * the nanoapp ending. - * - * While the CHRE implementation is required to free up heap resources of - * a nanoapp when unloading it, future requirements and tests focused on - * nanoapps themselves may check for memory leaks, and will require nanoapps - * to properly manage their heap resources. - * - * @param bytes The number of bytes requested. - * @returns A pointer to 'bytes' contiguous bytes of heap memory, or NULL - * if the allocation could not be performed. This pointer must be suitably - * aligned for any kind of variable. - * - * @see chreHeapFree. - */ -void* chreHeapAlloc(uint32_t bytes); - -/** - * Free a heap allocation. - * - * This allocation must be from a value returned from a chreHeapAlloc() call - * made by this nanoapp. In other words, it is illegal to free memory - * allocated by another nanoapp (or the CHRE). - * - * @param ptr 'ptr' is required to be a value returned from chreHeapAlloc(). - * Note that since chreHeapAlloc can return NULL, CHRE - * implementations must safely handle 'ptr' being NULL. - * - * @see chreHeapAlloc. - */ -void chreHeapFree(void* ptr); - - -#ifdef __cplusplus -} -#endif - -#endif /* _CHRE_RE_H_ */ - diff --git a/inc/chre/sensor.h b/inc/chre/sensor.h deleted file mode 100644 index 9e743363..00000000 --- a/inc/chre/sensor.h +++ /dev/null @@ -1,817 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_SENSOR_H_ -#define _CHRE_SENSOR_H_ - -/** - * API dealing with sensor interaction in the Context Hub Runtime - * Environment. - * - * This includes the definition of our sensor types and the ability to - * configure them for receiving events. - */ - -#include <stdbool.h> -#include <stdint.h> - -// For CHRE_EVENT_SENSOR_FIRST_EVENT and CHRE_EVENT_SENSOR_LAST_EVENT -#include <chre/event.h> - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * The CHRE_SENSOR_TYPE_* defines are the sensor types supported. - * - * Unless otherwise noted, each of these sensor types is based off of a - * corresponding sensor type in the Android API's sensors.h interface. - * For a given CHRE_SENSOR_TYPE_FOO, it corresponds to the SENSOR_TYPE_FOO in - * hardware/libhardware/include/hardware/sensors.h of the Android code base. - * - * Unless otherwise noted below, a CHRE_SENSOR_TYPE_FOO should be assumed - * to work the same as the Android SENSOR_TYPE_FOO, as documented in the - * sensors.h documentation and as detailed within the Android Compatibility - * Definition Document. - * - * Note that every sensor will generate CHRE_EVENT_SENSOR_SAMPLING_CHANGE - * events, so it is not listed with each individual sensor. - */ - -/** - * Accelerometer. - * - * Generates: CHRE_EVENT_SENSOR_ACCELEROMETER_DATA - * - * @see CHRE_EVENT_SENSOR_ACCELEROMETER_DATA - */ -#define CHRE_SENSOR_TYPE_ACCELEROMETER UINT8_C(1) - -/** - * Instantaneous motion detection. - * - * Generates: CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA - * - * This is a one-shot sensor. - * - * This does not have a direct analogy within sensors.h. This is similar - * to SENSOR_TYPE_MOTION_DETECT, but this triggers instantly upon any - * motion, instead of waiting for a period of continuous motion. - */ -#define CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT UINT8_C(2) - -/** - * Stationary detection. - * - * Generates: CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA - * - * This is a one-shot sensor. - */ -#define CHRE_SENSOR_TYPE_STATIONARY_DETECT UINT8_C(3) - -/** - * Gyroscope. - * - * Generates: CHRE_EVENT_SENSOR_GYROSCOPE_DATA and - * CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO - * - * Note that the GYROSCOPE_DATA is always the calibrated data, and not - * raw data. - */ -#define CHRE_SENSOR_TYPE_GYROSCOPE UINT8_C(6) - -/** - * Magnetometer. - * - * Generates: CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA and - * CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO - * - * Note that the GEOMAGNETIC_FIELD_DATA is always the calibrated data, and not - * raw data. - */ -#define CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD UINT8_C(8) - -/** - * Barometric pressure sensor. - * - * Generates: CHRE_EVENT_SENSOR_PRESSURE_DATA - */ -#define CHRE_SENSOR_TYPE_PRESSURE UINT8_C(10) - -/** - * Ambient light sensor. - * - * Generates: CHRE_EVENT_SENSOR_LIGHT_DATA - */ -#define CHRE_SENSOR_TYPE_LIGHT UINT8_C(12) - -/** - * Proximity detection. - * - * Generates: CHRE_EVENT_SENSOR_PROXIMITY_DATA - * - * This is an on-change sensor. - */ -#define CHRE_SENSOR_TYPE_PROXIMITY UINT8_C(13) - -/** - * Base value for all of the data events for sensors. - * - * The value for a data event FOO is - * CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_FOO - * - * This allows for easy mapping, and also explains why there are gaps - * in our values since we don't have all possible sensor types assigned. - */ -#define CHRE_EVENT_SENSOR_DATA_EVENT_BASE CHRE_EVENT_SENSOR_FIRST_EVENT - -/** - * nanoappHandleEvent argument: struct chreSensorThreeAxisData - * - * The data can be interpreted using the 'x', 'y', and 'z' fields within - * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z). - * - * All values are in SI units (m/s^2) and measure the acceleration of the - * device minus the force of gravity. - */ -#define CHRE_EVENT_SENSOR_ACCELEROMETER_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_ACCELEROMETER) - -/** - * nanoappHandleEvent argument: struct chreSensorOccurrenceData - * - * Since this is a one-shot sensor, after this event is delivered to the - * nanoapp, the sensor automatically goes into DONE mode. Sensors of this - * type must be configured with a ONE_SHOT mode. - */ -#define CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT) - -/** - * nanoappHandleEvent argument: struct chreSensorOccurrenceData - * - * Since this is a one-shot sensor, after this event is delivered to the - * nanoapp, the sensor automatically goes into DONE mode. Sensors of this - * type must be configured with a ONE_SHOT mode. - */ -#define CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_STATIONARY_DETECT) - -/** - * nanoappHandleEvent argument: struct chreSensorThreeAxisData - * - * The data can be interpreted using the 'x', 'y', and 'z' fields within - * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z). - * - * All values are in radians/second and measure the rate of rotation - * around the X, Y and Z axis. - */ -#define CHRE_EVENT_SENSOR_GYROSCOPE_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_GYROSCOPE) - -/** - * nanoappHandleEvent argument: struct chreSensorThreeAxisData - * - * The data can be interpreted using the 'x', 'y', and 'z' fields within - * 'readings', or by the 3D array 'v' (v[0] == x; v[1] == y; v[2] == z). - * - * All values are in micro-Tesla (uT) and measure the geomagnetic - * field in the X, Y and Z axis. - */ -#define CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_GEOMAGNETIC_FIELD) - -/** - * nanoappHandleEvent argument: struct chreSensorFloatData - * - * The data can be interpreted using the 'pressure' field within 'readings'. - * This value is in hectopascals (hPa). - */ -#define CHRE_EVENT_SENSOR_PRESSURE_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_PRESSURE) - -/** - * nanoappHandleEvent argument: struct chreSensorFloatData - * - * The data can be interpreted using the 'light' field within 'readings'. - * This value is in SI lux units. - */ -#define CHRE_EVENT_SENSOR_LIGHT_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_LIGHT) - -/** - * nanoappHandleEvent argument: struct chreSensorByteData - * - * The data is interpreted from the following fields in 'readings': - * o 'isNear': If set to 1, we are nearby (on the order of centimeters); - * if set to 0, we are far. - * o 'invalid': If set to 1, this is not a valid reading of this data. - * - * As an on-change sensor, there is an event generated upon configuring - * this sensor. This is when we might get an 'invalid' reading. Thus, - * this field must be checked on the first event before interpreting 'isNear'. - */ -#define CHRE_EVENT_SENSOR_PROXIMITY_DATA \ - (CHRE_EVENT_SENSOR_DATA_EVENT_BASE + CHRE_SENSOR_TYPE_PROXIMITY) - - -/** - * First value for sensor events which are not data from the sensor. - * - * Unlike the data event values, these other event values don't have any - * mapping to sensor types. - */ -#define CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE \ - (CHRE_EVENT_SENSOR_FIRST_EVENT + 0x0100) - -/** - * nanoappHandleEvent argument: struct chreSensorSamplingStatusEvent - * - * Indicates that the interval and/or the latency which this sensor is - * sampling at has changed. - */ -#define CHRE_EVENT_SENSOR_SAMPLING_CHANGE \ - (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 0) - -/** - * nanoappHandleEvent argument: struct chreSensorThreeAxisData - * - * The data can be interpreted using the 'x_bias', 'y_bias', and 'z_bias' - * field within 'readings', or by the 3D array 'bias' (bias[0] == x_bias; - * bias[1] == y_bias; bias[2] == z_bias). - * - * All values are in radians/second and measure the rate of rotation - * around the X, Y and Z axis. - */ -#define CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO \ - (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 1) - -/** - * nanoappHandleEvent argument: struct chreSensorThreeAxisData - * - * The data can be interpreted using the 'x_bias', 'y_bias', and 'z_bias' - * field within 'readings', or by the 3D array 'bias' (bias[0] == x_bias; - * bias[1] == y_bias; bias[2] == z_bias). - * - * All values are in micro-Tesla (uT) and measure the geomagnetic - * field in the X, Y and Z axis. - */ -#define CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO \ - (CHRE_EVENT_SENSOR_OTHER_EVENTS_BASE + 2) - - -#if CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO > CHRE_EVENT_SENSOR_LAST_EVENT -#error Too many sensor events. -#endif - - -/** - * Value indicating we want the smallest possible latency for a sensor. - * - * This literally translates to 0 nanoseconds for the chreSensorConfigure() - * argument. While we won't get exactly 0 nanoseconds, the CHRE will - * queue up this event As Soon As Possible. - */ -#define CHRE_SENSOR_LATENCY_ASAP UINT64_C(0) - -/** - * Special value indicating non-importance of the interval. - * - * @see chreSensorConfigure - * @see chreSensorSamplingStatus - */ -#define CHRE_SENSOR_INTERVAL_DEFAULT UINT64_C(-1) - -/** - * Special value indicating non-importance of the latency. - * - * @see chreSensorConfigure - * @see chreSensorSamplingStatus - */ -#define CHRE_SENSOR_LATENCY_DEFAULT UINT64_C(-1) - - -// This is used to define elements of enum chreSensorConfigureMode. -#define CHRE_SENSOR_CONFIGURE_RAW_POWER_ON (1 << 0) - -// This is used to define elements of enum chreSensorConfigureMode. -#define CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS (1 << 1) - -// This is used to define elements of enum chreSensorConfigureMode. -#define CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT (2 << 1) - - - -/** - * Modes we can configure a sensor to use. - * - * Our mode will affect not only how/if we receive events, but - * also whether or not the sensor will be powered on our behalf. - * - * @see chreSensorConfigure - */ -enum chreSensorConfigureMode { - /** - * Get events from the sensor. - * - * Power: Turn on if not already on. - * Reporting: Continuous. Send each new event as it comes (subject to - * batching and latency). - */ - CHRE_SENSOR_CONFIGURE_MODE_CONTINUOUS = - (CHRE_SENSOR_CONFIGURE_RAW_POWER_ON | - CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS), - - /** - * Get a single event from the sensor and then become DONE. - * - * Once the event is sent, the sensor automatically - * changes to CHRE_SENSOR_CONFIGURE_MODE_DONE mode. - * - * Power: Turn on if not already on. - * Reporting: One shot. Send the next event and then be DONE. - */ - CHRE_SENSOR_CONFIGURE_MODE_ONE_SHOT = - (CHRE_SENSOR_CONFIGURE_RAW_POWER_ON | - CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT), - - /** - * Get events from a sensor that are generated for other apps. - * - * This is considered passive because the sensor will not be powered - * on for the sake of our nanoapp. If and only if another app in - * the system has requested this sensor power on will we get events. - * - * This can be useful for something which is interested in seeing data, - * but not interested enough to be responsible for powering on the sensor. - * - * Power: Do not power the sensor on our behalf. - * Reporting: Continuous. Send each event as it comes. - */ - CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS = - CHRE_SENSOR_CONFIGURE_RAW_REPORT_CONTINUOUS, - - /** - * Get a single event from a sensor that is generated for other apps. - * - * See CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_CONTINUOUS for more details - * on what be "passive" means. - * - * Power: Do not power the sensor on our behalf. - * Reporting: One shot. Send only the next event and then be DONE. - */ - CHRE_SENSOR_CONFIGURE_MODE_PASSIVE_ONE_SHOT = - CHRE_SENSOR_CONFIGURE_RAW_REPORT_ONE_SHOT, - - /** - * Indicate we are done using this sensor and no longer interested in it. - * - * See chreSensorConfigure for more details on expressing interest or - * lack of interest in a sensor. - * - * Power: Do not power the sensor on our behalf. - * Reporting: None. - */ - CHRE_SENSOR_CONFIGURE_MODE_DONE = 0, -}; - -/** - * A structure containing information about a Sensor. - * - * See documentation of individual fields below. - */ -struct chreSensorInfo { - /** - * The name of the sensor. - * - * A text name, useful for logging/debugging, describing the Sensor. This - * is not assured to be unique (i.e. there could be multiple sensors with - * the name "Temperature"). - * - * CHRE implementations may not set this as NULL. An empty - * string, while discouraged, is legal. - */ - const char *sensorName; - - /** - * One of the CHRE_SENSOR_TYPE_* defines above. - */ - uint8_t sensorType; - - /** - * Flag indicating if this sensor is on-change. - * - * An on-change sensor only generates events when underlying state - * changes. This has the same meaning as on-change does in the Android - * Sensors HAL. See sensors.h for much more details. - * - * A value of 1 indicates this is on-change. 0 indicates this is not - * on-change. - */ - uint8_t isOnChange : 1; - - /** - * Flag indicating if this sensor is one-shot. - * - * A one-shot sensor only triggers a single event, and then automatically - * disables itself. - * - * A value of 1 indicates this is on-change. 0 indicates this is not - * on-change. - */ - uint8_t isOneShot : 1; - uint8_t unusedFlags : 6; -}; - -/** - * Header used in every structure containing batchable data from a sensor. - * - * The typical structure for sensor data looks like: - * - * struct chreSensorTypeData { - * struct chreSensorDataHeader header; - * struct chreSensorTypeSampleData { - * uint32_t timestampDelta; - * union { - * <type> value; - * <type> interpretation0; - * <type> interpretation1; - * }; - * } readings[1]; - * }; - * - * Despite 'readings' being declared as an array of 1 element, - * an instance of the struct will actually have 'readings' as - * an array of header.readingCount elements (which may be 1). - * The 'timestampDelta' is in relation to the previous 'readings' (or - * the baseTimestamp for readings[0]. So, - * Timestamp for readings[0] == header.baseTimestamp + - * readings[0].timestampDelta. - * Timestamp for readings[1] == timestamp for readings[0] + - * readings[1].timestampDelta. - * And thus, in order to determine the timestamp for readings[N], it's - * necessary to process through all of the N-1 readings. The advantage, - * though, is that our entire readings can span an arbitrary length of time, - * just as long as any two consecutive readings differ by no more than - * 4.295 seconds (timestampDelta, like all time in the CHRE, is in - * nanoseconds). - * - * If a sensor has batched readings where two consecutive readings differ by - * more than 4.295 seconds, the CHRE will split them across multiple - * instances of the struct, and send multiple events. - * - * The value from the sensor is typically expressed in a union, - * allowing a generic access to the data ('value'), along with - * differently named access giving a more natural interpretation - * of the data for the specific sensor types which use this - * structure. This allows, for example, barometer code to - * reference readings[N].pressure, and an ambient light sensor - * to reference readings[N].light, while both use the same - * structure. - */ -struct chreSensorDataHeader { - /** - * The base timestamp, in nanoseconds. - */ - uint64_t baseTimestamp; - - /** - * The handle of the sensor producing this event. - */ - uint32_t sensorHandle; - - /** - * The number elements in the 'readings' array. - * - * This must be at least 1. - */ - uint16_t readingCount; - - /** - * Reserved bytes. - * - * These must be 0. - */ - uint8_t reserved[2]; -}; - -/** - * Data for a sensor which reports on three axes. - * - * This is used by CHRE_EVENT_SENSOR_ACCELEROMETER_DATA, - * CHRE_EVENT_SENSOR_GYROSCOPE_DATA, - * CHRE_EVENT_SENSOR_GYROSCOPE_BIAS_INFO, - * CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_DATA, and - * CHRE_EVENT_SENSOR_GEOMAGNETIC_FIELD_BIAS_INFO. - */ -struct chreSensorThreeAxisData { - /** - * @see chreSensorDataHeader - */ - struct chreSensorDataHeader header; - struct chreSensorThreeAxisSampleData { - /** - * @see chreSensorDataHeader - */ - uint32_t timestampDelta; - union { - float values[3]; - float v[3]; - struct { - float x; - float y; - float z; - }; - float bias[3]; - struct { - float x_bias; - float y_bias; - float z_bias; - }; - }; - } readings[1]; -}; - -/** - * Data from a sensor where we only care about a event occurring. - * - * This is a bit unusual in that our readings have no data in addition - * to the timestamp. But since we only care about the occurrence, we - * don't need to know anything else. - * - * Used by: CHRE_EVENT_SENSOR_INSTANT_MOTION_DETECT_DATA and - * CHRE_EVENT_SENSOR_STATIONARY_DETECT_DATA. - */ -struct chreSensorOccurrenceData { - struct chreSensorDataHeader header; - struct chreSensorOccurenceSampleData { - uint32_t timestampDelta; - // This space intentionally left blank. - // Only the timestamp is meaningful here, there - // is no additional data. - } readings[1]; -}; - -/** - * CHRE_EVENT_SENSOR_LIGHT_DATA and CHRE_EVENT_SENSOR_PRESSURE_DATA. - */ -struct chreSensorFloatData { - struct chreSensorDataHeader header; - struct chreSensorFloatSampleData { - uint32_t timestampDelta; - union { - float value; - float light; // lux - float pressure; // hectopascals (hPa) - }; - } readings[1]; -}; - -/** - * CHRE_EVENT_SENSOR_PROXIMITY_DATA. - */ -struct chreSensorByteData { - struct chreSensorDataHeader header; - struct chreSensorByteSampleData { - uint32_t timestampDelta; - union { - uint8_t value; - struct { - uint8_t isNear : 1; - uint8_t invalid : 1; - uint8_t padding0 : 6; - }; - }; - } readings[1]; -}; - -/** - * The status of a sensor's sampling configuration. - */ -struct chreSensorSamplingStatus { - /** - * The interval, in nanoseconds, at which the sensor is now sampling. - * - * If this is CHRE_SENSOR_INTERVAL_DEFAULT, then a sampling interval - * isn't meaningful for this sensor. - * - * Note that if 'enabled' is false, this value is not meaningful. - */ - uint64_t interval; - - /** - * The latency, in nanoseconds, at which the senor is now reporting. - * - * If this is CHRE_SENSOR_LATENCY_DEFAULT, then a latency - * isn't meaningful for this sensor. - * - * Note that if 'enabled' is false, this value is not meaningful. - */ - uint64_t latency; - - /** - * True if the sensor is actively powered and sampling; false otherwise. - */ - bool enabled; -}; - -/** - * The nanoappHandleEvent argument for CHRE_EVENT_SENSOR_SAMPLING_CHANGE. - * - * Note that only at least one of 'interval' or 'latency' must be - * different than it was prior to this event. Thus, one of these - * fields may be (but doesn't need to be) the same as before. - */ -struct chreSensorSamplingStatusEvent { - /** - * The handle of the sensor which has experienced a change in sampling. - */ - uint32_t sensorHandle; - - /** - * The new sampling status. - * - * At least one of the field in this struct will be different from - * the previous sampling status event. - */ - struct chreSensorSamplingStatus status; -}; - - - -/** - * Find the default sensor for a given sensor type. - * - * @param sensorType One of the CHRE_SENSOR_TYPE_* constants. - * @param handle If a sensor is found, then the memory will be filled with - * the value for the sensor's handle. This argument must be non-NULL. - * @returns true if a sensor was found, false otherwise. - */ -bool chreSensorFindDefault(uint8_t sensorType, uint32_t *handle); - -/** - * Get the chreSensorInfo struct for a given sensor. - * - * @param sensorHandle The sensor handle, as obtained from - * chreSensorFindDefault() or passed to nanoappHandleEvent(). - * @param info If the sensor is valid, then this memory will be filled with - * the SensorInfo contents for this sensor. This argument must be - * non-NULL. - * @returns true if the senor handle is valid and 'info' was filled in; - * false otherwise. - */ -bool chreGetSensorInfo(uint32_t sensorHandle, struct chreSensorInfo *info); - -/** - * Get the chreSensorSamplingStatus struct for a given sensor. - * - * Note that this may be different from what was requested in - * chreSensorConfigure(), for multiple reasons. It's possible that the sensor - * does not exactly support the interval requested in chreSensorConfigure(), so - * a faster one was chosen. - * - * It's also possible that there is another user of this sensor who has - * requested a faster interval and/or lower latency. This latter scenario - * should be noted, because it means the sensor rate can change due to no - * interaction from this nanoapp. Note that the - * CHRE_EVENT_SENSOR_SAMPLING_CHANGE event will trigger in this case, so it's - * not necessary to poll for such a change. - * - * @param sensorHandle The sensor handle, as obtained from - * chreSensorFindDefault() or passed to nanoappHandleEvent(). - * @param status If the sensor is valid, then this memory will be filled with - * the sampling status contents for this sensor. This argument must be - * non-NULL. - * @returns true if the senor handle is valid and 'status' was filled in; - * false otherwise. - */ -bool chreGetSensorSamplingStatus(uint32_t sensorHandle, - struct chreSensorSamplingStatus *status); - -/** - * Configures a given sensor at a specific interval and latency and mode. - * - * If this sensor's chreSensorInfo has isOneShot set to 1, - * then the mode must be one of the ONE_SHOT modes, or this method will fail. - * - * The CHRE wants to power as few sensors as possible, in keeping with its - * low power design. As such, it only turns on sensors when there are clients - * actively interested in that sensor data, and turns off sensors as soon as - * there are no clients interested in them. Calling this method generally - * indicates an interest, and using CHRE_SENSOR_CONFIGURE_MODE_DONE shows - * when we are no longer interested. - * - * Thus, each initial Configure of a sensor (per nanoapp) needs to eventually - * have a DONE call made, either directly or on its behalf. Subsequent calls - * to a Configure method within the same nanoapp, when there has been no DONE - * in between, still only require a single DONE call. - * - * For example, the following is valid usage: - * <code> - * chreSensorConfigure(myHandle, mode, interval0, latency0); - * [...] - * chreSensorConfigure(myHandle, mode, interval1, latency0); - * [...] - * chreSensorConfigure(myHandle, mode, interval1, latency1); - * [...] - * chreSensorConfigureModeOnly(myHandle, CHRE_SENSOR_CONFIGURE_MODE_DONE); - * </code> - * - * The first call to Configure is the one which creates the requirement - * to eventually call with DONE. The subsequent calls are just changing the - * interval/latency. They have not changed the fact that this nanoapp is - * still interested in output from the sensor 'myHandle'. Thus, only one - * single call for DONE is needed. - * - * There is a special case. One-shot sensors, sensors which - * just trigger a single event and never trigger again, implicitly go into - * DONE mode after that single event triggers. Thus, the - * following are legitimate usages: - * <code> - * chreSensorConfigure(myHandle, MODE_ONE_SHOT, rate, latency); - * [...] - * [myHandle triggers an event] - * [no need to configure to DONE]. - * </code> - * - * And: - * <code> - * chreSensorConfigure(myHandle, MODE_ONE_SHOT, rate, latency); - * [...] - * chreSensorConfigureModeOnly(myHandle, MODE_DONE); - * [we cancelled myHandle before it ever triggered an event] - * </code> - * - * Note that while PASSIVE modes, by definition, don't express - * an interest in powering the sensor, DONE is still necessary - * to silence the event reporting. - * - * @param sensorHandle The handle to the sensor, as obtained from - * chreSensorFindDefault(). - * @param mode The mode to use. See descriptions within the - * chreSensorConfigureMode enum. - * @param interval The interval, in nanoseconds, at which we want events from - * the sensor. On success, the sensor will be set to 'interval', or a value - * less than 'interval'. There is a special value - * CHRE_SENSOR_INTERVAL_DEFAULT, in which we don't express a preference for - * the interval, and allow the sensor to chose what it wants. Note that - * due to batching, we may receive events less frequently than - * 'interval'. - * @param latency The maximum latency, in nanoseconds, allowed before the - * CHRE begins delivery of an event. This will control how many events - * can be queued by the sensor before requiring a delivery event. - * Latency is defined as the "timestamp when event is queued by the CHRE" - * minus "timestamp of oldest unsent data reading". - * There is a special value CHRE_SENSOR_LATENCY_DEFAULT, in which we don't - * express a preference for the latency, and allow the sensor to chose what - * it wants. - * Note that there is no assurance of how long it will take an event to - * get through a CHRE's queueing system, and thus there is no ability to - * request a minimum time from the occurrence of a phenomenon to when the - * nanoapp receives the information. The current CHRE API has no - * real-time elements, although future versions may introduce some to - * help with this issue. - * @returns true if the configuration succeeded, false otherwise. - * - * @see chreSensorConfigureMode - * @see chreSensorFindDefault - * @see chreSensorInfo - */ -bool chreSensorConfigure(uint32_t sensorHandle, - enum chreSensorConfigureMode mode, - uint64_t interval, uint64_t latency); - -/** - * Short cut for chreSensorConfigure where we only want to change the mode. - * - * @see chreSensorConfigure - */ -static inline bool chreSensorConfigureModeOnly( - uint32_t sensorHandle, enum chreSensorConfigureMode mode) { - return chreSensorConfigure(sensorHandle, - mode, - CHRE_SENSOR_INTERVAL_DEFAULT, - CHRE_SENSOR_LATENCY_DEFAULT); -} - - -#ifdef __cplusplus -} -#endif - -#endif /* _CHRE_SENSOR_H_ */ - diff --git a/inc/chre/version.h b/inc/chre/version.h deleted file mode 100644 index ae6b14ca..00000000 --- a/inc/chre/version.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _CHRE_VERSION_H_ -#define _CHRE_VERSION_H_ - -/** - * Definitions and methods for the versioning of the Context Hub Runtime - * Environment. - * - * The CHRE API versioning pertains to all the chre_*.h files and chre.h. - */ - - -#include <stdint.h> - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * Value for version 0.1 of the Context Hub Runtime Environment API interface. - * - * This is a legacy version. Version 1.0 is considered the first official - * version of the API. - * - * @see CHRE_API_VERSION - */ -#define CHRE_API_VERSION_0_1 UINT32_C(0x00010000) - -/** - * Value for version 1.0 of the Context Hub Runtime Environment API interface. - * - * The version of the CHRE API which shipped with the Android Nougat release. - * - * @see CHRE_API_VERSION - */ -#define CHRE_API_VERSION_1_0 UINT32_C(0x01000000) - -/** - * Major and Minor Version of this Context Hub Runtime Environment API. - * - * The major version changes when there is an incompatible API change. - * - * The minor version changes when there is an addition in functionality - * in a backwards-compatible manner. - * - * We define the version number as an unsigned 32-bit value. The most - * significant byte is the Major Version. The second-most significant byte - * is the Minor Version. The two least significant bytes are the Patch - * Version. The Patch Version is not defined by this header API, but - * is provided by a specific CHRE implementation (see chreGetVersion()). - * - * Note that version numbers can always be numerically compared with - * expected results, so 1.0.0 < 1.0.4 < 1.1.0 < 2.0.300 < 3.5.0. - */ -#define CHRE_API_VERSION CHRE_API_VERSION_1_0 - - -/** - * Get the API version the CHRE implementation was compiled against. - * - * This is not necessarily the CHRE_API_VERSION in the header the nanoapp was - * built against, and indeed may not have even appeared in the context_hub_os.h - * header which this nanoapp was built against. - * - * By definition, this will have the two least significant bytes set to 0, - * and only contain the major and minor version number. - * - * @returns The API version. - */ -uint32_t chreGetApiVersion(void); - -/** - * Get the version of this CHRE implementation. - * - * By definition, ((chreGetApiVersion() & UINT32_C(0xFFFF0000)) == - * (chreGetVersion() & UINT32_C(0xFFFF0000))). - * - * The Patch Version, in the lower two bytes, only have meaning in context - * of this specific platform ID. It is increased by the platform every time - * a backwards-compatible bug fix is released. - * - * @returns The version. - * - * @see chreGetPlatformId() - */ -uint32_t chreGetVersion(void); - -/** - * Get the Platform ID of this CHRE. - * - * The most significant five bytes are the vendor ID as set out by the - * NANOAPP_VENDOR convention in context_hub.h, as used by nanoapp IDs. - * - * The least significant three bytes are set by the vendor, but must be - * unique for each different CHRE implementation/hardware that the vendor - * supplies. - * - * The idea is that in the case of known bugs in the field, a new nanoapp could - * be shipped with a workaround that would use this value, and chreGetVersion(), - * to have code that can conditionally work around the bug on a buggy version. - * Thus, we require this uniqueness to allow such a setup to work. - * - * @returns The platform ID. - */ -uint64_t chreGetPlatformId(void); - - -#ifdef __cplusplus -} -#endif - -#endif /* _CHRE_VERSION_H_ */ - diff --git a/lib/include/nanohub/nanohub.h b/lib/include/nanohub/nanohub.h index 451df9dd..61d1dc85 100644 --- a/lib/include/nanohub/nanohub.h +++ b/lib/include/nanohub/nanohub.h @@ -55,7 +55,9 @@ struct nano_app_binary_t { uint32_t app_version; // Version of the app uint32_t flags; // Signed, encrypted uint64_t hw_hub_type; // which hub type is this compiled for - uint32_t reserved[2]; // Should be all zeroes + uint8_t chre_api_major; // Which CHRE API version this is compiled for + uint8_t chre_api_minor; + uint8_t reserved[6]; // Should be all zeroes uint8_t custom_binary[0]; // start of custom binary data }; @@ -67,11 +69,19 @@ struct HostMsgHdr { uint8_t len; } __attribute__((packed)); +struct HostMsgHdrChreV10 { + uint32_t eventId; + uint64_t appId; + uint8_t len; + uint32_t appEventId; +} __attribute__((packed)); + struct HostMsgHdrChre { uint32_t eventId; uint64_t appId; uint8_t len; uint32_t appEventId; + uint16_t endpoint; } __attribute__((packed)); // we translate AOSP header into FW header: this header is in LE format @@ -84,7 +94,8 @@ struct FwCommonHdr { uint32_t appVer; // external: copy from AOSP header; internal: defined locally uint8_t payInfoType; // external: copy ImageLayout::payload; internal: LAYOUT_APP uint8_t payInfoSize; // sizeof(PayloadInfo) for this payload type - uint8_t rfu[2]; // filled with 0xFF + uint8_t chreApiMajor; // Chre Api Major Version (or 0xFF for non-chre nanoapps) + uint8_t chreApiMinor; // Chre Api Minor Version (or 0xFF for non-chre nanoapps) }; struct SectInfo { diff --git a/util/nanoapp_postprocess/postprocess_elf.c b/util/nanoapp_postprocess/postprocess_elf.c index aa0b2ba3..b5bf0c07 100644 --- a/util/nanoapp_postprocess/postprocess_elf.c +++ b/util/nanoapp_postprocess/postprocess_elf.c @@ -109,6 +109,7 @@ static void fatalUsage(const char *name, const char *msg, const char *arg) " -n <layout name> : app, os, key\n" " -i <layout id> : 1 (app), 2 (key), 3 (os)\n" " -f <layout flags>: 16-bit hex value, stored as layout-specific flags\n" + " -c <chre api> : 16-bit hex value, stored as chre-major + chre-minor\n" " -a <app ID> : 64-bit hex number != 0\n" " -e <app version> : 32-bit hex number\n" " -k <key ID> : 64-bit hex number != 0\n" @@ -225,7 +226,7 @@ static uint8_t *packNanoRelocs(struct NanoRelocEntry *nanoRelocs, uint32_t outNu return packedNanoRelocs; } -static int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE *out, uint32_t layoutFlags, uint64_t appId) +static int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t chreApi) { int ret; struct AppInfo app; @@ -238,12 +239,14 @@ static int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE .app_id = appId, .app_version = bin->hdr.appVer, .flags = 0, // encrypted (1), signed (2) (will be set by other tools) + .chre_api_major = chreApi >> 8, + .chre_api_minor = chreApi & 0xFF, }, .layout = (struct ImageLayout) { .magic = GOOGLE_LAYOUT_MAGIC, .version = 1, .payload = LAYOUT_APP, - .flags = layoutFlags, + .flags = layoutFlags | (chreApi ? 0x0010 : 0x0000), }, }; uint32_t dataOffset = sizeof(outHeader) + sizeof(app); @@ -285,7 +288,7 @@ static int finalizeAndWrite(uint8_t *buf, uint32_t bufUsed, uint32_t bufSz, FILE return ret; } -static int handleApp(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, bool verbose) +static int handleApp(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, uint32_t chreApi, bool verbose) { uint32_t i, numRelocs, numSyms, outNumRelocs = 0, packedNanoRelocSz; struct NanoRelocEntry *nanoRelocs = NULL; @@ -529,7 +532,7 @@ static int handleApp(uint8_t **pbuf, uint32_t bufUsed, FILE *out, uint32_t layou sect->rel_start -= FLASH_BASE + BINARY_RELOC_OFFSET; sect->rel_end -= FLASH_BASE + BINARY_RELOC_OFFSET; - ret = finalizeAndWrite(buf, bufUsed, bufSz, out, layoutFlags, appId); + ret = finalizeAndWrite(buf, bufUsed, bufSz, out, layoutFlags, appId, chreApi); out: free(nanoRelocs); return ret; @@ -786,7 +789,7 @@ out: return success; } -static int handleAppStatic(const char *fileName, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, bool verbose) +static int handleAppStatic(const char *fileName, FILE *out, uint32_t layoutFlags, uint64_t appId, uint32_t appVer, uint32_t chreApi, bool verbose) { struct ElfNanoApp app; @@ -823,7 +826,7 @@ static int handleAppStatic(const char *fileName, FILE *out, uint32_t layoutFlags hdr->sect.rel_end = hdr->sect.rel_start + app.packedNanoRelocs.size; hdr->hdr.appVer = appVer; - return finalizeAndWrite(buf, offset, bufSize, out, layoutFlags, appId); + return finalizeAndWrite(buf, offset, bufSize, out, layoutFlags, appId, chreApi); // TODO: should free all memory we allocated... just letting the OS handle // it for now } @@ -896,6 +899,7 @@ int main(int argc, char **argv) uint64_t appId = 0; uint64_t keyId = 0; uint32_t appVer = 0; + uint32_t chreApi = 0; uint32_t layoutId = 0; uint32_t layoutFlags = 0; int ret = -1; @@ -923,6 +927,8 @@ int main(int argc, char **argv) staticElf = true; else if (!strcmp(argv[i], "-a")) u64Arg = &appId; + else if (!strcmp(argv[i], "-c")) + u32Arg = &chreApi; else if (!strcmp(argv[i], "-e")) u32Arg = &appVer; else if (!strcmp(argv[i], "-k")) @@ -1000,9 +1006,9 @@ int main(int argc, char **argv) switch(layoutId) { case LAYOUT_APP: if (staticElf) { - ret = handleAppStatic(posArg[0], out, layoutFlags, appId, appVer, verbose); + ret = handleAppStatic(posArg[0], out, layoutFlags, appId, appVer, chreApi, verbose); } else { - ret = handleApp(&buf, bufUsed, out, layoutFlags, appId, appVer, verbose); + ret = handleApp(&buf, bufUsed, out, layoutFlags, appId, appVer, chreApi, verbose); } break; case LAYOUT_KEY: |