Ben Fennema | 404a713 | 2017-07-12 11:07:11 -0700 | [diff] [blame] | 1 | /* |
Ben Fennema | 5b6af28 | 2017-12-13 15:33:19 -0800 | [diff] [blame] | 2 | * Copyright (C) 2017 The Android Open Source Project |
Ben Fennema | 404a713 | 2017-07-12 11:07:11 -0700 | [diff] [blame] | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <eventnums.h> |
| 18 | #include <seos.h> |
| 19 | #include <timer.h> |
| 20 | #include <toolchain.h> |
| 21 | #include <crt_priv.h> |
| 22 | #include <string.h> |
| 23 | |
| 24 | #include <chre.h> |
| 25 | #include <sensors.h> |
| 26 | #include <syscallDo.h> |
| 27 | #include <hostIntf.h> |
| 28 | |
| 29 | #define SENSOR_TYPE(x) ((x) & 0xFF) |
| 30 | |
| 31 | /* |
| 32 | * Common CHRE App support code |
| 33 | */ |
| 34 | |
| 35 | static bool chreappStart(uint32_t tid) |
| 36 | { |
| 37 | __crt_init(); |
| 38 | return nanoappStart(); |
| 39 | } |
| 40 | |
| 41 | static void chreappEnd(void) |
| 42 | { |
| 43 | nanoappEnd(); |
| 44 | __crt_exit(); |
| 45 | } |
| 46 | |
| 47 | static void initDataHeader(struct chreSensorDataHeader *header, uint64_t timestamp, uint32_t sensorHandle) { |
| 48 | header->baseTimestamp = timestamp; |
| 49 | header->sensorHandle = sensorHandle; |
| 50 | header->readingCount = 1; |
| 51 | header->reserved[0] = header->reserved[1] = 0; |
| 52 | } |
| 53 | |
| 54 | static void processTripleAxisData(const struct TripleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType) |
| 55 | { |
| 56 | int i; |
| 57 | struct chreSensorThreeAxisData three; |
| 58 | |
| 59 | initDataHeader(&three.header, src->referenceTime, sensorHandle); |
| 60 | three.readings[0].timestampDelta = 0; |
| 61 | |
| 62 | for (i=0; i<src->samples[0].firstSample.numSamples; i++) { |
| 63 | if (i > 0) |
| 64 | three.header.baseTimestamp += src->samples[i].deltaTime; |
| 65 | three.readings[0].x = src->samples[i].x; |
| 66 | three.readings[0].y = src->samples[i].y; |
| 67 | three.readings[0].z = src->samples[i].z; |
| 68 | |
| 69 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &three); |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | static void processSingleAxisData(const struct SingleAxisDataEvent *src, uint32_t sensorHandle, uint8_t sensorType) |
| 74 | { |
| 75 | int i; |
| 76 | |
| 77 | switch (sensorType) { |
| 78 | case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT: |
| 79 | case CHRE_SENSOR_TYPE_STATIONARY_DETECT: { |
| 80 | struct chreSensorOccurrenceData occ; |
| 81 | |
| 82 | initDataHeader(&occ.header, src->referenceTime, sensorHandle); |
| 83 | occ.readings[0].timestampDelta = 0; |
| 84 | |
| 85 | for (i=0; i<src->samples[0].firstSample.numSamples; i++) { |
| 86 | if (i > 0) |
| 87 | occ.header.baseTimestamp += src->samples[i].deltaTime; |
| 88 | |
| 89 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ); |
| 90 | } |
| 91 | break; |
| 92 | } |
| 93 | case CHRE_SENSOR_TYPE_LIGHT: |
| 94 | case CHRE_SENSOR_TYPE_PRESSURE: { |
| 95 | struct chreSensorFloatData flt; |
| 96 | |
| 97 | initDataHeader(&flt.header, src->referenceTime, sensorHandle); |
| 98 | flt.readings[0].timestampDelta = 0; |
| 99 | |
| 100 | for (i=0; i<src->samples[0].firstSample.numSamples; i++) { |
| 101 | if (i > 0) |
| 102 | flt.header.baseTimestamp += src->samples[i].deltaTime; |
| 103 | flt.readings[0].value = src->samples[i].fdata; |
| 104 | |
| 105 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt); |
| 106 | } |
| 107 | break; |
| 108 | } |
| 109 | case CHRE_SENSOR_TYPE_PROXIMITY: { |
| 110 | struct chreSensorByteData byte; |
| 111 | |
| 112 | initDataHeader(&byte.header, src->referenceTime, sensorHandle); |
| 113 | byte.readings[0].timestampDelta = 0; |
| 114 | |
| 115 | for (i=0; i<src->samples[0].firstSample.numSamples; i++) { |
| 116 | if (i > 0) |
| 117 | byte.header.baseTimestamp += src->samples[i].deltaTime; |
| 118 | byte.readings[0].isNear = src->samples[i].fdata == 0.0f; |
| 119 | byte.readings[0].invalid = false; |
| 120 | byte.readings[0].padding0 = 0; |
| 121 | |
| 122 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte); |
| 123 | } |
| 124 | break; |
| 125 | } |
| 126 | } |
| 127 | } |
| 128 | |
| 129 | static void processEmbeddedData(const void *src, uint32_t sensorHandle, uint8_t sensorType) |
| 130 | { |
| 131 | union EmbeddedDataPoint data = (union EmbeddedDataPoint)((void *)src); |
| 132 | |
| 133 | switch (sensorType) { |
| 134 | case CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT: |
| 135 | case CHRE_SENSOR_TYPE_STATIONARY_DETECT: { |
| 136 | struct chreSensorOccurrenceData occ; |
| 137 | |
| 138 | initDataHeader(&occ.header, eOsSensorGetTime(), sensorHandle); |
| 139 | occ.readings[0].timestampDelta = 0; |
| 140 | |
| 141 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &occ); |
| 142 | break; |
| 143 | } |
| 144 | case CHRE_SENSOR_TYPE_LIGHT: |
| 145 | case CHRE_SENSOR_TYPE_PRESSURE: { |
| 146 | struct chreSensorFloatData flt; |
| 147 | |
| 148 | initDataHeader(&flt.header, eOsSensorGetTime(), sensorHandle); |
| 149 | flt.readings[0].timestampDelta = 0; |
| 150 | flt.readings[0].value = data.fdata; |
| 151 | |
| 152 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &flt); |
| 153 | break; |
| 154 | } |
| 155 | case CHRE_SENSOR_TYPE_PROXIMITY: { |
| 156 | struct chreSensorByteData byte; |
| 157 | |
| 158 | initDataHeader(&byte.header, eOsSensorGetTime(), sensorHandle); |
| 159 | byte.readings[0].timestampDelta = 0; |
| 160 | byte.readings[0].isNear = data.fdata == 0.0f; |
| 161 | byte.readings[0].invalid = false; |
| 162 | byte.readings[0].padding0 = 0; |
| 163 | |
| 164 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_DATA_EVENT_BASE | sensorType, &byte); |
| 165 | break; |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | static void chreappProcessSensorData(uint16_t evt, const void *eventData) |
| 171 | { |
| 172 | const struct SensorInfo *si; |
| 173 | uint32_t sensorHandle; |
| 174 | |
| 175 | if (eventData == SENSOR_DATA_EVENT_FLUSH) |
| 176 | return; |
| 177 | |
| 178 | si = eOsSensorFind(SENSOR_TYPE(evt), 0, &sensorHandle); |
| 179 | if (si && eOsSensorGetReqRate(sensorHandle)) { |
| 180 | switch (si->numAxis) { |
| 181 | case NUM_AXIS_EMBEDDED: |
| 182 | processEmbeddedData(eventData, sensorHandle, SENSOR_TYPE(evt)); |
| 183 | break; |
| 184 | case NUM_AXIS_ONE: |
| 185 | processSingleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt)); |
| 186 | break; |
| 187 | case NUM_AXIS_THREE: |
| 188 | processTripleAxisData(eventData, sensorHandle, SENSOR_TYPE(evt)); |
| 189 | break; |
| 190 | } |
| 191 | |
| 192 | if (SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_INSTANT_MOTION_DETECT |
| 193 | || SENSOR_TYPE(evt) == CHRE_SENSOR_TYPE_STATIONARY_DETECT) { |
| 194 | // one-shot, disable after receiving sample |
| 195 | chreSensorConfigure(sensorHandle, CHRE_SENSOR_CONFIGURE_MODE_DONE, CHRE_SENSOR_INTERVAL_DEFAULT, CHRE_SENSOR_LATENCY_DEFAULT); |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | static void chreappProcessConfigEvt(uint16_t evt, const void *eventData) |
| 201 | { |
| 202 | const struct SensorRateChangeEvent *msg = eventData; |
| 203 | struct chreSensorSamplingStatusEvent change; |
| 204 | |
| 205 | change.sensorHandle = msg->sensorHandle; |
| 206 | if (!msg->newRate) { |
| 207 | change.status.enabled = 0; |
| 208 | change.status.interval = 0; |
| 209 | change.status.latency = 0; |
| 210 | } else { |
| 211 | change.status.enabled = true; |
| 212 | if (msg->newRate == SENSOR_RATE_ONDEMAND |
| 213 | || msg->newRate == SENSOR_RATE_ONCHANGE |
| 214 | || msg->newRate == SENSOR_RATE_ONESHOT) |
| 215 | change.status.interval = CHRE_SENSOR_INTERVAL_DEFAULT; |
| 216 | else |
| 217 | change.status.interval = (UINT32_C(1024000000) / msg->newRate) * UINT64_C(1000); |
| 218 | |
| 219 | if (msg->newLatency == SENSOR_LATENCY_NODATA) |
| 220 | change.status.latency = CHRE_SENSOR_INTERVAL_DEFAULT; |
| 221 | else |
| 222 | change.status.latency = msg->newLatency; |
| 223 | } |
| 224 | |
| 225 | nanoappHandleEvent(CHRE_INSTANCE_ID, CHRE_EVENT_SENSOR_SAMPLING_CHANGE, &change); |
| 226 | } |
| 227 | |
| 228 | static void chreappHandle(uint32_t eventTypeAndTid, const void *eventData) |
| 229 | { |
| 230 | uint16_t evt = eventTypeAndTid; |
| 231 | uint16_t srcTid = eventTypeAndTid >> 16; |
| 232 | const void *data = eventData; |
| 233 | |
| 234 | union EventLocalData { |
| 235 | struct chreMessageFromHostData msg; |
| 236 | } u; |
| 237 | |
| 238 | switch(evt) { |
| 239 | case EVT_APP_TIMER: |
| 240 | evt = CHRE_EVENT_TIMER; |
| 241 | data = ((struct TimerEvent *)eventData)->data; |
| 242 | break; |
| 243 | case EVT_APP_FROM_HOST: |
| 244 | srcTid = CHRE_INSTANCE_ID; |
| 245 | evt = CHRE_EVENT_MESSAGE_FROM_HOST; |
| 246 | data = &u.msg; |
| 247 | u.msg.message = (uint8_t*)eventData + 1; |
| 248 | u.msg.reservedMessageType = 0; |
| 249 | u.msg.messageSize = *(uint8_t*)eventData; |
| 250 | break; |
| 251 | case EVT_APP_FROM_HOST_CHRE: |
| 252 | { |
Ben Fennema | 150d0f7 | 2017-08-30 23:35:39 -0700 | [diff] [blame] | 253 | const struct NanohubMsgChreHdrV10 *hdr = eventData; |
Ben Fennema | 404a713 | 2017-07-12 11:07:11 -0700 | [diff] [blame] | 254 | srcTid = CHRE_INSTANCE_ID; |
| 255 | evt = CHRE_EVENT_MESSAGE_FROM_HOST; |
| 256 | data = &u.msg; |
| 257 | u.msg.message = hdr + 1; |
| 258 | u.msg.reservedMessageType = hdr->appEvent; |
| 259 | u.msg.messageSize = hdr->size; |
| 260 | break; |
| 261 | } |
| 262 | case EVT_APP_SENSOR_SELF_TEST: |
| 263 | case EVT_APP_SENSOR_MARSHALL: |
| 264 | case EVT_APP_SENSOR_SEND_ONE_DIR_EVT: |
| 265 | case EVT_APP_SENSOR_CFG_DATA: |
| 266 | case EVT_APP_SENSOR_CALIBRATE: |
| 267 | case EVT_APP_SENSOR_TRIGGER: |
| 268 | case EVT_APP_SENSOR_FLUSH: |
| 269 | case EVT_APP_SENSOR_SET_RATE: |
| 270 | case EVT_APP_SENSOR_FW_UPLD: |
| 271 | case EVT_APP_SENSOR_POWER: |
| 272 | // sensor events; pass through |
| 273 | break; |
| 274 | default: |
| 275 | // ignore any other system events; OS may send them to any app |
| 276 | if (evt < EVT_NO_FIRST_USER_EVENT) |
| 277 | return; |
| 278 | else if (evt > EVT_NO_FIRST_SENSOR_EVENT && evt < EVT_NO_SENSOR_CONFIG_EVENT) { |
| 279 | return chreappProcessSensorData(evt, data); |
| 280 | } else if (evt > EVT_NO_SENSOR_CONFIG_EVENT && evt < EVT_APP_START) { |
| 281 | return chreappProcessConfigEvt(evt, data); |
| 282 | } |
| 283 | } |
| 284 | nanoappHandleEvent(srcTid, evt, data); |
| 285 | } |
| 286 | |
| 287 | // Collect entry points |
| 288 | const struct AppFuncs SET_EXTERNAL_APP_ATTRIBUTES(used, section (".app_init"),visibility("default")) _mAppFuncs = { |
| 289 | .init = chreappStart, |
| 290 | .end = chreappEnd, |
| 291 | .handle = chreappHandle, |
| 292 | }; |
| 293 | |
| 294 | // declare version for compatibility with current runtime |
| 295 | const uint32_t SET_EXTERNAL_APP_VERSION(used, section (".app_version"), visibility("default")) _mAppVer = 0; |