Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <inttypes.h>
     18 #include <stdint.h>
     19 #include <sys/endian.h>
     20 #include <string.h>
     21 #include <alloca.h>
     22 
     23 #include <variant/variant.h>
     24 #include <eventnums.h>
     25 
     26 #include <plat/pwr.h>
     27 
     28 #include <nanohub/crc.h>
     29 
     30 #include <platform.h>
     31 #include <cpu.h>
     32 #include <halIntf.h>
     33 #include <hostIntf.h>
     34 #include <hostIntf_priv.h>
     35 #include <nanohubCommand.h>
     36 #include <nanohubPacket.h>
     37 #include <seos.h>
     38 #include <seos_priv.h>
     39 #include <util.h>
     40 #include <atomicBitset.h>
     41 #include <atomic.h>
     42 #include <gpio.h>
     43 #include <apInt.h>
     44 #include <sensors.h>
     45 #include <timer.h>
     46 #include <heap.h>
     47 #include <simpleQ.h>
     48 
     49 #define HOSTINTF_MAX_ERR_MSG    8
     50 #define MAX_NUM_BLOCKS          280         /* times 256 = 71680 bytes */
     51 #define MIN_NUM_BLOCKS          10          /* times 256 = 2560 bytes */
     52 #define SENSOR_INIT_DELAY       500000000   /* ns */
     53 #define SENSOR_INIT_ERROR_MAX   4
     54 #define CHECK_LATENCY_TIME      500000000   /* ns */
     55 #define EVT_LATENCY_TIMER       EVT_NO_FIRST_USER_EVENT
     56 
     57 static const uint32_t delta_time_multiplier_order = 9;
     58 static const uint32_t delta_time_coarse_mask = ~1;
     59 static const uint32_t delta_time_fine_mask = 1;
     60 static const uint32_t delta_time_rounding = 0x200;      /* 1ul << delta_time_multiplier_order */
     61 static const uint64_t delta_time_max = 0x1FFFFFFFE00;   /* UINT32_MAX << delta_time_multiplier_order */
     62 
     63 enum ConfigCmds
     64 {
     65     CONFIG_CMD_DISABLE      = 0,
     66     CONFIG_CMD_ENABLE       = 1,
     67     CONFIG_CMD_FLUSH        = 2,
     68     CONFIG_CMD_CFG_DATA     = 3,
     69     CONFIG_CMD_CALIBRATE    = 4,
     70     CONFIG_CMD_SELF_TEST    = 5,
     71 };
     72 
     73 struct ConfigCmd
     74 {
     75     uint64_t latency;
     76     uint32_t rate;
     77     uint8_t sensType;
     78     uint8_t cmd;
     79     uint16_t flags;
     80 } __attribute__((packed));
     81 
     82 struct ActiveSensor
     83 {
     84     uint64_t latency;
     85     uint64_t firstTime;
     86     uint64_t lastTime;
     87     struct HostIntfDataBuffer buffer;
     88     uint32_t rate;
     89     uint32_t sensorHandle;
     90     float rawScale;
     91     uint16_t minSamples;
     92     uint16_t curSamples;
     93     uint8_t numAxis;
     94     uint8_t interrupt;
     95     uint8_t numSamples;
     96     uint8_t packetSamples;
     97     // The sensorType used to report bias samples; normally the same as
     98     // buffer.sensorType, but in the case of raw, this gets set to the base
     99     // sensorType matching struct SensorInfo (because the sensor can have a
    100     // different rawType). Note that this is different than biasType in struct
    101     // SensorInfo.
    102     uint8_t biasReportType;
    103     uint8_t oneshot : 1;
    104     uint8_t discard : 1;
    105     uint8_t raw : 1;
    106     uint8_t reserved : 5;
    107 } __attribute__((packed));
    108 
    109 static uint8_t mSensorList[SENS_TYPE_LAST_USER];
    110 static struct SimpleQueue *mOutputQ;
    111 static struct ActiveSensor *mActiveSensorTable;
    112 static uint8_t mNumSensors;
    113 static uint8_t mLastSensor;
    114 
    115 static const struct HostIntfComm *mComm;
    116 static bool mBusy;
    117 static uint64_t mRxTimestamp;
    118 static uint8_t mRxBuf[NANOHUB_PACKET_SIZE_MAX];
    119 static size_t mRxSize;
    120 static struct
    121 {
    122     const struct NanohubCommand *cmd;
    123     uint32_t seq;
    124     bool seqMatch;
    125 } mTxRetrans;
    126 static struct
    127 {
    128     uint8_t pad; // packet header is 10 bytes. + 2 to word align
    129     uint8_t prePreamble;
    130     uint8_t buf[NANOHUB_PACKET_SIZE_MAX];
    131     uint8_t postPreamble;
    132 } mTxBuf;
    133 static struct
    134 {
    135     uint8_t pad; // packet header is 10 bytes. + 2 to word align
    136     uint8_t prePreamble;
    137     uint8_t buf[NANOHUB_PACKET_SIZE_MIN];
    138     uint8_t postPreamble;
    139 } mTxNakBuf;
    140 static size_t mTxSize;
    141 static uint8_t *mTxBufPtr;
    142 static const struct NanohubCommand *mRxCmd;
    143 ATOMIC_BITSET_DECL(mInterrupt, HOSTINTF_MAX_INTERRUPTS, static);
    144 ATOMIC_BITSET_DECL(mInterruptMask, HOSTINTF_MAX_INTERRUPTS, static);
    145 static uint32_t mInterruptCntWkup, mInterruptCntNonWkup;
    146 static uint32_t mWakeupBlocks, mNonWakeupBlocks, mTotalBlocks;
    147 static uint32_t mHostIntfTid;
    148 static uint32_t mLatencyTimer;
    149 static uint8_t mLatencyCnt;
    150 
    151 static uint8_t mRxIdle;
    152 static uint8_t mWakeActive;
    153 static uint8_t mActiveWrite;
    154 static uint8_t mRestartRx;
    155 static uint8_t mIntErrMsgIdx;
    156 static volatile uint32_t mIntErrMsgCnt;
    157 
    158 enum hostIntfIntErrReason
    159 {
    160     HOSTINTF_ERR_PKG_INCOMPELETE = 0,
    161     HOSTINTF_ERR_PGK_SIZE,
    162     HOSTINTF_ERR_PKG_PAYLOAD_SIZE,
    163     HOSTINTF_ERR_PKG_CRC,
    164     HOSTINTF_ERR_RECEIVE,
    165     HOSTINTF_ERR_SEND,
    166     HOSTINTF_ERR_ACK,
    167     HOSTINTF_ERR_NAK,
    168     HOSTINTF_ERR_UNKNOWN
    169 };
    170 
    171 struct hostIntfIntErrMsg
    172 {
    173     enum LogLevel level;
    174     enum hostIntfIntErrReason reason;
    175     const char *func;
    176 };
    177 static struct hostIntfIntErrMsg mIntErrMsg[HOSTINTF_MAX_ERR_MSG];
    178 
    179 static void hostIntfTxPacket(uint32_t reason, uint8_t len, uint32_t seq,
    180         HostIntfCommCallbackF callback);
    181 
    182 static void hostIntfRxDone(size_t rx, int err);
    183 static void hostIntfGenerateAck(void *cookie);
    184 
    185 static void hostIntfTxAckDone(size_t tx, int err);
    186 static void hostIntfGenerateResponse(void *cookie);
    187 
    188 static void hostIntfTxPayloadDone(size_t tx, int err);
    189 
    190 static inline void *hostIntfGetPayload(uint8_t *buf)
    191 {
    192     struct NanohubPacket *packet = (struct NanohubPacket *)buf;
    193     return packet->data;
    194 }
    195 
    196 static inline uint8_t hostIntfGetPayloadLen(uint8_t *buf)
    197 {
    198     struct NanohubPacket *packet = (struct NanohubPacket *)buf;
    199     return packet->len;
    200 }
    201 
    202 static inline struct NanohubPacketFooter *hostIntfGetFooter(uint8_t *buf)
    203 {
    204     struct NanohubPacket *packet = (struct NanohubPacket *)buf;
    205     return (struct NanohubPacketFooter *)(buf + sizeof(*packet) + packet->len);
    206 }
    207 
    208 static inline __le32 hostIntfComputeCrc(uint8_t *buf)
    209 {
    210     struct NanohubPacket *packet = (struct NanohubPacket *)buf;
    211     uint32_t crc = crc32(packet, packet->len + sizeof(*packet), CRC_INIT);
    212     return htole32(crc);
    213 }
    214 
    215 static void hostIntfPrintErrMsg(void *cookie)
    216 {
    217     struct hostIntfIntErrMsg *msg = (struct hostIntfIntErrMsg *)cookie;
    218     osLog(msg->level, "%s failed with: %d\n", msg->func, msg->reason);
    219     atomicAdd32bits(&mIntErrMsgCnt, -1UL);
    220 }
    221 
    222 static void hostIntfDeferErrLog(enum LogLevel level, enum hostIntfIntErrReason reason, const char *func)
    223 {
    224     // If the message buffer is full, we drop the newer messages.
    225     if (atomicRead32bits(&mIntErrMsgCnt) == HOSTINTF_MAX_ERR_MSG)
    226         return;
    227 
    228     mIntErrMsg[mIntErrMsgIdx].level = level;
    229     mIntErrMsg[mIntErrMsgIdx].reason = reason;
    230     mIntErrMsg[mIntErrMsgIdx].func = func;
    231     if (osDefer(hostIntfPrintErrMsg, &mIntErrMsg[mIntErrMsgIdx], false)) {
    232         atomicAdd32bits(&mIntErrMsgCnt, 1UL);
    233         mIntErrMsgIdx = (mIntErrMsgIdx + 1) % HOSTINTF_MAX_ERR_MSG;
    234     }
    235 }
    236 
    237 static inline const struct NanohubCommand *hostIntfFindHandler(uint8_t *buf, size_t size, uint32_t *seq)
    238 {
    239     struct NanohubPacket *packet = (struct NanohubPacket *)buf;
    240     struct NanohubPacketFooter *footer;
    241     __le32 packetCrc;
    242     uint32_t packetReason;
    243     const struct NanohubCommand *cmd;
    244 
    245     if (size < NANOHUB_PACKET_SIZE(0)) {
    246         hostIntfDeferErrLog(LOG_WARN, HOSTINTF_ERR_PKG_INCOMPELETE, __func__);
    247         return NULL;
    248     }
    249 
    250     if (size != NANOHUB_PACKET_SIZE(packet->len)) {
    251         hostIntfDeferErrLog(LOG_WARN, HOSTINTF_ERR_PGK_SIZE, __func__);
    252         return NULL;
    253     }
    254 
    255     footer = hostIntfGetFooter(buf);
    256     packetCrc = hostIntfComputeCrc(buf);
    257     if (footer->crc != packetCrc) {
    258         hostIntfDeferErrLog(LOG_WARN, HOSTINTF_ERR_PKG_CRC, __func__);
    259         return NULL;
    260     }
    261 
    262     if (mTxRetrans.seq == packet->seq) {
    263         mTxRetrans.seqMatch = true;
    264         return mTxRetrans.cmd;
    265     } else {
    266         mTxRetrans.seqMatch = false;
    267     }
    268 
    269     *seq = packet->seq;
    270 
    271     if (mBusy)
    272         return NULL;
    273 
    274     packetReason = le32toh(packet->reason);
    275 
    276     if ((cmd = nanohubFindCommand(packetReason)) != NULL) {
    277         if (packet->len < cmd->minDataLen || packet->len > cmd->maxDataLen) {
    278             hostIntfDeferErrLog(LOG_WARN, HOSTINTF_ERR_PKG_PAYLOAD_SIZE, __func__);
    279             return NULL;
    280         }
    281 
    282         return cmd;
    283     }
    284 
    285     hostIntfDeferErrLog(LOG_WARN, HOSTINTF_ERR_UNKNOWN, __func__);
    286     return NULL;
    287 }
    288 
    289 static void hostIntfTxBuf(int size, uint8_t *buf, HostIntfCommCallbackF callback)
    290 {
    291     mTxSize = size;
    292     mTxBufPtr = buf;
    293     mComm->txPacket(mTxBufPtr, mTxSize, callback);
    294 }
    295 
    296 static void hostIntfTxPacket(__le32 reason, uint8_t len, uint32_t seq,
    297         HostIntfCommCallbackF callback)
    298 {
    299     struct NanohubPacket *txPacket = (struct NanohubPacket *)(mTxBuf.buf);
    300     txPacket->reason = reason;
    301     txPacket->seq = seq;
    302     txPacket->sync = NANOHUB_SYNC_BYTE;
    303     txPacket->len = len;
    304 
    305     struct NanohubPacketFooter *txFooter = hostIntfGetFooter(mTxBuf.buf);
    306     txFooter->crc = hostIntfComputeCrc(mTxBuf.buf);
    307 
    308     // send starting with the prePremable byte
    309     hostIntfTxBuf(1+NANOHUB_PACKET_SIZE(len), &mTxBuf.prePreamble, callback);
    310 }
    311 
    312 static void hostIntfTxNakPacket(__le32 reason, uint32_t seq,
    313         HostIntfCommCallbackF callback)
    314 {
    315     struct NanohubPacket *txPacket = (struct NanohubPacket *)(mTxNakBuf.buf);
    316     txPacket->reason = reason;
    317     txPacket->seq = seq;
    318     txPacket->sync = NANOHUB_SYNC_BYTE;
    319     txPacket->len = 0;
    320 
    321     struct NanohubPacketFooter *txFooter = hostIntfGetFooter(mTxNakBuf.buf);
    322     txFooter->crc = hostIntfComputeCrc(mTxNakBuf.buf);
    323 
    324     // send starting with the prePremable byte
    325     hostIntfTxBuf(1+NANOHUB_PACKET_SIZE_MIN, &mTxNakBuf.prePreamble, callback);
    326 }
    327 
    328 static inline bool hostIntfTxPacketDone(int err, size_t tx,
    329         HostIntfCommCallbackF callback)
    330 {
    331     if (!err && tx < mTxSize) {
    332         mTxSize -= tx;
    333         mTxBufPtr += tx;
    334 
    335         mComm->txPacket(mTxBufPtr, mTxSize, callback);
    336         return false;
    337     }
    338 
    339     return true;
    340 }
    341 
    342 static bool hostIntfRequest(uint32_t tid)
    343 {
    344     mHostIntfTid = tid;
    345     atomicBitsetInit(mInterrupt, HOSTINTF_MAX_INTERRUPTS);
    346     atomicBitsetInit(mInterruptMask, HOSTINTF_MAX_INTERRUPTS);
    347 #ifdef AP_INT_NONWAKEUP
    348     hostIntfSetInterruptMask(NANOHUB_INT_NONWAKEUP);
    349 #endif
    350     mTxBuf.prePreamble = NANOHUB_PREAMBLE_BYTE;
    351     mTxBuf.postPreamble = NANOHUB_PREAMBLE_BYTE;
    352     mTxNakBuf.prePreamble = NANOHUB_PREAMBLE_BYTE;
    353     mTxNakBuf.postPreamble = NANOHUB_PREAMBLE_BYTE;
    354 
    355     mComm = platHostIntfInit();
    356     if (mComm) {
    357         int err = mComm->request();
    358         if (!err) {
    359             nanohubInitCommand();
    360             mComm->rxPacket(mRxBuf, sizeof(mRxBuf), hostIntfRxDone);
    361             osEventSubscribe(mHostIntfTid, EVT_APP_START);
    362             return true;
    363         }
    364     }
    365 
    366     return false;
    367 }
    368 
    369 void hostIntfRxPacket(bool wakeupActive)
    370 {
    371     if (mWakeActive) {
    372         if (atomicXchgByte(&mRxIdle, false)) {
    373             if (!wakeupActive)
    374                 hostIntfClearInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    375             mComm->rxPacket(mRxBuf, sizeof(mRxBuf), hostIntfRxDone);
    376             if (wakeupActive)
    377                 hostIntfSetInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    378         } else if (atomicReadByte(&mActiveWrite)) {
    379             atomicWriteByte(&mRestartRx, true);
    380         } else {
    381             if (!wakeupActive)
    382                 hostIntfClearInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    383             else
    384                 hostIntfSetInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    385         }
    386     } else if (wakeupActive && !atomicReadByte(&mActiveWrite))
    387         hostIntfSetInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    388 
    389     mWakeActive = wakeupActive;
    390 }
    391 
    392 static void hostIntfRxDone(size_t rx, int err)
    393 {
    394     mRxTimestamp = sensorGetTime();
    395     mRxSize = rx;
    396 
    397     if (err != 0) {
    398         hostIntfDeferErrLog(LOG_ERROR, HOSTINTF_ERR_RECEIVE, __func__);
    399         return;
    400     }
    401 
    402     hostIntfGenerateAck(NULL);
    403 }
    404 
    405 static void hostIntfTxSendAck(uint32_t resp)
    406 {
    407     void *txPayload = hostIntfGetPayload(mTxBuf.buf);
    408 
    409     if (resp == NANOHUB_FAST_UNHANDLED_ACK) {
    410         hostIntfCopyInterrupts(txPayload, HOSTINTF_MAX_INTERRUPTS);
    411         hostIntfTxPacket(NANOHUB_REASON_ACK, 32, mTxRetrans.seq, hostIntfTxAckDone);
    412     } else if (resp == NANOHUB_FAST_DONT_ACK) {
    413         // do nothing. something else will do the ack
    414     } else {
    415         hostIntfTxPacket(mRxCmd->reason, resp, mTxRetrans.seq, hostIntfTxPayloadDone);
    416     }
    417 }
    418 
    419 void hostIntfTxAck(void *buffer, uint8_t len)
    420 {
    421     void *txPayload = hostIntfGetPayload(mTxBuf.buf);
    422 
    423     memcpy(txPayload, buffer, len);
    424 
    425     hostIntfTxSendAck(len);
    426 }
    427 
    428 static void hostIntfGenerateAck(void *cookie)
    429 {
    430     uint32_t seq = 0;
    431     void *txPayload = hostIntfGetPayload(mTxBuf.buf);
    432     void *rxPayload = hostIntfGetPayload(mRxBuf);
    433     uint8_t rx_len = hostIntfGetPayloadLen(mRxBuf);
    434     uint32_t resp = NANOHUB_FAST_UNHANDLED_ACK;
    435 
    436     atomicWriteByte(&mActiveWrite, true);
    437     hostIntfSetInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    438     mRxCmd = hostIntfFindHandler(mRxBuf, mRxSize, &seq);
    439 
    440     if (mRxCmd) {
    441         if (mTxRetrans.seqMatch) {
    442             hostIntfTxBuf(mTxSize, &mTxBuf.prePreamble, hostIntfTxPayloadDone);
    443         } else {
    444             mTxRetrans.seq = seq;
    445             mTxRetrans.cmd = mRxCmd;
    446             if (mRxCmd->fastHandler)
    447                 resp = mRxCmd->fastHandler(rxPayload, rx_len, txPayload, mRxTimestamp);
    448 
    449             hostIntfTxSendAck(resp);
    450         }
    451     } else {
    452         if (mBusy)
    453             hostIntfTxNakPacket(NANOHUB_REASON_NAK_BUSY, seq, hostIntfTxAckDone);
    454         else
    455             hostIntfTxNakPacket(NANOHUB_REASON_NAK, seq, hostIntfTxAckDone);
    456     }
    457 }
    458 
    459 
    460 static void hostIntfTxComplete(bool clearInt, bool restartRx)
    461 {
    462     if (restartRx || clearInt || !mWakeActive)
    463         hostIntfClearInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    464     atomicWriteByte(&mActiveWrite, false);
    465     atomicWriteByte(&mRestartRx, false);
    466     if (restartRx) {
    467         mComm->rxPacket(mRxBuf, sizeof(mRxBuf), hostIntfRxDone);
    468         hostIntfSetInterrupt(NANOHUB_INT_WAKE_COMPLETE);
    469     } else {
    470         atomicWriteByte(&mRxIdle, true);
    471     }
    472 }
    473 
    474 static void hostIntfTxAckDone(size_t tx, int err)
    475 {
    476     hostIntfTxPacketDone(err, tx, hostIntfTxAckDone);
    477 
    478     if (err) {
    479         hostIntfDeferErrLog(LOG_ERROR, HOSTINTF_ERR_ACK, __func__);
    480         hostIntfTxComplete(false, false);
    481         return;
    482     }
    483 
    484     if (!mRxCmd) {
    485         if (!mBusy)
    486             hostIntfDeferErrLog(LOG_DEBUG, HOSTINTF_ERR_NAK, __func__);
    487         if (atomicReadByte(&mRestartRx))
    488             hostIntfTxComplete(false, true);
    489         else
    490             hostIntfTxComplete(false, false);
    491         return;
    492     } else if (atomicReadByte(&mRestartRx)) {
    493         mTxRetrans.seq = 0;
    494         mTxRetrans.cmd = NULL;
    495         hostIntfTxComplete(false, true);
    496     } else {
    497         if (!osDefer(hostIntfGenerateResponse, NULL, true)) {
    498             mTxRetrans.seq = 0;
    499             mTxRetrans.cmd = NULL;
    500             hostIntfTxComplete(false, false);
    501         }
    502     }
    503 }
    504 
    505 static void hostIntfGenerateResponse(void *cookie)
    506 {
    507     void *rxPayload = hostIntfGetPayload(mRxBuf);
    508     uint8_t rx_len = hostIntfGetPayloadLen(mRxBuf);
    509     void *txPayload = hostIntfGetPayload(mTxBuf.buf);
    510     uint8_t respLen = mRxCmd->handler(rxPayload, rx_len, txPayload, mRxTimestamp);
    511 
    512     hostIntfTxPacket(mRxCmd->reason, respLen, mTxRetrans.seq, hostIntfTxPayloadDone);
    513 }
    514 
    515 static void hostIntfTxPayloadDone(size_t tx, int err)
    516 {
    517     bool done = hostIntfTxPacketDone(err, tx, hostIntfTxPayloadDone);
    518 
    519     if (err)
    520         hostIntfDeferErrLog(LOG_ERROR, HOSTINTF_ERR_SEND, __func__);
    521 
    522     if (done) {
    523         if (atomicReadByte(&mRestartRx))
    524             hostIntfTxComplete(true, true);
    525         else
    526             hostIntfTxComplete(true, false);
    527     }
    528 }
    529 
    530 static void hostIntfRelease()
    531 {
    532     mComm->release();
    533 }
    534 
    535 static void resetBuffer(struct ActiveSensor *sensor)
    536 {
    537     sensor->discard = true;
    538     sensor->buffer.length = 0;
    539     memset(&sensor->buffer.firstSample, 0x00, sizeof(struct SensorFirstSample));
    540 }
    541 
    542 void hostIntfSetBusy(bool busy)
    543 {
    544     mBusy = busy;
    545 }
    546 
    547 static inline struct ActiveSensor *getActiveSensorByType(uint32_t sensorType)
    548 {
    549     struct ActiveSensor *sensor = NULL;
    550 
    551     if (sensorType > SENS_TYPE_INVALID && sensorType <= SENS_TYPE_LAST_USER &&
    552         mSensorList[sensorType - 1] < MAX_REGISTERED_SENSORS)
    553         sensor = mActiveSensorTable + mSensorList[sensorType - 1];
    554 
    555     return sensor;
    556 }
    557 
    558 bool hostIntfPacketDequeue(void *data, uint32_t *wakeup, uint32_t *nonwakeup)
    559 {
    560     struct HostIntfDataBuffer *buffer = data;
    561     bool ret;
    562     struct ActiveSensor *sensor;
    563     uint32_t i;
    564 
    565     ret = simpleQueueDequeue(mOutputQ, buffer);
    566     while (ret) {
    567         sensor = getActiveSensorByType(buffer->sensType);
    568         if (sensor) {
    569             // do not sent sensor data if sensor is not requested; only maintain stats
    570             if (sensor->sensorHandle == 0 && !buffer->firstSample.biasPresent && !buffer->firstSample.numFlushes) {
    571                 if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    572                     mWakeupBlocks--;
    573                 else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    574                     mNonWakeupBlocks--;
    575                 sensor->curSamples -= buffer->firstSample.numSamples;
    576                 ret = simpleQueueDequeue(mOutputQ, buffer);
    577             } else {
    578                 break;
    579             }
    580         } else {
    581             break;
    582         }
    583     }
    584 
    585     if (!ret) {
    586         // nothing in queue. look for partial buffers to flush
    587         for (i = 0; i < mNumSensors; i++, mLastSensor = (mLastSensor + 1) % mNumSensors) {
    588             sensor = mActiveSensorTable + mLastSensor;
    589 
    590             if (sensor->curSamples != sensor->buffer.firstSample.numSamples) {
    591                 osLog(LOG_ERROR, "hostIntfPacketDequeue: sensor(%d)->curSamples=%d != buffer->numSamples=%d\n", sensor->buffer.sensType, sensor->curSamples, sensor->buffer.firstSample.numSamples);
    592                 sensor->curSamples = sensor->buffer.firstSample.numSamples;
    593             }
    594 
    595             if (sensor->buffer.length > 0) {
    596                 memcpy(buffer, &sensor->buffer, sizeof(struct HostIntfDataBuffer));
    597                 resetBuffer(sensor);
    598                 ret = true;
    599                 mLastSensor = (mLastSensor + 1) % mNumSensors;
    600                 break;
    601             }
    602         }
    603     }
    604 
    605     if (ret) {
    606         sensor = getActiveSensorByType(buffer->sensType);
    607         if (sensor) {
    608             if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    609                 mWakeupBlocks--;
    610             else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    611                 mNonWakeupBlocks--;
    612             sensor->curSamples -= buffer->firstSample.numSamples;
    613             sensor->firstTime = 0ull;
    614         } else {
    615             if (buffer->interrupt == NANOHUB_INT_WAKEUP)
    616                 mWakeupBlocks--;
    617             else if (buffer->interrupt == NANOHUB_INT_NONWAKEUP)
    618                 mNonWakeupBlocks--;
    619         }
    620     }
    621 
    622     *wakeup = mWakeupBlocks;
    623     *nonwakeup = mNonWakeupBlocks;
    624 
    625     return ret;
    626 }
    627 
    628 static void initCompleteCallback(uint32_t timerId, void *data)
    629 {
    630     osEnqueuePrivateEvt(EVT_APP_START, NULL, NULL, mHostIntfTid);
    631 }
    632 
    633 static bool queueDiscard(void *data, bool onDelete)
    634 {
    635     struct HostIntfDataBuffer *buffer = data;
    636     struct ActiveSensor *sensor = getActiveSensorByType(buffer->sensType);
    637 
    638     if (sensor) {
    639         if (sensor->curSamples - buffer->firstSample.numSamples >= sensor->minSamples || onDelete) {
    640             if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    641                 mWakeupBlocks--;
    642             else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    643                 mNonWakeupBlocks--;
    644             sensor->curSamples -= buffer->firstSample.numSamples;
    645 
    646             return true;
    647         } else {
    648             return false;
    649         }
    650     } else {
    651         if (buffer->interrupt == NANOHUB_INT_WAKEUP)
    652             mWakeupBlocks--;
    653         else if (buffer->interrupt == NANOHUB_INT_NONWAKEUP)
    654             mNonWakeupBlocks--;
    655         return true;
    656     }
    657 }
    658 
    659 static void latencyTimerCallback(uint32_t timerId, void* data)
    660 {
    661     osEnqueuePrivateEvt(EVT_LATENCY_TIMER, data, NULL, mHostIntfTid);
    662 }
    663 
    664 static bool initSensors()
    665 {
    666     uint32_t i, j, blocks, maxBlocks, numAxis, packetSamples;
    667     bool present, error;
    668     const struct SensorInfo *si;
    669     uint32_t handle;
    670     static uint8_t errorCnt = 0;
    671     uint32_t totalBlocks = 0;
    672     uint8_t numSensors = 0;
    673     ATOMIC_BITSET_DECL(sensorPresent, SENS_TYPE_LAST_USER - SENS_TYPE_INVALID,);
    674 
    675     atomicBitsetInit(sensorPresent, SENS_TYPE_LAST_USER - SENS_TYPE_INVALID);
    676 
    677     for (i = SENS_TYPE_INVALID + 1; i <= SENS_TYPE_LAST_USER; i++) {
    678         for (j = 0, present = 0, error = 0; (si = sensorFind(i, j, &handle)) != NULL; j++) {
    679             if (!sensorGetInitComplete(handle)) {
    680                 if (errorCnt >= SENSOR_INIT_ERROR_MAX) {
    681                     osLog(LOG_ERROR, "initSensors: %s not ready - skipping!\n", si->sensorName);
    682                     continue;
    683                 } else {
    684                     osLog(LOG_INFO, "initSensors: %s not ready!\n", si->sensorName);
    685                     timTimerSet(SENSOR_INIT_DELAY, 0, 50, initCompleteCallback, NULL, true);
    686                     errorCnt ++;
    687                     return false;
    688                 }
    689             } else if (!(si->flags1 & SENSOR_INFO_FLAGS1_LOCAL_ONLY)) {
    690                 if (!present) {
    691                     present = 1;
    692                     numAxis = si->numAxis;
    693                     switch (si->numAxis) {
    694                     case NUM_AXIS_EMBEDDED:
    695                     case NUM_AXIS_ONE:
    696                         packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct SingleAxisDataPoint);
    697                         break;
    698                     case NUM_AXIS_THREE:
    699                         if (si->flags1 & SENSOR_INFO_FLAGS1_RAW)
    700                             packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct RawTripleAxisDataPoint);
    701                         else
    702                             packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct TripleAxisDataPoint);
    703                         break;
    704                     default:
    705                         packetSamples = 1;
    706                         error = true;
    707                     }
    708                     if (si->minSamples > MAX_MIN_SAMPLES)
    709                         maxBlocks = (MAX_MIN_SAMPLES + packetSamples - 1) / packetSamples;
    710                     else
    711                         maxBlocks = (si->minSamples + packetSamples - 1) / packetSamples;
    712                 } else {
    713                     if (si->numAxis != numAxis) {
    714                         error = true;
    715                     } else {
    716                         if (si->minSamples > MAX_MIN_SAMPLES)
    717                             blocks = (MAX_MIN_SAMPLES + packetSamples - 1) / packetSamples;
    718                         else
    719                             blocks = (si->minSamples + packetSamples - 1) / packetSamples;
    720 
    721                         maxBlocks = maxBlocks > blocks ? maxBlocks : blocks;
    722                     }
    723                 }
    724             }
    725         }
    726 
    727         if (present && !error) {
    728             atomicBitsetSetBit(sensorPresent, i - 1);
    729             numSensors++;
    730             totalBlocks += maxBlocks;
    731         }
    732     }
    733 
    734     if (totalBlocks > MAX_NUM_BLOCKS) {
    735         osLog(LOG_INFO, "initSensors: totalBlocks of %ld exceeds maximum of %d\n", totalBlocks, MAX_NUM_BLOCKS);
    736         totalBlocks = MAX_NUM_BLOCKS;
    737     } else if (totalBlocks < MIN_NUM_BLOCKS) {
    738         totalBlocks = MIN_NUM_BLOCKS;
    739     }
    740 
    741     mOutputQ = simpleQueueAlloc(totalBlocks, sizeof(struct HostIntfDataBuffer), queueDiscard);
    742     if (!mOutputQ) {
    743         osLog(LOG_ERROR, "initSensors: failed to allocate data buffer queue!\n");
    744         return false;
    745     }
    746 
    747     mActiveSensorTable = heapAlloc(numSensors * sizeof(struct ActiveSensor));
    748     if (!mActiveSensorTable) {
    749         osLog(LOG_ERROR, "initSensors: failed to allocate active sensor table!\n");
    750         simpleQueueDestroy(mOutputQ);
    751         return false;
    752     }
    753 
    754     memset(mActiveSensorTable, 0x00, numSensors * sizeof(struct ActiveSensor));
    755 
    756     for (i = SENS_TYPE_INVALID; i < SENS_TYPE_LAST_USER; i++) {
    757         mSensorList[i] = MAX_REGISTERED_SENSORS;
    758     }
    759 
    760     for (i = SENS_TYPE_INVALID + 1, j = 0; i <= SENS_TYPE_LAST_USER && j < numSensors; i++) {
    761         if (atomicBitsetGetBit(sensorPresent, i - 1)
    762             && (si = sensorFind(i, 0, &handle)) != NULL
    763             && !(si->flags1 & SENSOR_INFO_FLAGS1_LOCAL_ONLY)) {
    764             mSensorList[i - 1] = j;
    765             resetBuffer(mActiveSensorTable + j);
    766             mActiveSensorTable[j].buffer.sensType = i;
    767             mActiveSensorTable[j].biasReportType = 0;
    768             mActiveSensorTable[j].rate = 0;
    769             mActiveSensorTable[j].latency = 0;
    770             mActiveSensorTable[j].numAxis = si->numAxis;
    771             mActiveSensorTable[j].interrupt = si->interrupt;
    772             if (si->flags1 & SENSOR_INFO_FLAGS1_RAW) {
    773                 mSensorList[si->rawType - 1] = j;
    774                 mActiveSensorTable[j].buffer.sensType = si->rawType;
    775                 mActiveSensorTable[j].raw = true;
    776                 mActiveSensorTable[j].rawScale = si->rawScale;
    777             }
    778             if (si->flags1 & SENSOR_INFO_FLAGS1_BIAS) {
    779                 mSensorList[si->biasType - 1] = j;
    780                 mActiveSensorTable[j].biasReportType = i;
    781                 osEventSubscribe(mHostIntfTid, sensorGetMyEventType(si->biasType));
    782             }
    783             if (si->minSamples > MAX_MIN_SAMPLES) {
    784                 mActiveSensorTable[j].minSamples = MAX_MIN_SAMPLES;
    785                 osLog(LOG_INFO, "initSensors: %s: minSamples of %d exceeded max of %d\n", si->sensorName, si->minSamples, MAX_MIN_SAMPLES);
    786             } else {
    787                 mActiveSensorTable[j].minSamples = si->minSamples;
    788             }
    789             mActiveSensorTable[j].curSamples = 0;
    790             mActiveSensorTable[j].oneshot = false;
    791             mActiveSensorTable[j].firstTime = 0ull;
    792             switch (si->numAxis) {
    793             case NUM_AXIS_EMBEDDED:
    794             case NUM_AXIS_ONE:
    795                 mActiveSensorTable[j].packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct SingleAxisDataPoint);
    796                 break;
    797             case NUM_AXIS_THREE:
    798                 if (mActiveSensorTable[j].raw)
    799                     mActiveSensorTable[j].packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct RawTripleAxisDataPoint);
    800                 else
    801                     mActiveSensorTable[j].packetSamples = HOSTINTF_SENSOR_DATA_MAX / sizeof(struct TripleAxisDataPoint);
    802                 break;
    803             }
    804             j++;
    805         }
    806     }
    807 
    808     mTotalBlocks = totalBlocks;
    809     mNumSensors = numSensors;
    810 
    811     return true;
    812 }
    813 
    814 static inline int16_t floatToInt16(float val)
    815 {
    816     if (val < (INT16_MIN + 0.5f))
    817         return INT16_MIN;
    818     else if (val > (INT16_MAX - 0.5f))
    819         return INT16_MAX;
    820     else if (val >= 0.0f)
    821         return val + 0.5f;
    822     else
    823         return val - 0.5f;
    824 }
    825 
    826 static uint32_t encodeDeltaTime(uint64_t time)
    827 {
    828     uint32_t deltaTime;
    829 
    830     if (time <= UINT32_MAX) {
    831         deltaTime = time | delta_time_fine_mask;
    832     } else {
    833         deltaTime = ((time + delta_time_rounding) >> delta_time_multiplier_order) & delta_time_coarse_mask;
    834     }
    835     return deltaTime;
    836 }
    837 
    838 static bool enqueueSensorBuffer(struct ActiveSensor *sensor)
    839 {
    840     bool queued = simpleQueueEnqueue(mOutputQ, &sensor->buffer,
    841                                      sizeof(uint32_t) + sensor->buffer.length, sensor->discard);
    842 
    843     if (!queued) {
    844         // undo counters if failed to add buffer
    845         if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    846             mWakeupBlocks--;
    847         else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    848             mNonWakeupBlocks--;
    849         sensor->curSamples -= sensor->buffer.firstSample.numSamples;
    850     }
    851     resetBuffer(sensor);
    852     return queued;
    853 }
    854 
    855 static void copySingleSamples(struct ActiveSensor *sensor, const struct SingleAxisDataEvent *single)
    856 {
    857     int i;
    858     uint32_t deltaTime;
    859     uint8_t numSamples;
    860     uint8_t evtNumSamples = single->samples[0].firstSample.numSamples;
    861 
    862     for (i = 0; i < evtNumSamples; i++) {
    863         if (sensor->buffer.firstSample.numSamples == sensor->packetSamples)
    864             enqueueSensorBuffer(sensor);
    865 
    866         if (sensor->buffer.firstSample.numSamples == 0) {
    867             if (i == 0) {
    868                 sensor->lastTime = sensor->buffer.referenceTime = single->referenceTime;
    869             } else {
    870                 sensor->lastTime += single->samples[i].deltaTime;
    871                 sensor->buffer.referenceTime = sensor->lastTime;
    872             }
    873             sensor->buffer.length = sizeof(struct SingleAxisDataEvent) + sizeof(struct SingleAxisDataPoint);
    874             sensor->buffer.single[0].idata = single->samples[i].idata;
    875             if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    876                 mWakeupBlocks++;
    877             else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    878                 mNonWakeupBlocks++;
    879             sensor->buffer.firstSample.numSamples = 1;
    880             sensor->buffer.firstSample.interrupt = sensor->interrupt;
    881             if (sensor->curSamples++ == 0)
    882                 sensor->firstTime = sensor->buffer.referenceTime;
    883         } else {
    884             if (i == 0) {
    885                 if (sensor->lastTime > single->referenceTime) {
    886                     // shouldn't happen. flush current packet
    887                     enqueueSensorBuffer(sensor);
    888                     i--;
    889                 } else if (single->referenceTime - sensor->lastTime >= delta_time_max) {
    890                     enqueueSensorBuffer(sensor);
    891                     i--;
    892                 } else {
    893                     deltaTime = encodeDeltaTime(single->referenceTime - sensor->lastTime);
    894                     numSamples = sensor->buffer.firstSample.numSamples;
    895 
    896                     sensor->buffer.length += sizeof(struct SingleAxisDataPoint);
    897                     sensor->buffer.single[numSamples].deltaTime = deltaTime;
    898                     sensor->buffer.single[numSamples].idata = single->samples[0].idata;
    899                     sensor->lastTime = single->referenceTime;
    900                     sensor->buffer.firstSample.numSamples++;
    901                     sensor->curSamples++;
    902                 }
    903             } else {
    904                 deltaTime = single->samples[i].deltaTime;
    905                 numSamples = sensor->buffer.firstSample.numSamples;
    906 
    907                 sensor->buffer.length += sizeof(struct SingleAxisDataPoint);
    908                 sensor->buffer.single[numSamples].deltaTime = deltaTime | delta_time_fine_mask;
    909                 sensor->buffer.single[numSamples].idata = single->samples[i].idata;
    910                 sensor->lastTime += deltaTime;
    911                 sensor->buffer.firstSample.numSamples++;
    912                 sensor->curSamples++;
    913             }
    914         }
    915     }
    916 }
    917 
    918 static void copyTripleSamples(struct ActiveSensor *sensor, const struct TripleAxisDataEvent *triple)
    919 {
    920     int i;
    921     uint32_t deltaTime;
    922     uint8_t numSamples;
    923 
    924     for (i = 0; i < triple->samples[0].firstSample.numSamples; i++) {
    925         if (sensor->buffer.firstSample.numSamples == sensor->packetSamples)
    926             enqueueSensorBuffer(sensor);
    927 
    928         if (sensor->buffer.firstSample.numSamples == 0) {
    929             if (i == 0) {
    930                 sensor->lastTime = sensor->buffer.referenceTime = triple->referenceTime;
    931             } else {
    932                 sensor->lastTime += triple->samples[i].deltaTime;
    933                 sensor->buffer.referenceTime = sensor->lastTime;
    934             }
    935             sensor->buffer.length = sizeof(struct TripleAxisDataEvent) + sizeof(struct TripleAxisDataPoint);
    936             sensor->buffer.triple[0].ix = triple->samples[i].ix;
    937             sensor->buffer.triple[0].iy = triple->samples[i].iy;
    938             sensor->buffer.triple[0].iz = triple->samples[i].iz;
    939             if (triple->samples[0].firstSample.biasPresent && triple->samples[0].firstSample.biasSample == i) {
    940                 sensor->buffer.firstSample.biasCurrent = triple->samples[0].firstSample.biasCurrent;
    941                 sensor->buffer.firstSample.biasPresent = 1;
    942                 sensor->buffer.firstSample.biasSample = 0;
    943                 sensor->discard = false;
    944             }
    945             if (sensor->interrupt == NANOHUB_INT_WAKEUP)
    946                 mWakeupBlocks++;
    947             else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
    948                 mNonWakeupBlocks++;
    949             sensor->buffer.firstSample.numSamples = 1;
    950             sensor->buffer.firstSample.interrupt = sensor->interrupt;
    951             if (sensor->curSamples++ == 0)
    952                 sensor->firstTime = sensor->buffer.referenceTime;
    953         } else {
    954             if (i == 0) {
    955                 if (sensor->lastTime > triple->referenceTime) {
    956                     // shouldn't happen. flush current packet
    957                     enqueueSensorBuffer(sensor);
    958                     i--;
    959                 } else if (triple->referenceTime - sensor->lastTime >= delta_time_max) {
    960                     enqueueSensorBuffer(sensor);
    961                     i--;
    962                 } else {
    963                     deltaTime = encodeDeltaTime(triple->referenceTime - sensor->lastTime);
    964                     numSamples = sensor->buffer.firstSample.numSamples;
    965 
    966                     sensor->buffer.length += sizeof(struct TripleAxisDataPoint);
    967                     sensor->buffer.triple[numSamples].deltaTime = deltaTime;
    968                     sensor->buffer.triple[numSamples].ix = triple->samples[0].ix;
    969                     sensor->buffer.triple[numSamples].iy = triple->samples[0].iy;
    970                     sensor->buffer.triple[numSamples].iz = triple->samples[0].iz;
    971                     sensor->lastTime = triple->referenceTime;
    972                     if (triple->samples[0].firstSample.biasPresent && triple->samples[0].firstSample.biasSample == 0) {
    973                         sensor->buffer.firstSample.biasCurrent = triple->samples[0].firstSample.biasCurrent;
    974                         sensor->buffer.firstSample.biasPresent = 1;
    975                         sensor->buffer.firstSample.biasSample = numSamples;
    976                         sensor->discard = false;
    977                     }
    978                     sensor->buffer.firstSample.numSamples++;
    979                     sensor->curSamples++;
    980                 }
    981             } else {
    982                 deltaTime = triple->samples[i].deltaTime;
    983                 numSamples = sensor->buffer.firstSample.numSamples;
    984 
    985                 sensor->buffer.length += sizeof(struct TripleAxisDataPoint);
    986                 sensor->buffer.triple[numSamples].deltaTime = deltaTime | delta_time_fine_mask;
    987                 sensor->buffer.triple[numSamples].ix = triple->samples[i].ix;
    988                 sensor->buffer.triple[numSamples].iy = triple->samples[i].iy;
    989                 sensor->buffer.triple[numSamples].iz = triple->samples[i].iz;
    990                 sensor->lastTime += deltaTime;
    991                 if (triple->samples[0].firstSample.biasPresent && triple->samples[0].firstSample.biasSample == i) {
    992                     sensor->buffer.firstSample.biasCurrent = triple->samples[0].firstSample.biasCurrent;
    993                     sensor->buffer.firstSample.biasPresent = 1;
    994                     sensor->buffer.firstSample.biasSample = numSamples;
    995                     sensor->discard = false;
    996                 }
    997                 sensor->buffer.firstSample.numSamples++;
    998                 sensor->curSamples++;
    999             }
   1000         }
   1001     }
   1002 }
   1003 
   1004 static void copyTripleSamplesBias(struct ActiveSensor *sensor, const struct TripleAxisDataEvent *triple)
   1005 {
   1006     uint8_t sensType = sensor->buffer.sensType;
   1007 
   1008     if (sensType == sensor->biasReportType) {
   1009         copyTripleSamples(sensor, triple);
   1010     } else {
   1011         // Bias needs to be sent with a different sensType, so enqueue any pending buffer, enqueue
   1012         // bias with a different sensor type, then restore the sensType
   1013         if (sensor->buffer.firstSample.numSamples > 0)
   1014             enqueueSensorBuffer(sensor);
   1015         sensor->buffer.sensType = sensor->biasReportType;
   1016         copyTripleSamples(sensor, triple);
   1017         if (sensor->buffer.firstSample.numSamples > 0)
   1018             enqueueSensorBuffer(sensor);
   1019         sensor->buffer.sensType = sensType;
   1020     }
   1021 }
   1022 
   1023 static void copyTripleSamplesRaw(struct ActiveSensor *sensor, const struct TripleAxisDataEvent *triple)
   1024 {
   1025     int i;
   1026     uint32_t deltaTime;
   1027     uint8_t numSamples;
   1028 
   1029     // Bias not supported in raw format; treat as regular format triple samples (potentially
   1030     // handling alternate bias report type)
   1031     if (triple->samples[0].firstSample.biasPresent) {
   1032         copyTripleSamplesBias(sensor, triple);
   1033         return;
   1034     }
   1035 
   1036     for (i = 0; i < triple->samples[0].firstSample.numSamples; i++) {
   1037         if (sensor->buffer.firstSample.numSamples == sensor->packetSamples)
   1038             enqueueSensorBuffer(sensor);
   1039 
   1040         if (sensor->buffer.firstSample.numSamples == 0) {
   1041             if (i == 0) {
   1042                 sensor->lastTime = sensor->buffer.referenceTime = triple->referenceTime;
   1043             } else {
   1044                 sensor->lastTime += triple->samples[i].deltaTime;
   1045                 sensor->buffer.referenceTime = sensor->lastTime;
   1046             }
   1047             sensor->buffer.length = sizeof(struct RawTripleAxisDataEvent) + sizeof(struct RawTripleAxisDataPoint);
   1048             sensor->buffer.rawTriple[0].ix = floatToInt16(triple->samples[i].x * sensor->rawScale);
   1049             sensor->buffer.rawTriple[0].iy = floatToInt16(triple->samples[i].y * sensor->rawScale);
   1050             sensor->buffer.rawTriple[0].iz = floatToInt16(triple->samples[i].z * sensor->rawScale);
   1051             if (sensor->interrupt == NANOHUB_INT_WAKEUP)
   1052                 mWakeupBlocks++;
   1053             else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
   1054                 mNonWakeupBlocks++;
   1055             sensor->buffer.firstSample.numSamples = 1;
   1056             sensor->buffer.firstSample.interrupt = sensor->interrupt;
   1057             if (sensor->curSamples++ == 0)
   1058                 sensor->firstTime = sensor->buffer.referenceTime;
   1059         } else {
   1060             if (i == 0) {
   1061                 if (sensor->lastTime > triple->referenceTime) {
   1062                     // shouldn't happen. flush current packet
   1063                     enqueueSensorBuffer(sensor);
   1064                     i--;
   1065                 } else if (triple->referenceTime - sensor->lastTime >= delta_time_max) {
   1066                     enqueueSensorBuffer(sensor);
   1067                     i--;
   1068                 } else {
   1069                     deltaTime = encodeDeltaTime(triple->referenceTime - sensor->lastTime);
   1070                     numSamples = sensor->buffer.firstSample.numSamples;
   1071 
   1072                     sensor->buffer.length += sizeof(struct RawTripleAxisDataPoint);
   1073                     sensor->buffer.rawTriple[numSamples].deltaTime = deltaTime;
   1074                     sensor->buffer.rawTriple[numSamples].ix = floatToInt16(triple->samples[0].x * sensor->rawScale);
   1075                     sensor->buffer.rawTriple[numSamples].iy = floatToInt16(triple->samples[0].y * sensor->rawScale);
   1076                     sensor->buffer.rawTriple[numSamples].iz = floatToInt16(triple->samples[0].z * sensor->rawScale);
   1077                     sensor->lastTime = triple->referenceTime;
   1078                     sensor->buffer.firstSample.numSamples++;
   1079                     sensor->curSamples++;
   1080                 }
   1081             } else {
   1082                 deltaTime = triple->samples[i].deltaTime;
   1083                 numSamples = sensor->buffer.firstSample.numSamples;
   1084 
   1085                 sensor->buffer.length += sizeof(struct RawTripleAxisDataPoint);
   1086                 sensor->buffer.rawTriple[numSamples].deltaTime = deltaTime | delta_time_fine_mask;
   1087                 sensor->buffer.rawTriple[numSamples].ix = floatToInt16(triple->samples[i].x * sensor->rawScale);
   1088                 sensor->buffer.rawTriple[numSamples].iy = floatToInt16(triple->samples[i].y * sensor->rawScale);
   1089                 sensor->buffer.rawTriple[numSamples].iz = floatToInt16(triple->samples[i].z * sensor->rawScale);
   1090                 sensor->lastTime += deltaTime;
   1091                 sensor->buffer.firstSample.numSamples++;
   1092                 sensor->curSamples++;
   1093             }
   1094         }
   1095     }
   1096 }
   1097 
   1098 static void hostIntfAddBlock(struct HostIntfDataBuffer *data, bool discardable, bool interrupt)
   1099 {
   1100     if (!simpleQueueEnqueue(mOutputQ, data, sizeof(uint32_t) + data->length, discardable))
   1101         return;
   1102 
   1103     if (data->interrupt == NANOHUB_INT_WAKEUP)
   1104         mWakeupBlocks++;
   1105     else if (data->interrupt == NANOHUB_INT_NONWAKEUP)
   1106         mNonWakeupBlocks++;
   1107     nanohubPrefetchTx(interrupt ? data->interrupt : HOSTINTF_MAX_INTERRUPTS, mWakeupBlocks, mNonWakeupBlocks);
   1108 }
   1109 
   1110 static void hostIntfNotifyReboot(uint32_t reason)
   1111 {
   1112     __le32 raw_reason = htole32(reason);
   1113 
   1114     struct NanohubHalSysMgmtTx *resp;
   1115     resp = heapAlloc(sizeof(*resp));
   1116     if (resp) {
   1117         resp->hdr = (struct NanohubHalHdr) {
   1118             .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0),
   1119             .len = sizeof(*resp) - sizeof(resp->hdr),
   1120         };
   1121         resp->ret = (struct NanohubHalRet) {
   1122             .msg = NANOHUB_HAL_SYS_MGMT,
   1123             .status = raw_reason,
   1124         };
   1125         resp->cmd = NANOHUB_HAL_SYS_MGMT_REBOOT;
   1126         osEnqueueEvtOrFree(EVT_APP_TO_HOST_CHRE, resp, heapFree);
   1127     }
   1128 
   1129 #ifdef LEGACY_HAL_ENABLED
   1130     struct NanohubHalLegacyRebootTx *respLegacy;
   1131     respLegacy = heapAlloc(sizeof(*respLegacy));
   1132     if (respLegacy) {
   1133         respLegacy->hdr = (struct NanohubHalLegacyHdr) {
   1134             .appId = APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0),
   1135             .len = sizeof(*respLegacy) - sizeof(respLegacy->hdr) + sizeof(respLegacy->hdr.msg),
   1136             .msg = NANOHUB_HAL_LEGACY_REBOOT,
   1137         };
   1138         memcpy(&respLegacy->reason, &raw_reason, sizeof(respLegacy->reason));
   1139         osEnqueueEvtOrFree(EVT_APP_TO_HOST, respLegacy, heapFree);
   1140     }
   1141 #endif
   1142 }
   1143 
   1144 static void queueFlush(struct ActiveSensor *sensor)
   1145 {
   1146     if (sensor->buffer.length == 0) {
   1147         sensor->buffer.length = sizeof(sensor->buffer.referenceTime) + sizeof(struct SensorFirstSample);
   1148         sensor->buffer.referenceTime = 0ull;
   1149         if (sensor->interrupt == NANOHUB_INT_WAKEUP)
   1150             mWakeupBlocks++;
   1151         else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
   1152             mNonWakeupBlocks++;
   1153         sensor->buffer.firstSample.numFlushes = 1;
   1154     } else {
   1155         sensor->buffer.firstSample.numFlushes++;
   1156     }
   1157     sensor->discard = false;
   1158     hostIntfSetInterrupt(sensor->interrupt);
   1159 }
   1160 
   1161 static void fakeFlush(struct ConfigCmd *cmd)
   1162 {
   1163     struct HostIntfDataBuffer *buffer;
   1164     uint8_t size = sizeof(buffer->evtType) + sizeof(buffer->referenceTime) + sizeof(struct SensorFirstSample);
   1165     buffer = alloca(size);
   1166     memset(buffer, 0x00, size);
   1167 
   1168     buffer->sensType = cmd->sensType;
   1169     buffer->length = sizeof(buffer->referenceTime) + sizeof(struct SensorFirstSample);
   1170     buffer->interrupt = NANOHUB_INT_WAKEUP;
   1171     mWakeupBlocks++;
   1172     buffer->firstSample.numFlushes = 1;
   1173     if (!simpleQueueEnqueue(mOutputQ, buffer, size, false))
   1174         mWakeupBlocks--;
   1175 }
   1176 
   1177 static void onEvtAppStart(const void *evtData)
   1178 {
   1179     if (initSensors()) {
   1180         uint32_t reason;
   1181         struct HostIntfDataBuffer *data;
   1182 
   1183         osEventUnsubscribe(mHostIntfTid, EVT_APP_START);
   1184         osEventsSubscribe(4, EVT_NO_SENSOR_CONFIG_EVENT,
   1185                              EVT_APP_TO_SENSOR_HAL_DATA,
   1186                              EVT_APP_TO_HOST,
   1187                              EVT_APP_TO_HOST_CHRE);
   1188 #ifdef DEBUG_LOG_EVT
   1189         osEventSubscribe(mHostIntfTid, EVT_DEBUG_LOG);
   1190         platEarlyLogFlush();
   1191 #endif
   1192         reason = pwrResetReason();
   1193         data = alloca(sizeof(uint32_t) + sizeof(reason));
   1194         data->sensType = SENS_TYPE_INVALID;
   1195         data->length = sizeof(reason);
   1196         data->dataType = HOSTINTF_DATA_TYPE_RESET_REASON;
   1197         data->interrupt = NANOHUB_INT_WAKEUP;
   1198         memcpy(data->buffer, &reason, sizeof(reason));
   1199         hostIntfAddBlock(data, false, true);
   1200         hostIntfNotifyReboot(reason);
   1201     }
   1202 }
   1203 
   1204 static void onEvtAppToHost(const void *evtData)
   1205 {
   1206     const struct HostHubRawPacket *hostMsg = evtData;
   1207 
   1208     if (hostMsg->dataLen <= HOST_HUB_RAW_PACKET_MAX_LEN) {
   1209         struct HostIntfDataBuffer *data = alloca(sizeof(uint32_t) + sizeof(*hostMsg) + hostMsg->dataLen);
   1210 
   1211         data->sensType = SENS_TYPE_INVALID;
   1212         data->length = sizeof(*hostMsg) + hostMsg->dataLen;
   1213         data->dataType = HOSTINTF_DATA_TYPE_APP_TO_HOST;
   1214         data->interrupt = NANOHUB_INT_WAKEUP;
   1215         memcpy(data->buffer, evtData, data->length);
   1216         hostIntfAddBlock(data, false, true);
   1217     }
   1218 }
   1219 
   1220 static void onEvtAppToHostChre(const void *evtData)
   1221 {
   1222     const struct HostHubChrePacket *hostMsg = evtData;
   1223 
   1224     if (hostMsg->messageSize <= HOST_HUB_CHRE_PACKET_MAX_LEN) {
   1225         struct HostIntfDataBuffer *data = alloca(sizeof(uint32_t) + sizeof(*hostMsg) + hostMsg->messageSize);
   1226 
   1227         data->sensType = SENS_TYPE_INVALID;
   1228         data->length = sizeof(*hostMsg) + hostMsg->messageSize;
   1229         data->dataType = HOSTINTF_DATA_TYPE_APP_TO_HOST;
   1230         data->interrupt = NANOHUB_INT_WAKEUP;
   1231         memcpy(data->buffer, evtData, data->length);
   1232         hostIntfAddBlock(data, false, true);
   1233     }
   1234 }
   1235 
   1236 #ifdef LEGACY_HAL_ENABLED
   1237 static void handleLegacyHalCmd(const uint8_t *halData, uint8_t size)
   1238 {
   1239     const struct NanohubHalLegacyCommand *halCmd = nanohubHalLegacyFindCommand(halData[0]);
   1240     if (halCmd)
   1241         halCmd->handler((void *)&halData[1], size - 1);
   1242 }
   1243 
   1244 static void onEvtAppFromHost(const void *evtData)
   1245 {
   1246     const uint8_t *halMsg = evtData;
   1247     handleLegacyHalCmd(&halMsg[1], halMsg[0]);
   1248 }
   1249 #endif
   1250 
   1251 static void onEvtAppFromHostChre(const void *evtData)
   1252 {
   1253     const struct NanohubMsgChreHdr *halMsg = (const struct NanohubMsgChreHdr *)evtData;
   1254     const struct NanohubHalCommand *halCmd;
   1255     const uint8_t *halData = (const uint8_t *)(halMsg+1);
   1256     uint8_t len;
   1257     uint32_t transactionId;
   1258 
   1259     memcpy(&transactionId, &halMsg->appEvent, sizeof(halMsg->appEvent));
   1260 
   1261     if (halMsg->size >= 1) {
   1262         len = halMsg->size - 1;
   1263         halCmd = nanohubHalFindCommand(halData[0]);
   1264         if (halCmd) {
   1265             if (len >= halCmd->minDataLen && len <= halCmd->maxDataLen)
   1266                 halCmd->handler((void *)&halData[1], len, transactionId);
   1267             return;
   1268         }
   1269     }
   1270 #ifdef LEGACY_HAL_ENABLED
   1271     handleLegacyHalCmd(halData, halMsg->size);
   1272 #endif
   1273 }
   1274 
   1275 #ifdef DEBUG_LOG_EVT
   1276 static void onEvtDebugLog(const void *evtData)
   1277 {
   1278     struct HostIntfDataBuffer *data = (struct HostIntfDataBuffer *)evtData;
   1279 
   1280     if (data->sensType == SENS_TYPE_INVALID && data->dataType == HOSTINTF_DATA_TYPE_LOG)
   1281         hostIntfAddBlock(data, true, true);
   1282 }
   1283 #endif
   1284 
   1285 static void onEvtLatencyTimer(const void *evtData)
   1286 {
   1287     uint64_t sensorTime = sensorGetTime();
   1288     uint32_t i, cnt;
   1289 
   1290     for (i = 0, cnt = 0; i < mNumSensors && cnt < mLatencyCnt; i++) {
   1291         if (mActiveSensorTable[i].latency > 0) {
   1292             cnt++;
   1293             if (mActiveSensorTable[i].firstTime &&
   1294                 sensorTime >= mActiveSensorTable[i].firstTime + mActiveSensorTable[i].latency) {
   1295                 hostIntfSetInterrupt(mActiveSensorTable[i].interrupt);
   1296             }
   1297         }
   1298     }
   1299 }
   1300 
   1301 static void onConfigCmdFlushOne(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1302 {
   1303     sensorFlush(sensor->sensorHandle);
   1304 }
   1305 
   1306 static void onConfigCmdEnableOne(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1307 {
   1308     if (sensorRequestRateChange(mHostIntfTid, sensor->sensorHandle, cmd->rate, cmd->latency)) {
   1309         sensor->rate = cmd->rate;
   1310         if (sensor->latency != cmd->latency) {
   1311             if (!sensor->latency) {
   1312                 if (mLatencyCnt++ == 0)
   1313                     mLatencyTimer = timTimerSet(CHECK_LATENCY_TIME, 100, 100, latencyTimerCallback, NULL, false);
   1314             } else if (!cmd->latency) {
   1315                 if (--mLatencyCnt == 0) {
   1316                     timTimerCancel(mLatencyTimer);
   1317                     mLatencyTimer = 0;
   1318                 }
   1319             }
   1320             sensor->latency = cmd->latency;
   1321         }
   1322     }
   1323 }
   1324 
   1325 static void onConfigCmdEnableAll(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1326 {
   1327     for (uint32_t i = 0; sensorFind(cmd->sensType, i, &sensor->sensorHandle) != NULL; i++) {
   1328         if (cmd->rate == SENSOR_RATE_ONESHOT) {
   1329             cmd->rate = SENSOR_RATE_ONCHANGE;
   1330             sensor->oneshot = true;
   1331         } else {
   1332             sensor->oneshot = false;
   1333         }
   1334 
   1335         if (sensorRequest(mHostIntfTid, sensor->sensorHandle, cmd->rate, cmd->latency)) {
   1336             if (cmd->latency) {
   1337                 if (mLatencyCnt++ == 0)
   1338                     mLatencyTimer = timTimerSet(CHECK_LATENCY_TIME, 100, 100, latencyTimerCallback, NULL, false);
   1339             }
   1340             sensor->rate = cmd->rate;
   1341             sensor->latency = cmd->latency;
   1342             osEventSubscribe(mHostIntfTid, sensorGetMyEventType(cmd->sensType));
   1343             break;
   1344         } else {
   1345             sensor->sensorHandle = 0;
   1346         }
   1347     }
   1348 }
   1349 
   1350 static void onConfigCmdDisableOne(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1351 {
   1352     sensorRelease(mHostIntfTid, sensor->sensorHandle);
   1353     osEventUnsubscribe(mHostIntfTid, sensorGetMyEventType(cmd->sensType));
   1354     if (sensor->latency) {
   1355         if (--mLatencyCnt == 0) {
   1356             timTimerCancel(mLatencyTimer);
   1357             mLatencyTimer = 0;
   1358         }
   1359     }
   1360     sensor->rate = 0;
   1361     sensor->latency = 0;
   1362     sensor->oneshot = false;
   1363     sensor->sensorHandle = 0;
   1364     if (sensor->buffer.length) {
   1365         enqueueSensorBuffer(sensor);
   1366         hostIntfSetInterrupt(sensor->interrupt);
   1367     }
   1368 }
   1369 
   1370 static void onConfigCmdCalibrateAll(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1371 {
   1372     uint32_t tempSensorHandle;
   1373     for (uint32_t i = 0; sensorFind(cmd->sensType, i, &tempSensorHandle) != NULL; i++)
   1374         sensorCalibrate(tempSensorHandle);
   1375 }
   1376 
   1377 static void onConfigCmdSelfTestAll(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1378 {
   1379     uint32_t tempSensorHandle;
   1380     for (uint32_t i = 0; sensorFind(cmd->sensType, i, &tempSensorHandle) != NULL; i++)
   1381         sensorSelfTest(tempSensorHandle);
   1382 }
   1383 
   1384 static void onConfigCmdCfgDataAll(struct ActiveSensor *sensor, struct ConfigCmd *cmd)
   1385 {
   1386     uint32_t tempSensorHandle;
   1387     for (uint32_t i = 0; sensorFind(cmd->sensType, i, &tempSensorHandle) != NULL; i++)
   1388         sensorCfgData(tempSensorHandle, (void *)(cmd+1));
   1389 }
   1390 
   1391 static void onEvtNoSensorConfigEvent(const void *evtData)
   1392 {
   1393     struct ConfigCmd *cmd = (struct ConfigCmd *)evtData;
   1394     struct ActiveSensor *sensor = getActiveSensorByType(cmd->sensType);
   1395     if (sensor) {
   1396         if (sensor->sensorHandle) {
   1397             switch (cmd->cmd) {
   1398             case CONFIG_CMD_FLUSH:
   1399                 onConfigCmdFlushOne(sensor, cmd);
   1400                 break;
   1401             case CONFIG_CMD_ENABLE:
   1402                 onConfigCmdEnableOne(sensor, cmd);
   1403                 break;
   1404             case CONFIG_CMD_DISABLE:
   1405                 onConfigCmdDisableOne(sensor, cmd);
   1406                 break;
   1407             case CONFIG_CMD_CFG_DATA:
   1408                 onConfigCmdCfgDataAll(sensor, cmd);
   1409                 break;
   1410             }
   1411         } else {
   1412             switch (cmd->cmd) {
   1413             case CONFIG_CMD_ENABLE:
   1414                 onConfigCmdEnableAll(sensor, cmd);
   1415                 break;
   1416             case CONFIG_CMD_CALIBRATE:
   1417                 onConfigCmdCalibrateAll(sensor, cmd);
   1418                 break;
   1419             case CONFIG_CMD_SELF_TEST:
   1420                 onConfigCmdSelfTestAll(sensor, cmd);
   1421                 break;
   1422             case CONFIG_CMD_CFG_DATA:
   1423                 onConfigCmdCfgDataAll(sensor, cmd);
   1424                 break;
   1425             case CONFIG_CMD_FLUSH:
   1426                 queueFlush(sensor);
   1427                 break;
   1428             }
   1429         }
   1430     } else if (cmd->cmd == CONFIG_CMD_FLUSH && cmd->sensType > SENS_TYPE_INVALID) {
   1431         // if a flush event is for an unknown sensor, we just return a fake flush event.
   1432         osLog(LOG_INFO, "Flush request from unrecognized sensor, returning a fake flush\n");
   1433         fakeFlush(cmd);
   1434     }
   1435 }
   1436 
   1437 static void onEvtAppToSensorHalData(const void *evtData)
   1438 {
   1439     struct HostIntfDataBuffer *data = (struct HostIntfDataBuffer *)evtData;
   1440     if (data->sensType == SENS_TYPE_INVALID
   1441             && data->dataType == HOSTINTF_DATA_TYPE_APP_TO_SENSOR_HAL) {
   1442         struct AppToSensorHalDataBuffer *buffer = (struct AppToSensorHalDataBuffer *)data;
   1443         hostIntfAddBlock(data, (buffer->payload.type & EVENT_TYPE_BIT_DISCARDABLE) != 0, false);
   1444     }
   1445 }
   1446 
   1447 static void copyEmbeddedSamples(struct ActiveSensor *sensor, const void* evtData)
   1448 {
   1449     uint64_t sensorTime = sensorGetTime();
   1450 
   1451     if (sensor->buffer.length > 0 && sensorTime - sensor->lastTime >= delta_time_max)
   1452         enqueueSensorBuffer(sensor);
   1453 
   1454     if (sensor->buffer.length == 0) {
   1455         sensor->buffer.length = sizeof(struct SingleAxisDataEvent) + sizeof(struct SingleAxisDataPoint);
   1456         sensor->lastTime = sensor->buffer.referenceTime = sensorTime;
   1457         if (sensor->interrupt == NANOHUB_INT_WAKEUP)
   1458             mWakeupBlocks++;
   1459         else if (sensor->interrupt == NANOHUB_INT_NONWAKEUP)
   1460             mNonWakeupBlocks++;
   1461         sensor->buffer.firstSample.numSamples = 1;
   1462         sensor->buffer.firstSample.interrupt = sensor->interrupt;
   1463         sensor->buffer.single[0].idata = (uint32_t)evtData;
   1464     } else {
   1465         sensor->buffer.length += sizeof(struct SingleAxisDataPoint);
   1466         sensor->buffer.single[sensor->buffer.firstSample.numSamples].deltaTime =
   1467                 encodeDeltaTime(sensorTime - sensor->lastTime);
   1468         sensor->lastTime = sensorTime;
   1469         sensor->buffer.single[sensor->buffer.firstSample.numSamples].idata = (uint32_t)evtData;
   1470         sensor->buffer.firstSample.numSamples++;
   1471     }
   1472     if (sensor->curSamples++ == 0)
   1473         sensor->firstTime = sensor->buffer.referenceTime;
   1474 }
   1475 
   1476 static uint32_t getSensorInterrupt(struct ActiveSensor *sensor)
   1477 {
   1478     uint32_t interrupt = HOSTINTF_MAX_INTERRUPTS;
   1479     uint64_t sensorTime = sensorGetTime();
   1480 
   1481     if (sensor->firstTime &&
   1482         ((sensorTime >= sensor->firstTime + sensor->latency) ||
   1483          ((sensor->latency > sensorGetCurLatency(sensor->sensorHandle)) &&
   1484           (sensorTime + sensorGetCurLatency(sensor->sensorHandle) > sensor->firstTime + sensor->latency)))) {
   1485         interrupt = sensor->interrupt;
   1486     } else if (mWakeupBlocks + mNonWakeupBlocks >= mTotalBlocks) {
   1487         interrupt = sensor->interrupt;
   1488     }
   1489 
   1490     return interrupt;
   1491 }
   1492 
   1493 static void onEvtSensorDataActive(struct ActiveSensor *sensor, uint32_t evtType, const void* evtData)
   1494 {
   1495     if (evtData == SENSOR_DATA_EVENT_FLUSH) {
   1496         queueFlush(sensor);
   1497     } else {
   1498         bool haveFlush = sensor->buffer.firstSample.numFlushes > 0;
   1499         if (sensor->buffer.length > 0 &&
   1500             (haveFlush || sensor->buffer.firstSample.numSamples == sensor->packetSamples)) {
   1501                 // processing will be aborted if we have pending flush and are not able to send
   1502                 // in this case, send eventually will be retried, otherwise data will be lost
   1503                 if (!enqueueSensorBuffer(sensor) && haveFlush)
   1504                     return;
   1505         }
   1506 
   1507         switch (sensor->numAxis) {
   1508         case NUM_AXIS_EMBEDDED:
   1509             copyEmbeddedSamples(sensor, evtData);
   1510             break;
   1511         case NUM_AXIS_ONE:
   1512             copySingleSamples(sensor, evtData);
   1513             break;
   1514         case NUM_AXIS_THREE:
   1515             if (sensor->raw)
   1516                 copyTripleSamplesRaw(sensor, evtData);
   1517             else
   1518                 copyTripleSamples(sensor, evtData);
   1519             break;
   1520         default:
   1521             return;
   1522         }
   1523     }
   1524 
   1525     nanohubPrefetchTx(getSensorInterrupt(sensor), mWakeupBlocks, mNonWakeupBlocks);
   1526 
   1527     if (sensor->oneshot) {
   1528         sensorRelease(mHostIntfTid, sensor->sensorHandle);
   1529         osEventUnsubscribe(mHostIntfTid, evtType);
   1530         sensor->sensorHandle = 0;
   1531         sensor->oneshot = false;
   1532     }
   1533 }
   1534 
   1535 static void onEvtSensorDataInactive(struct ActiveSensor *sensor, uint32_t evtType, const void* evtData)
   1536 {
   1537     if (evtData != SENSOR_DATA_EVENT_FLUSH) {
   1538         // handle bias data which can be generated for sensors that are
   1539         // not currently requested by the AP
   1540         switch (sensor->numAxis) {
   1541         case NUM_AXIS_THREE:
   1542             if (((const struct TripleAxisDataEvent *)evtData)->samples[0].firstSample.biasPresent) {
   1543                 copyTripleSamplesBias(sensor, evtData);
   1544                 nanohubPrefetchTx(HOSTINTF_MAX_INTERRUPTS, mWakeupBlocks, mNonWakeupBlocks);
   1545             }
   1546             break;
   1547         }
   1548     }
   1549 }
   1550 
   1551 static void onEvtSensorData(uint32_t evtType, const void* evtData)
   1552 {
   1553     if (evtType > EVT_NO_FIRST_SENSOR_EVENT && evtType < EVT_NO_SENSOR_CONFIG_EVENT) {
   1554         struct ActiveSensor *sensor = getActiveSensorByType(evtType & 0xFF);
   1555         if (sensor) {
   1556             if (sensor->sensorHandle)
   1557                 onEvtSensorDataActive(sensor, evtType, evtData);
   1558             else
   1559                 onEvtSensorDataInactive(sensor, evtType, evtData);
   1560         }
   1561     }
   1562 }
   1563 
   1564 static void hostIntfHandleEvent(uint32_t evtType, const void* evtData)
   1565 {
   1566     switch (EVENT_GET_EVENT(evtType)) {
   1567     case EVT_APP_START:
   1568         onEvtAppStart(evtData);
   1569         break;
   1570     case EVT_APP_TO_HOST:
   1571         onEvtAppToHost(evtData);
   1572         break;
   1573     case EVT_APP_TO_HOST_CHRE:
   1574         onEvtAppToHostChre(evtData);
   1575         break;
   1576 #ifdef LEGACY_HAL_ENABLED
   1577     case EVT_APP_FROM_HOST:
   1578         onEvtAppFromHost(evtData);
   1579         break;
   1580 #endif
   1581     case EVT_APP_FROM_HOST_CHRE:
   1582         onEvtAppFromHostChre(evtData);
   1583         break;
   1584 #ifdef DEBUG_LOG_EVT
   1585     case EVT_DEBUG_LOG:
   1586         onEvtDebugLog(evtData);
   1587         break;
   1588 #endif
   1589     case EVT_LATENCY_TIMER:
   1590         onEvtLatencyTimer(evtData);
   1591         break;
   1592     case EVT_NO_SENSOR_CONFIG_EVENT:
   1593         onEvtNoSensorConfigEvent(evtData);
   1594         break;
   1595     case EVT_APP_TO_SENSOR_HAL_DATA:
   1596         onEvtAppToSensorHalData(evtData);
   1597         break;
   1598     default:
   1599         onEvtSensorData(EVENT_GET_EVENT(evtType), evtData);
   1600         break;
   1601     }
   1602 }
   1603 
   1604 void hostIntfCopyInterrupts(void *dst, uint32_t numBits)
   1605 {
   1606     if (mInterrupt->numBits != numBits)
   1607         return;
   1608 
   1609     atomicBitsetBulkRead(mInterrupt, dst, numBits);
   1610 }
   1611 
   1612 void hostIntfClearInterrupts()
   1613 {
   1614     uint32_t i;
   1615 
   1616     for (i = 0; i < HOSTINTF_MAX_INTERRUPTS; i++) {
   1617         if (atomicBitsetGetBit(mInterrupt, i))
   1618             hostIntfClearInterrupt(i);
   1619     }
   1620 }
   1621 
   1622 void hostIntfSetInterrupt(uint32_t bit)
   1623 {
   1624     uint64_t state = cpuIntsOff();
   1625     if (mHostIntfTid) {
   1626         if (!atomicBitsetGetBit(mInterrupt, bit)) {
   1627             atomicBitsetSetBit(mInterrupt, bit);
   1628             if (!atomicBitsetGetBit(mInterruptMask, bit)) {
   1629                 if (mInterruptCntWkup++ == 0)
   1630                     apIntSet(true);
   1631             } else {
   1632                 if (mInterruptCntNonWkup++ == 0)
   1633                     apIntSet(false);
   1634             }
   1635         }
   1636     }
   1637     cpuIntsRestore(state);
   1638 }
   1639 
   1640 bool hostIntfGetInterrupt(uint32_t bit)
   1641 {
   1642     return atomicBitsetGetBit(mInterrupt, bit);
   1643 }
   1644 
   1645 void hostIntfClearInterrupt(uint32_t bit)
   1646 {
   1647     uint64_t state = cpuIntsOff();
   1648     if (mHostIntfTid) {
   1649         if (atomicBitsetGetBit(mInterrupt, bit)) {
   1650             atomicBitsetClearBit(mInterrupt, bit);
   1651             if (!atomicBitsetGetBit(mInterruptMask, bit)) {
   1652                 if (--mInterruptCntWkup == 0)
   1653                     apIntClear(true);
   1654             } else {
   1655                 if (--mInterruptCntNonWkup == 0)
   1656                     apIntClear(false);
   1657             }
   1658         }
   1659     }
   1660     cpuIntsRestore(state);
   1661 }
   1662 
   1663 void hostIntfSetInterruptMask(uint32_t bit)
   1664 {
   1665     uint64_t state = cpuIntsOff();
   1666     if (mHostIntfTid) {
   1667         if (!atomicBitsetGetBit(mInterruptMask, bit)) {
   1668             atomicBitsetSetBit(mInterruptMask, bit);
   1669             if (atomicBitsetGetBit(mInterrupt, bit)) {
   1670                 if (--mInterruptCntWkup == 0)
   1671                     apIntClear(true);
   1672                 if (mInterruptCntNonWkup++ == 0)
   1673                     apIntSet(false);
   1674             }
   1675         }
   1676     }
   1677     cpuIntsRestore(state);
   1678 }
   1679 
   1680 bool hostIntfGetInterruptMask(uint32_t bit)
   1681 {
   1682     return atomicBitsetGetBit(mInterruptMask, bit);
   1683 }
   1684 
   1685 void hostIntfClearInterruptMask(uint32_t bit)
   1686 {
   1687     uint64_t state = cpuIntsOff();
   1688     if (mHostIntfTid) {
   1689         if (atomicBitsetGetBit(mInterruptMask, bit)) {
   1690             atomicBitsetClearBit(mInterruptMask, bit);
   1691             if (atomicBitsetGetBit(mInterrupt, bit)) {
   1692                 if (mInterruptCntWkup++ == 0)
   1693                     apIntSet(true);
   1694                 if (--mInterruptCntNonWkup == 0)
   1695                     apIntClear(false);
   1696             }
   1697         }
   1698     }
   1699     cpuIntsRestore(state);
   1700 }
   1701 
   1702 INTERNAL_CHRE_APP_INIT(APP_ID_MAKE(NANOHUB_VENDOR_GOOGLE, 0), 0, hostIntfRequest, hostIntfRelease, hostIntfHandleEvent);
   1703