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 <string.h> 19 #include <stdint.h> 20 #include <sys/endian.h> 21 22 #include <variant/inc/variant.h> 23 #include <eventnums.h> 24 25 #include <plat/inc/taggedPtr.h> 26 #include <plat/inc/bl.h> 27 #include <plat/inc/plat.h> 28 29 #include <nanohub/crc.h> 30 #include <nanohub/rsa.h> 31 32 #include <atomicBitset.h> 33 #include <atomic.h> 34 #include <hostIntf.h> 35 #include <hostIntf_priv.h> 36 #include <nanohubCommand.h> 37 #include <nanohubPacket.h> 38 #include <eeData.h> 39 #include <seos.h> 40 #include <util.h> 41 #include <mpu.h> 42 #include <heap.h> 43 #include <slab.h> 44 #include <sensType.h> 45 #include <timer.h> 46 #include <appSec.h> 47 #include <cpu.h> 48 #include <cpu/inc/cpuMath.h> 49 #include <algos/ap_hub_sync.h> 50 51 #define NANOHUB_COMMAND(_reason, _fastHandler, _handler, _minReqType, _maxReqType) \ 52 { .reason = _reason, .fastHandler = _fastHandler, .handler = _handler, \ 53 .minDataLen = sizeof(_minReqType), .maxDataLen = sizeof(_maxReqType) } 54 55 #define NANOHUB_HAL_COMMAND(_msg, _handler) \ 56 { .msg = _msg, .handler = _handler } 57 58 // maximum number of bytes to feed into appSecRxData at once 59 // The bigger the number, the more time we block other event processing 60 // appSecRxData only feeds 16 bytes at a time into writeCbk, so large 61 // numbers don't buy us that much 62 #define MAX_APP_SEC_RX_DATA_LEN 64 63 64 #define REQUIRE_SIGNED_IMAGE true 65 #define DEBUG_APHUB_TIME_SYNC false 66 67 #if DEBUG_APHUB_TIME_SYNC 68 static void syncDebugAdd(uint64_t, uint64_t); 69 #endif 70 71 struct DownloadState 72 { 73 struct AppSecState *appSecState; 74 uint32_t size; // document size, as reported by client 75 uint32_t srcOffset; // bytes received from client 76 uint32_t dstOffset; // bytes sent to flash 77 struct AppHdr *start; // start of flash segment, where to write 78 uint32_t crc; // document CRC-32, as reported by client 79 uint32_t srcCrc; // current state of CRC-32 we generate from input 80 uint8_t data[NANOHUB_PACKET_PAYLOAD_MAX]; 81 uint8_t len; 82 uint8_t lenLeft; 83 uint8_t chunkReply; 84 bool erase; 85 bool eraseScheduled; 86 }; 87 88 static struct DownloadState *mDownloadState; 89 static AppSecErr mAppSecStatus; 90 static struct SlabAllocator *mEventSlab; 91 static struct HostIntfDataBuffer mTxCurr, mTxNext; 92 static uint8_t mTxCurrLength, mTxNextLength; 93 static uint8_t mPrefetchActive, mPrefetchTx; 94 static uint32_t mTxWakeCnt[2]; 95 static struct ApHubSync mTimeSync; 96 97 static inline bool isSensorEvent(uint32_t evtType) 98 { 99 return evtType > EVT_NO_FIRST_SENSOR_EVENT && evtType <= EVT_NO_FIRST_SENSOR_EVENT + SENS_TYPE_LAST_USER; 100 } 101 102 static void slabFree(void *ptr) 103 { 104 slabAllocatorFree(mEventSlab, ptr); 105 } 106 107 void nanohubInitCommand(void) 108 { 109 mEventSlab = slabAllocatorNew(NANOHUB_PACKET_PAYLOAD_MAX-sizeof(__le32), 4, 2); 110 } 111 112 static uint32_t getOsHwVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 113 { 114 struct NanohubOsHwVersionsResponse *resp = tx; 115 resp->hwType = htole16(platHwType()); 116 resp->hwVer = htole16(platHwVer()); 117 resp->blVer = htole16(platBlVer()); 118 resp->osVer = htole16(OS_VER); 119 resp->variantVer = htole32(VARIANT_VER); 120 121 return sizeof(*resp); 122 } 123 124 static uint32_t getAppVersion(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 125 { 126 struct NanohubAppVersionsRequest *req = rx; 127 struct NanohubAppVersionsResponse *resp = tx; 128 uint32_t appIdx, appVer, appSize; 129 130 if (osAppInfoById(le64toh(req->appId), &appIdx, &appVer, &appSize)) { 131 resp->appVer = htole32(appVer); 132 return sizeof(*resp); 133 } 134 135 return 0; 136 } 137 138 static uint32_t queryAppInfo(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 139 { 140 struct NanohubAppInfoRequest *req = rx; 141 struct NanohubAppInfoResponse *resp = tx; 142 uint64_t appId; 143 uint32_t appVer, appSize; 144 145 if (osAppInfoByIndex(le32toh(req->appIdx), &appId, &appVer, &appSize)) { 146 resp->appId = htole64(appId); 147 resp->appVer = htole32(appVer); 148 resp->appSize = htole32(appSize); 149 return sizeof(*resp); 150 } 151 152 return 0; 153 } 154 155 static AppSecErr writeCbk(const void *data, uint32_t len) 156 { 157 AppSecErr ret = APP_SEC_BAD; 158 159 if (osWriteShared((uint8_t*)(mDownloadState->start) + mDownloadState->dstOffset, data, len)) { 160 ret = APP_SEC_NO_ERROR; 161 mDownloadState->dstOffset += len; 162 } 163 164 return ret; 165 } 166 167 static AppSecErr pubKeyFindCbk(const uint32_t *gotKey, bool *foundP) 168 { 169 const uint32_t *ptr; 170 uint32_t numKeys, i; 171 172 *foundP = false; 173 ptr = BL.blGetPubKeysInfo(&numKeys); 174 for (i = 0; ptr && i < numKeys; i++, ptr += RSA_LIMBS) { 175 if (!memcmp(gotKey, ptr, RSA_BYTES)) { 176 *foundP = true; 177 break; 178 } 179 } 180 181 return APP_SEC_NO_ERROR; 182 } 183 184 static AppSecErr osSecretKeyLookup(uint64_t keyId, void *keyBuf) 185 { 186 struct SeosEedataEncrKeyData kd; 187 void *state = NULL; 188 189 while(1) { 190 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 191 192 if (!eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state)) 193 break; 194 195 if (sz == sizeof(struct SeosEedataEncrKeyData) && kd.keyID == keyId) { 196 if (keyBuf) 197 memcpy(keyBuf, kd.key, sizeof(kd.key)); 198 return APP_SEC_NO_ERROR; 199 } 200 } 201 202 return APP_SEC_KEY_NOT_FOUND; 203 } 204 205 static AppSecErr osSecretKeyDelete(uint64_t keyId) 206 { 207 struct SeosEedataEncrKeyData kd; 208 void *state = NULL; 209 bool good = true; 210 int count = 0; 211 212 while(1) { 213 uint32_t sz = sizeof(struct SeosEedataEncrKeyData); 214 void *addr = eeDataGetAllVersions(EE_DATA_NAME_ENCR_KEY, &kd, &sz, &state); 215 216 if (!addr) 217 break; 218 219 if (sz == sizeof(kd) && kd.keyID == keyId) { 220 good = eeDataEraseOldVersion(EE_DATA_NAME_ENCR_KEY, addr) && good; 221 count++; 222 } 223 } 224 225 return count == 0 ? APP_SEC_KEY_NOT_FOUND : good ? APP_SEC_NO_ERROR : APP_SEC_BAD; 226 } 227 228 static AppSecErr osSecretKeyAdd(uint64_t keyId, void *keyBuf) 229 { 230 struct SeosEedataEncrKeyData kd; 231 232 // do not add key if it already exists 233 if (osSecretKeyLookup(keyId, NULL) != APP_SEC_KEY_NOT_FOUND) 234 return APP_SEC_BAD; 235 236 memcpy(&kd.key, keyBuf, 32); 237 kd.keyID = keyId; 238 239 return eeDataSet(EE_DATA_NAME_ENCR_KEY, &kd, sizeof(kd)) ? APP_SEC_NO_ERROR : APP_SEC_BAD; 240 } 241 242 static void freeDownloadState() 243 { 244 if (mDownloadState->appSecState) 245 appSecDeinit(mDownloadState->appSecState); 246 heapFree(mDownloadState); 247 mDownloadState = NULL; 248 } 249 250 static void resetDownloadState(bool initial) 251 { 252 bool doCreate = true; 253 254 mAppSecStatus = APP_SEC_NO_ERROR; 255 if (mDownloadState->appSecState) 256 appSecDeinit(mDownloadState->appSecState); 257 mDownloadState->appSecState = appSecInit(writeCbk, pubKeyFindCbk, osSecretKeyLookup, REQUIRE_SIGNED_IMAGE); 258 mDownloadState->srcOffset = 0; 259 mDownloadState->srcCrc = ~0; 260 if (!initial) { 261 // if no data was written, we can reuse the same segment 262 if (mDownloadState->dstOffset) 263 osAppSegmentClose(mDownloadState->start, mDownloadState->dstOffset, SEG_ST_ERASED); 264 else 265 doCreate = false; 266 } 267 if (doCreate) 268 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 269 if (!mDownloadState->start) 270 mDownloadState->erase = true; 271 mDownloadState->dstOffset = 0; 272 } 273 274 static bool doStartFirmwareUpload(struct NanohubStartFirmwareUploadRequest *req) 275 { 276 if (!mDownloadState) { 277 mDownloadState = heapAlloc(sizeof(struct DownloadState)); 278 279 if (!mDownloadState) 280 return false; 281 else 282 memset(mDownloadState, 0x00, sizeof(struct DownloadState)); 283 } 284 285 mDownloadState->size = le32toh(req->size); 286 mDownloadState->crc = le32toh(req->crc); 287 mDownloadState->chunkReply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 288 resetDownloadState(true); 289 290 return true; 291 } 292 293 static uint32_t startFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 294 { 295 struct NanohubStartFirmwareUploadRequest *req = rx; 296 struct NanohubStartFirmwareUploadResponse *resp = tx; 297 298 resp->accepted = doStartFirmwareUpload(req); 299 300 return sizeof(*resp); 301 } 302 303 static void deferredUpdateOs(void *cookie) 304 { 305 const struct AppHdr *app = cookie; 306 struct OsUpdateHdr *os = (struct OsUpdateHdr *)(&(app->hdr) + 1); 307 uint32_t uploadStatus = OS_UPDT_HDR_CHECK_FAILED; 308 uint8_t marker = OS_UPDT_MARKER_DOWNLOADED; 309 struct Segment *seg = osGetSegment(app); 310 uint32_t segSize = osSegmentGetSize(seg); 311 312 osLog(LOG_INFO, "%s: checking OS image @ %p\n", __func__, os); 313 // some sanity checks before asking BL to do image lookup 314 hostIntfSetBusy(true); 315 if (segSize >= (sizeof(*app) + sizeof(*os)) && segSize > os->size) { 316 if (osWriteShared(&os->marker, &marker, sizeof(os->marker))) 317 uploadStatus = BL.blVerifyOsUpdate(); 318 else 319 osLog(LOG_ERROR, "%s: could not set marker on OS image\n", __func__); 320 } 321 hostIntfSetBusy(false); 322 osLog(LOG_INFO, "%s: status=%" PRIu32 "\n", __func__, uploadStatus); 323 } 324 325 static AppSecErr updateKey(const struct AppHdr *app) 326 { 327 AppSecErr ret; 328 struct KeyInfo *ki = (struct KeyInfo *)(&(app->hdr) + 1); 329 uint8_t *data = (uint8_t *)(ki + 1); 330 uint64_t keyId = KEY_ID_MAKE(APP_ID_GET_VENDOR(app->hdr.appId), ki->id); 331 const char *op; 332 333 if ((app->hdr.fwFlags & FL_KEY_HDR_DELETE) != 0) { 334 // removing existing key 335 ret = osSecretKeyDelete(keyId); 336 op = "Removing"; 337 } else { 338 // adding new key 339 ret = osSecretKeyAdd(keyId, data); 340 op = "Adding"; 341 } 342 osLog(LOG_INFO, "%s: %s key: id=%016" PRIX64 "; ret=%" PRIu32 "\n", 343 __func__, op, keyId, ret); 344 345 return ret; 346 } 347 348 static uint32_t appSecErrToNanohubReply(AppSecErr status) 349 { 350 uint32_t reply; 351 352 switch (status) { 353 case APP_SEC_NO_ERROR: 354 reply = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 355 break; 356 case APP_SEC_KEY_NOT_FOUND: 357 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_KEY_NOT_FOUND; 358 break; 359 case APP_SEC_HEADER_ERROR: 360 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_HEADER_ERROR; 361 break; 362 case APP_SEC_TOO_MUCH_DATA: 363 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_MUCH_DATA; 364 break; 365 case APP_SEC_TOO_LITTLE_DATA: 366 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_TOO_LITTLE_DATA; 367 break; 368 case APP_SEC_SIG_VERIFY_FAIL: 369 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_VERIFY_FAIL; 370 break; 371 case APP_SEC_SIG_DECODE_FAIL: 372 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_DECODE_FAIL; 373 break; 374 case APP_SEC_SIG_ROOT_UNKNOWN: 375 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_SIG_ROOT_UNKNOWN; 376 break; 377 case APP_SEC_MEMORY_ERROR: 378 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_MEMORY_ERROR; 379 break; 380 case APP_SEC_INVALID_DATA: 381 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_INVALID_DATA; 382 break; 383 case APP_SEC_VERIFY_FAILED: 384 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_VERIFY_FAILED; 385 break; 386 default: 387 reply = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 388 break; 389 } 390 return reply; 391 } 392 393 static uint32_t firmwareFinish(bool valid) 394 { 395 struct AppHdr *app; 396 struct Segment *storageSeg; 397 uint32_t segState; 398 uint32_t ret = NANOHUB_FIRMWARE_UPLOAD_SUCCESS; 399 400 if (!mDownloadState) { 401 ret = appSecErrToNanohubReply(mAppSecStatus); 402 osLog(LOG_INFO, "%s: no DL status; decoding secure status: %" PRIu32 "\n", __func__, ret); 403 return ret; 404 } 405 406 app = mDownloadState->start; 407 storageSeg = osGetSegment(app); 408 409 if (mAppSecStatus == APP_SEC_NO_ERROR && valid) { 410 osLog(LOG_INFO, "%s: Secure verification passed\n", __func__); 411 if (storageSeg->state != SEG_ST_RESERVED || 412 mDownloadState->size < sizeof(struct FwCommonHdr) || 413 app->hdr.magic != APP_HDR_MAGIC || 414 app->hdr.fwVer != APP_HDR_VER_CUR) { 415 segState = SEG_ST_ERASED; 416 osLog(LOG_INFO, "%s: Header verification failed\n", __func__); 417 } else { 418 segState = SEG_ST_VALID; 419 } 420 } else { 421 segState = SEG_ST_ERASED; 422 osLog(LOG_INFO, "%s: Secure verification failed: valid=%d; status=%" PRIu32 "\n", __func__, valid, mAppSecStatus); 423 } 424 425 if (!osAppSegmentClose(app, mDownloadState->dstOffset, segState)) { 426 osLog(LOG_INFO, "%s: Failed to close segment\n", __func__); 427 valid = false; 428 } else { 429 segState = osAppSegmentGetState(app); 430 valid = (segState == SEG_ST_VALID); 431 } 432 osLog(LOG_INFO, "Loaded %s image type %" PRIu8 ": %" PRIu32 433 " bytes @ %p; state=%02" PRIX32 "\n", 434 valid ? "valid" : "invalid", 435 app->hdr.payInfoType, mDownloadState->size, 436 mDownloadState->start, segState); 437 438 freeDownloadState(); // no more access to mDownloadState 439 440 if (!valid) 441 ret = NANOHUB_FIRMWARE_UPLOAD_APP_SEC_BAD; 442 443 // take extra care about some special payload types 444 if (ret == NANOHUB_FIRMWARE_UPLOAD_SUCCESS) { 445 switch(app->hdr.payInfoType) { 446 case LAYOUT_OS: 447 osLog(LOG_INFO, "Performing OS update\n"); 448 // we want to give this message a chance to reach host before we start erasing stuff 449 osDefer(deferredUpdateOs, (void*)app, false); 450 break; 451 case LAYOUT_KEY: 452 ret = appSecErrToNanohubReply(updateKey(app)); 453 break; 454 } 455 } 456 457 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS || (app->hdr.fwFlags & FL_APP_HDR_VOLATILE)) { 458 if ((app->hdr.fwFlags & FL_APP_HDR_SECURE)) 459 osAppWipeData((struct AppHdr*)app); 460 osAppSegmentSetState(app, SEG_ST_ERASED); 461 } 462 463 // if any error happened after we downloaded and verified image, we say it is unknown fault 464 // we don't have download status, so e have to save returned value in secure status field, because 465 // host may request the same status multiple times 466 if (ret != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 467 mAppSecStatus = APP_SEC_BAD; 468 469 return ret; 470 } 471 472 static void firmwareErase(void *cookie) 473 { 474 if (mDownloadState->erase == true) { 475 osLog(LOG_INFO, "%s: erasing shared area\n", __func__); 476 osEraseShared(); 477 mDownloadState->start = osAppSegmentCreate(mDownloadState->size); 478 if (!mDownloadState->start) 479 firmwareFinish(false); 480 mDownloadState->erase = false; 481 hostIntfSetInterrupt(NANOHUB_INT_CMD_WAIT); 482 } 483 mDownloadState->eraseScheduled = false; 484 } 485 486 static void firmwareWrite(void *cookie) 487 { 488 bool valid; 489 bool finished = false; 490 struct NanohubHalContUploadTx *resp = cookie; 491 // only check crc when cookie is NULL (write came from kernel, not HAL) 492 bool checkCrc = !cookie; 493 494 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME) { 495 mAppSecStatus = appSecDoSomeProcessing(mDownloadState->appSecState); 496 } else if (mDownloadState->lenLeft) { 497 const uint8_t *data = mDownloadState->data + mDownloadState->len - mDownloadState->lenLeft; 498 uint32_t len = mDownloadState->lenLeft, lenLeft, lenRem = 0; 499 500 if (len > MAX_APP_SEC_RX_DATA_LEN) { 501 lenRem = len - MAX_APP_SEC_RX_DATA_LEN; 502 len = MAX_APP_SEC_RX_DATA_LEN; 503 } 504 505 mAppSecStatus = appSecRxData(mDownloadState->appSecState, data, len, &lenLeft); 506 mDownloadState->lenLeft = lenLeft + lenRem; 507 } 508 509 valid = (mAppSecStatus == APP_SEC_NO_ERROR); 510 if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 511 osDefer(firmwareWrite, cookie, false); 512 return; 513 } else if (valid) { 514 if (mDownloadState->srcOffset == mDownloadState->size) { 515 finished = true; 516 valid = !checkCrc || mDownloadState->crc == ~mDownloadState->srcCrc; 517 } else if (mDownloadState->srcOffset > mDownloadState->size) { 518 valid = false; 519 } 520 } 521 if (!valid) 522 finished = true; 523 if (finished) { 524 if (firmwareFinish(valid) != NANOHUB_FIRMWARE_UPLOAD_SUCCESS) 525 valid = false; 526 } 527 if (resp) { 528 resp->success = valid; 529 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 530 } 531 } 532 533 static uint32_t doFirmwareChunk(uint8_t *data, uint32_t offset, uint32_t len, void *cookie) 534 { 535 uint32_t reply; 536 537 if (!mDownloadState) { 538 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 539 } else if (mAppSecStatus == APP_SEC_NEED_MORE_TIME || mDownloadState->lenLeft) { 540 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESEND; 541 } else if (mDownloadState->chunkReply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 542 reply = mDownloadState->chunkReply; 543 firmwareFinish(false); 544 } else { 545 if (mDownloadState->erase == true) { 546 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_WAIT; 547 if (!mDownloadState->eraseScheduled) 548 mDownloadState->eraseScheduled = osDefer(firmwareErase, NULL, false); 549 } else if (!mDownloadState->start) { 550 // this means we can't allocate enough space even after we did erase 551 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 552 firmwareFinish(false); 553 } else if (offset != mDownloadState->srcOffset) { 554 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_RESTART; 555 resetDownloadState(false); 556 } else { 557 if (!cookie) 558 mDownloadState->srcCrc = crc32(data, len, mDownloadState->srcCrc); 559 mDownloadState->srcOffset += len; 560 memcpy(mDownloadState->data, data, len); 561 mDownloadState->lenLeft = mDownloadState->len = len; 562 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED; 563 osDefer(firmwareWrite, cookie, false); 564 } 565 } 566 567 return reply; 568 } 569 570 static uint32_t firmwareChunk(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 571 { 572 struct NanohubFirmwareChunkRequest *req = rx; 573 struct NanohubFirmwareChunkResponse *resp = tx; 574 uint32_t offset = le32toh(req->offset); 575 uint8_t len = rx_len - sizeof(req->offset); 576 577 resp->chunkReply = doFirmwareChunk(req->data, offset, len, NULL); 578 579 return sizeof(*resp); 580 } 581 582 static uint32_t doFinishFirmwareUpload() 583 { 584 uint32_t reply; 585 586 if (!mDownloadState) { 587 reply = appSecErrToNanohubReply(mAppSecStatus); 588 } else if (mDownloadState->srcOffset == mDownloadState->size) { 589 reply = NANOHUB_FIRMWARE_UPLOAD_PROCESSING; 590 } else { 591 reply = firmwareFinish(false); 592 } 593 594 return reply; 595 } 596 597 static uint32_t finishFirmwareUpload(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 598 { 599 struct NanohubFinishFirmwareUploadResponse *resp = tx; 600 resp->uploadReply = doFinishFirmwareUpload(); 601 if (resp->uploadReply != NANOHUB_FIRMWARE_UPLOAD_PROCESSING) 602 osLog(LOG_INFO, "%s: reply=%" PRIu8 "\n", __func__, resp->uploadReply); 603 return sizeof(*resp); 604 } 605 606 static uint32_t getInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 607 { 608 struct NanohubGetInterruptRequest *req = rx; 609 struct NanohubGetInterruptResponse *resp = tx; 610 int i; 611 612 if (rx_len == sizeof(struct NanohubGetInterruptRequest)) { 613 for (i = 0; i < HOSTINTF_MAX_INTERRUPTS; i++) { 614 if (req->clear[i/32] & (1UL << (i & 31))) 615 hostIntfClearInterrupt(i); 616 } 617 } 618 619 hostIntfCopyInterrupts(resp->interrupts, HOSTINTF_MAX_INTERRUPTS); 620 621 return sizeof(*resp); 622 } 623 624 static uint32_t maskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 625 { 626 struct NanohubMaskInterruptRequest *req = rx; 627 struct NanohubMaskInterruptResponse *resp = tx; 628 629 hostIntfSetInterruptMask(req->interrupt); 630 631 resp->accepted = true; 632 return sizeof(*resp); 633 } 634 635 static uint32_t unmaskInterrupt(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 636 { 637 struct NanohubUnmaskInterruptRequest *req = rx; 638 struct NanohubUnmaskInterruptResponse *resp = tx; 639 640 hostIntfClearInterruptMask(req->interrupt); 641 642 resp->accepted = true; 643 return sizeof(*resp); 644 } 645 646 static void addDelta(struct ApHubSync *sync, uint64_t apTime, uint64_t hubTime) 647 { 648 #if DEBUG_APHUB_TIME_SYNC 649 syncDebugAdd(apTime, hubTime); 650 #endif 651 apHubSyncAddDelta(sync, apTime, hubTime); 652 } 653 654 static int64_t getAvgDelta(struct ApHubSync *sync) 655 { 656 return apHubSyncGetDelta(sync, sensorGetTime()); 657 } 658 659 static int fillBuffer(void *tx, uint32_t totLength, uint32_t *wakeup, uint32_t *nonwakeup) 660 { 661 struct HostIntfDataBuffer *packet = &mTxNext; 662 struct HostIntfDataBuffer *firstPacket = tx; 663 uint8_t *buf = tx; 664 uint32_t length; 665 uint32_t prevWakeup, prevNonWakeup; 666 667 prevWakeup = *wakeup; 668 prevNonWakeup = *nonwakeup; 669 670 while (hostIntfPacketDequeue(&mTxNext, wakeup, nonwakeup)) { 671 length = packet->length + sizeof(packet->evtType); 672 if (packet->sensType == SENS_TYPE_INVALID) { 673 switch (packet->dataType) { 674 case HOSTINTF_DATA_TYPE_APP_TO_HOST: 675 packet->evtType = htole32(EVT_APP_TO_HOST); 676 break; 677 case HOSTINTF_DATA_TYPE_RESET_REASON: 678 packet->evtType = htole32(EVT_RESET_REASON); 679 break; 680 #ifdef DEBUG_LOG_EVT 681 case HOSTINTF_DATA_TYPE_LOG: 682 packet->evtType = htole32(HOST_EVT_DEBUG_LOG); 683 break; 684 #endif 685 default: 686 packet->evtType = htole32(0x00000000); 687 break; 688 } 689 } else { 690 packet->evtType = htole32(EVT_NO_FIRST_SENSOR_EVENT + packet->sensType); 691 if (packet->referenceTime) 692 packet->referenceTime += getAvgDelta(&mTimeSync); 693 694 if (*wakeup > 0) 695 packet->firstSample.interrupt = NANOHUB_INT_WAKEUP; 696 } 697 698 if ((!totLength || (isSensorEvent(firstPacket->evtType) && isSensorEvent(packet->evtType))) && totLength + length <= sizeof(struct HostIntfDataBuffer)) { 699 memcpy(buf + totLength, &mTxNext, length); 700 totLength += length; 701 if (isSensorEvent(packet->evtType) && packet->firstSample.interrupt == NANOHUB_INT_WAKEUP) 702 firstPacket->firstSample.interrupt = NANOHUB_INT_WAKEUP; 703 } else { 704 mTxNextLength = length; 705 *wakeup = prevWakeup; 706 *nonwakeup = prevNonWakeup; 707 break; 708 } 709 710 prevWakeup = *wakeup; 711 prevNonWakeup = *nonwakeup; 712 } 713 714 return totLength; 715 } 716 717 static void updateInterrupts(void) 718 { 719 uint32_t wakeup = atomicRead32bits(&mTxWakeCnt[0]); 720 uint32_t nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 721 bool wakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_WAKEUP); 722 bool nonwakeupStatus = hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP); 723 724 if (!wakeup && wakeupStatus) 725 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 726 else if (wakeup && !wakeupStatus) 727 hostIntfSetInterrupt(NANOHUB_INT_WAKEUP); 728 729 if (!nonwakeup && nonwakeupStatus) 730 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 731 else if (nonwakeup && !nonwakeupStatus) 732 hostIntfSetInterrupt(NANOHUB_INT_NONWAKEUP); 733 } 734 735 void nanohubPrefetchTx(uint32_t interrupt, uint32_t wakeup, uint32_t nonwakeup) 736 { 737 uint64_t state; 738 739 if (wakeup < atomicRead32bits(&mTxWakeCnt[0])) 740 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 741 742 if (nonwakeup < atomicRead32bits(&mTxWakeCnt[1])) 743 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 744 745 if (interrupt == HOSTINTF_MAX_INTERRUPTS && !hostIntfGetInterrupt(NANOHUB_INT_WAKEUP) && !hostIntfGetInterrupt(NANOHUB_INT_NONWAKEUP)) 746 return; 747 748 atomicWriteByte(&mPrefetchActive, 1); 749 750 if (interrupt < HOSTINTF_MAX_INTERRUPTS) 751 hostIntfSetInterrupt(interrupt); 752 753 do { 754 if (atomicReadByte(&mTxCurrLength) == 0 && mTxNextLength > 0) { 755 memcpy(&mTxCurr, &mTxNext, mTxNextLength); 756 atomicWriteByte(&mTxCurrLength, mTxNextLength); 757 mTxNextLength = 0; 758 } 759 760 if (mTxNextLength == 0) { 761 atomicWriteByte(&mTxCurrLength, fillBuffer(&mTxCurr, atomicReadByte(&mTxCurrLength), &wakeup, &nonwakeup)); 762 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 763 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 764 } 765 766 atomicWriteByte(&mPrefetchActive, 0); 767 768 if (atomicReadByte(&mPrefetchTx)) { 769 state = cpuIntsOff(); 770 771 // interrupt occured during this call 772 // take care of it 773 hostIntfTxAck(&mTxCurr, atomicReadByte(&mTxCurrLength)); 774 atomicWriteByte(&mPrefetchTx, 0); 775 atomicWriteByte(&mTxCurrLength, 0); 776 777 cpuIntsRestore(state); 778 779 updateInterrupts(); 780 } else { 781 break; 782 } 783 } while (mTxNextLength > 0); 784 } 785 786 static void nanohubPrefetchTxDefer(void *cookie) 787 { 788 nanohubPrefetchTx(HOSTINTF_MAX_INTERRUPTS, 0, 0); 789 } 790 791 static uint32_t readEventFast(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 792 { 793 struct NanohubReadEventRequest *req = rx; 794 uint8_t ret = 0; 795 796 if (atomicReadByte(&mPrefetchActive)) { 797 atomicWriteByte(&mPrefetchTx, 1); 798 return NANOHUB_FAST_DONT_ACK; 799 } else { 800 if ((ret = atomicReadByte(&mTxCurrLength))) { 801 addDelta(&mTimeSync, req->apBootTime, timestamp); 802 803 memcpy(tx, &mTxCurr, ret); 804 atomicWriteByte(&mTxCurrLength, 0); 805 806 updateInterrupts(); 807 osDefer(nanohubPrefetchTxDefer, NULL, true); 808 } else { 809 return NANOHUB_FAST_UNHANDLED_ACK; 810 } 811 } 812 813 return ret; 814 } 815 816 static uint32_t readEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 817 { 818 struct NanohubReadEventRequest *req = rx; 819 uint8_t *buf = tx; 820 uint32_t length, wakeup, nonwakeup; 821 uint32_t totLength = 0; 822 823 addDelta(&mTimeSync, req->apBootTime, timestamp); 824 825 if ((totLength = atomicReadByte(&mTxCurrLength))) { 826 memcpy(tx, &mTxCurr, totLength); 827 atomicWriteByte(&mTxCurrLength, 0); 828 updateInterrupts(); 829 return totLength; 830 } 831 832 wakeup = atomicRead32bits(&mTxWakeCnt[0]); 833 nonwakeup = atomicRead32bits(&mTxWakeCnt[1]); 834 835 if (mTxNextLength > 0) { 836 length = mTxNextLength; 837 memcpy(buf, &mTxNext, length); 838 totLength = length; 839 mTxNextLength = 0; 840 } 841 842 totLength = fillBuffer(buf, totLength, &wakeup, &nonwakeup); 843 atomicWrite32bits(&mTxWakeCnt[0], wakeup); 844 atomicWrite32bits(&mTxWakeCnt[1], nonwakeup); 845 846 if (totLength) { 847 updateInterrupts(); 848 } else { 849 hostIntfClearInterrupt(NANOHUB_INT_WAKEUP); 850 hostIntfClearInterrupt(NANOHUB_INT_NONWAKEUP); 851 } 852 853 return totLength; 854 } 855 856 static uint32_t writeEvent(void *rx, uint8_t rx_len, void *tx, uint64_t timestamp) 857 { 858 struct NanohubWriteEventRequest *req = rx; 859 struct NanohubWriteEventResponse *resp = tx; 860 uint8_t *packet; 861 struct HostHubRawPacket *rawPacket; 862 uint32_t tid; 863 EventFreeF free = slabFree; 864 865 if (le32toh(req->evtType) == EVT_APP_FROM_HOST) { 866 rawPacket = (struct HostHubRawPacket *)req->evtData; 867 if (rx_len >= sizeof(req->evtType) + sizeof(struct HostHubRawPacket) && rx_len == sizeof(req->evtType) + sizeof(struct HostHubRawPacket) + rawPacket->dataLen && osTidById(rawPacket->appId, &tid)) { 868 packet = slabAllocatorAlloc(mEventSlab); 869 if (!packet) { 870 packet = heapAlloc(rawPacket->dataLen + 1); 871 free = heapFree; 872 } 873 if (!packet) { 874 resp->accepted = false; 875 } else { 876 packet[0] = rawPacket->dataLen; 877 memcpy(packet + 1, rawPacket + 1, rawPacket->dataLen); 878 resp->accepted = osEnqueuePrivateEvt(EVT_APP_FROM_HOST, packet, free, tid); 879 if (!resp->accepted) 880 free(packet); 881 } 882 } else { 883 resp->accepted = false; 884 } 885 } else { 886 packet = slabAllocatorAlloc(mEventSlab); 887 if (!packet) { 888 packet = heapAlloc(rx_len - sizeof(req->evtType)); 889 free = heapFree; 890 } 891 if (!packet) { 892 resp->accepted = false; 893 } else { 894 memcpy(packet, req->evtData, rx_len - sizeof(req->evtType)); 895 resp->accepted = osEnqueueEvtOrFree(le32toh(req->evtType), packet, free); 896 } 897 } 898 899 return sizeof(*resp); 900 } 901 902 const static struct NanohubCommand mBuiltinCommands[] = { 903 NANOHUB_COMMAND(NANOHUB_REASON_GET_OS_HW_VERSIONS, 904 getOsHwVersion, 905 getOsHwVersion, 906 struct NanohubOsHwVersionsRequest, 907 struct NanohubOsHwVersionsRequest), 908 NANOHUB_COMMAND(NANOHUB_REASON_GET_APP_VERSIONS, 909 NULL, 910 getAppVersion, 911 struct NanohubAppVersionsRequest, 912 struct NanohubAppVersionsRequest), 913 NANOHUB_COMMAND(NANOHUB_REASON_QUERY_APP_INFO, 914 NULL, 915 queryAppInfo, 916 struct NanohubAppInfoRequest, 917 struct NanohubAppInfoRequest), 918 NANOHUB_COMMAND(NANOHUB_REASON_START_FIRMWARE_UPLOAD, 919 NULL, 920 startFirmwareUpload, 921 struct NanohubStartFirmwareUploadRequest, 922 struct NanohubStartFirmwareUploadRequest), 923 NANOHUB_COMMAND(NANOHUB_REASON_FIRMWARE_CHUNK, 924 NULL, 925 firmwareChunk, 926 __le32, 927 struct NanohubFirmwareChunkRequest), 928 NANOHUB_COMMAND(NANOHUB_REASON_FINISH_FIRMWARE_UPLOAD, 929 NULL, 930 finishFirmwareUpload, 931 struct NanohubFinishFirmwareUploadRequest, 932 struct NanohubFinishFirmwareUploadRequest), 933 NANOHUB_COMMAND(NANOHUB_REASON_GET_INTERRUPT, 934 getInterrupt, 935 getInterrupt, 936 0, 937 struct NanohubGetInterruptRequest), 938 NANOHUB_COMMAND(NANOHUB_REASON_MASK_INTERRUPT, 939 maskInterrupt, 940 maskInterrupt, 941 struct NanohubMaskInterruptRequest, 942 struct NanohubMaskInterruptRequest), 943 NANOHUB_COMMAND(NANOHUB_REASON_UNMASK_INTERRUPT, 944 unmaskInterrupt, 945 unmaskInterrupt, 946 struct NanohubUnmaskInterruptRequest, 947 struct NanohubUnmaskInterruptRequest), 948 NANOHUB_COMMAND(NANOHUB_REASON_READ_EVENT, 949 readEventFast, 950 readEvent, 951 struct NanohubReadEventRequest, 952 struct NanohubReadEventRequest), 953 NANOHUB_COMMAND(NANOHUB_REASON_WRITE_EVENT, 954 writeEvent, 955 writeEvent, 956 __le32, 957 struct NanohubWriteEventRequest), 958 }; 959 960 const struct NanohubCommand *nanohubFindCommand(uint32_t packetReason) 961 { 962 uint32_t i; 963 964 for (i = 0; i < ARRAY_SIZE(mBuiltinCommands); i++) { 965 const struct NanohubCommand *cmd = &mBuiltinCommands[i]; 966 if (cmd->reason == packetReason) 967 return cmd; 968 } 969 return NULL; 970 } 971 972 static void halSendMgmtResponse(uint32_t cmd, uint32_t status) 973 { 974 struct NanohubHalMgmtTx *resp; 975 976 resp = heapAlloc(sizeof(*resp)); 977 if (resp) { 978 resp->hdr = (struct NanohubHalHdr) { 979 .appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0), 980 .len = sizeof(*resp) - sizeof(resp->hdr) + sizeof(resp->hdr.msg), 981 .msg = cmd, 982 }; 983 resp->status = htole32(status); 984 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 985 } 986 } 987 988 static void halExtAppsOn(void *rx, uint8_t rx_len) 989 { 990 struct NanohubHalMgmtRx *req = rx; 991 992 halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_ON, osExtAppStartApps(le64toh(req->appId))); 993 } 994 995 static void halExtAppsOff(void *rx, uint8_t rx_len) 996 { 997 struct NanohubHalMgmtRx *req = rx; 998 999 halSendMgmtResponse(NANOHUB_HAL_EXT_APPS_OFF, osExtAppStopApps(le64toh(req->appId))); 1000 } 1001 1002 static void halExtAppDelete(void *rx, uint8_t rx_len) 1003 { 1004 struct NanohubHalMgmtRx *req = rx; 1005 1006 halSendMgmtResponse(NANOHUB_HAL_EXT_APP_DELETE, osExtAppEraseApps(le64toh(req->appId))); 1007 } 1008 1009 static void halQueryMemInfo(void *rx, uint8_t rx_len) 1010 { 1011 } 1012 1013 static void halQueryApps(void *rx, uint8_t rx_len) 1014 { 1015 struct NanohubHalQueryAppsRx *req = rx; 1016 struct NanohubHalQueryAppsTx *resp; 1017 struct NanohubHalHdr *hdr; 1018 uint64_t appId; 1019 uint32_t appVer, appSize; 1020 1021 if (osAppInfoByIndex(le32toh(req->idx), &appId, &appVer, &appSize)) { 1022 resp = heapAlloc(sizeof(*resp)); 1023 resp->hdr.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1024 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1025 resp->hdr.msg = NANOHUB_HAL_QUERY_APPS; 1026 resp->appId = appId; 1027 resp->version = appVer; 1028 resp->flashUse = appSize; 1029 resp->ramUse = 0; 1030 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1031 } else { 1032 hdr = heapAlloc(sizeof(*hdr)); 1033 hdr->appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1034 hdr->len = 1; 1035 hdr->msg = NANOHUB_HAL_QUERY_APPS; 1036 osEnqueueEvtOrFree(EVT_APP_TO_HOST, hdr, heapFree); 1037 } 1038 } 1039 1040 static void halQueryRsaKeys(void *rx, uint8_t rx_len) 1041 { 1042 struct NanohubHalQueryRsaKeysRx *req = rx; 1043 struct NanohubHalQueryRsaKeysTx *resp; 1044 int len = 0; 1045 const uint32_t *ptr; 1046 uint32_t numKeys; 1047 1048 if (!(resp = heapAlloc(sizeof(*resp) + NANOHUB_RSA_KEY_CHUNK_LEN))) 1049 return; 1050 1051 ptr = BL.blGetPubKeysInfo(&numKeys); 1052 if (ptr && numKeys * RSA_BYTES > req->offset) { 1053 len = numKeys * RSA_BYTES - req->offset; 1054 if (len > NANOHUB_RSA_KEY_CHUNK_LEN) 1055 len = NANOHUB_RSA_KEY_CHUNK_LEN; 1056 memcpy(resp->data, (uint8_t *)ptr + req->offset, len); 1057 } 1058 1059 resp->hdr.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1060 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1 + len; 1061 resp->hdr.msg = NANOHUB_HAL_QUERY_RSA_KEYS; 1062 1063 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1064 } 1065 1066 static void halStartUpload(void *rx, uint8_t rx_len) 1067 { 1068 struct NanohubHalStartUploadRx *req = rx; 1069 struct NanohubStartFirmwareUploadRequest hwReq = { 1070 .size= req->length 1071 }; 1072 struct NanohubHalStartUploadTx *resp; 1073 1074 if (!(resp = heapAlloc(sizeof(*resp)))) 1075 return; 1076 1077 resp->hdr.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1078 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1079 resp->hdr.msg = NANOHUB_HAL_START_UPLOAD; 1080 resp->success = doStartFirmwareUpload(&hwReq); 1081 1082 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1083 } 1084 1085 static void halContUpload(void *rx, uint8_t rx_len) 1086 { 1087 uint32_t offset; 1088 uint32_t reply; 1089 uint8_t len; 1090 struct NanohubHalContUploadRx *req = rx; 1091 struct NanohubHalContUploadTx *resp; 1092 1093 if (!(resp = heapAlloc(sizeof(*resp)))) 1094 return; 1095 1096 resp->hdr.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1097 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1098 resp->hdr.msg = NANOHUB_HAL_CONT_UPLOAD; 1099 1100 if (!mDownloadState) { 1101 reply = NANOHUB_FIRMWARE_CHUNK_REPLY_CANCEL_NO_RETRY; 1102 } else { 1103 offset = le32toh(req->offset); 1104 len = rx_len - sizeof(req->offset); 1105 reply = doFirmwareChunk(req->data, offset, len, resp); 1106 } 1107 if (reply != NANOHUB_FIRMWARE_CHUNK_REPLY_ACCEPTED) { 1108 osLog(LOG_ERROR, "%s: reply=%" PRIu32 "\n", __func__, reply); 1109 1110 resp->success = false; 1111 1112 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1113 } 1114 } 1115 1116 static void halFinishUpload(void *rx, uint8_t rx_len) 1117 { 1118 struct NanohubHalFinishUploadTx *resp; 1119 uint32_t reply; 1120 1121 if (!(resp = heapAlloc(sizeof(*resp)))) 1122 return; 1123 1124 resp->hdr.appId = APP_ID_MAKE(APP_ID_VENDOR_GOOGLE, 0); 1125 resp->hdr.len = sizeof(*resp) - sizeof(struct NanohubHalHdr) + 1; 1126 resp->hdr.msg = NANOHUB_HAL_FINISH_UPLOAD; 1127 1128 reply = doFinishFirmwareUpload(); 1129 1130 osLog(LOG_INFO, "%s: reply=%" PRIu32 "\n", __func__, reply); 1131 1132 resp->success = (reply == NANOHUB_FIRMWARE_UPLOAD_SUCCESS); 1133 1134 osEnqueueEvtOrFree(EVT_APP_TO_HOST, resp, heapFree); 1135 } 1136 1137 static void halReboot(void *rx, uint8_t rx_len) 1138 { 1139 BL.blReboot(); 1140 } 1141 1142 const static struct NanohubHalCommand mBuiltinHalCommands[] = { 1143 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APPS_ON, 1144 halExtAppsOn), 1145 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APPS_OFF, 1146 halExtAppsOff), 1147 NANOHUB_HAL_COMMAND(NANOHUB_HAL_EXT_APP_DELETE, 1148 halExtAppDelete), 1149 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_MEMINFO, 1150 halQueryMemInfo), 1151 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_APPS, 1152 halQueryApps), 1153 NANOHUB_HAL_COMMAND(NANOHUB_HAL_QUERY_RSA_KEYS, 1154 halQueryRsaKeys), 1155 NANOHUB_HAL_COMMAND(NANOHUB_HAL_START_UPLOAD, 1156 halStartUpload), 1157 NANOHUB_HAL_COMMAND(NANOHUB_HAL_CONT_UPLOAD, 1158 halContUpload), 1159 NANOHUB_HAL_COMMAND(NANOHUB_HAL_FINISH_UPLOAD, 1160 halFinishUpload), 1161 NANOHUB_HAL_COMMAND(NANOHUB_HAL_REBOOT, 1162 halReboot), 1163 }; 1164 1165 const struct NanohubHalCommand *nanohubHalFindCommand(uint8_t msg) 1166 { 1167 uint32_t i; 1168 1169 for (i = 0; i < ARRAY_SIZE(mBuiltinHalCommands); i++) { 1170 const struct NanohubHalCommand *cmd = &mBuiltinHalCommands[i]; 1171 if (cmd->msg == msg) 1172 return cmd; 1173 } 1174 return NULL; 1175 } 1176 1177 uint64_t hostGetTime(void) 1178 { 1179 int64_t delta = getAvgDelta(&mTimeSync); 1180 1181 if (!delta || delta == INT64_MIN) 1182 return 0ULL; 1183 else 1184 return sensorGetTime() + delta; 1185 } 1186 1187 #if DEBUG_APHUB_TIME_SYNC 1188 1189 #define N_APHUB_SYNC_DATA 256 1190 #define PRINT_DELAY 20000000 // unit ns, 20ms 1191 struct ApHubSyncDebug { 1192 uint64_t apFirst; 1193 uint64_t hubFirst; 1194 uint32_t apDelta[N_APHUB_SYNC_DATA]; // us 1195 uint32_t hubDelta[N_APHUB_SYNC_DATA]; // us 1196 int printIndex; //negative means not printing 1197 int writeIndex; 1198 1199 uint32_t printTimer; 1200 }; 1201 1202 struct ApHubSyncDebug mApHubSyncDebug = {0}; 1203 1204 static void syncDebugCallback(uint32_t timerId, void *data) { 1205 1206 if (mApHubSyncDebug.printIndex >= mApHubSyncDebug.writeIndex || 1207 mApHubSyncDebug.printIndex >= N_APHUB_SYNC_DATA) { 1208 timTimerCancel(mApHubSyncDebug.printTimer); 1209 1210 osLog(LOG_DEBUG, "APHUB Done printing %d items", mApHubSyncDebug.printIndex); 1211 mApHubSyncDebug.writeIndex = 0; 1212 mApHubSyncDebug.printIndex = -1; 1213 1214 mApHubSyncDebug.printTimer = 0; 1215 } else { 1216 if (mApHubSyncDebug.printIndex == 0) { 1217 osLog(LOG_DEBUG, "APHUB init %" PRIu64 " %" PRIu64, 1218 mApHubSyncDebug.apFirst, 1219 mApHubSyncDebug.hubFirst); 1220 } 1221 1222 osLog(LOG_DEBUG, "APHUB %d %" PRIu32 " %" PRIu32, 1223 mApHubSyncDebug.printIndex, 1224 mApHubSyncDebug.apDelta[mApHubSyncDebug.printIndex], 1225 mApHubSyncDebug.hubDelta[mApHubSyncDebug.printIndex]); 1226 1227 mApHubSyncDebug.printIndex++; 1228 } 1229 } 1230 1231 static void syncDebugTriggerPrint() { 1232 if (mApHubSyncDebug.printTimer) { 1233 //printing already going 1234 return; 1235 } 1236 1237 mApHubSyncDebug.printIndex = 0; 1238 1239 syncDebugCallback(0, NULL); 1240 if (!(mApHubSyncDebug.printTimer = 1241 timTimerSet(PRINT_DELAY, 0, 50, syncDebugCallback, NULL, false /*oneShot*/))) { 1242 osLog(LOG_WARN, "Cannot get timer for printing"); 1243 1244 mApHubSyncDebug.writeIndex = 0; // discard all data 1245 mApHubSyncDebug.printIndex = -1; // not printing 1246 } 1247 } 1248 1249 static void syncDebugAdd(uint64_t ap, uint64_t hub) { 1250 if (mApHubSyncDebug.writeIndex >= N_APHUB_SYNC_DATA) { 1251 //full 1252 syncDebugTriggerPrint(); 1253 return; 1254 } 1255 1256 if (mApHubSyncDebug.writeIndex == 0) { 1257 mApHubSyncDebug.apFirst = ap; 1258 mApHubSyncDebug.hubFirst = hub; 1259 } 1260 1261 // convert ns to us 1262 mApHubSyncDebug.apDelta[mApHubSyncDebug.writeIndex] = 1263 (uint32_t) U64_DIV_BY_CONST_U16((ap - mApHubSyncDebug.apFirst), 1000u); 1264 mApHubSyncDebug.hubDelta[mApHubSyncDebug.writeIndex] = 1265 (uint32_t) U64_DIV_BY_CONST_U16((hub - mApHubSyncDebug.hubFirst), 1000u); 1266 1267 ++mApHubSyncDebug.writeIndex; 1268 } 1269 #endif 1270