DFUOverSMP.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. /*
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include "DFUOverSMP.h"
  18. #if !defined(CONFIG_MCUMGR_TRANSPORT_BT) || !defined(CONFIG_MCUMGR_GRP_IMG) || !defined(CONFIG_MCUMGR_GRP_OS)
  19. #error "DFUOverSMP requires MCUMGR module configs enabled"
  20. #endif
  21. #include "OTAUtil.h"
  22. #include <platform/CHIPDeviceLayer.h>
  23. #include <lib/support/logging/CHIPLogging.h>
  24. #include <zephyr/dfu/mcuboot.h>
  25. #include <zephyr/mgmt/mcumgr/mgmt/callbacks.h>
  26. #include <zephyr/mgmt/mcumgr/mgmt/mgmt.h>
  27. using namespace ::chip;
  28. using namespace ::chip::DeviceLayer;
  29. constexpr uint8_t kAdvertisingPriority = UINT8_MAX;
  30. constexpr uint32_t kAdvertisingOptions = BT_LE_ADV_OPT_CONNECTABLE;
  31. constexpr uint16_t kAdvertisingIntervalMin = 400;
  32. constexpr uint16_t kAdvertisingIntervalMax = 500;
  33. constexpr uint8_t kAdvertisingFlags = BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR;
  34. namespace {
  35. int32_t UploadConfirmHandler(uint32_t event, int32_t rc, bool * abort_more, void * data, size_t data_size)
  36. {
  37. const img_mgmt_upload_check & imgData = *static_cast<img_mgmt_upload_check *>(data);
  38. IgnoreUnusedVariable(imgData);
  39. ChipLogProgress(SoftwareUpdate, "DFU over SMP progress: %u/%u B of image %u", static_cast<unsigned>(imgData.req->off),
  40. static_cast<unsigned>(imgData.action->size), static_cast<unsigned>(imgData.req->image));
  41. return MGMT_ERR_EOK;
  42. }
  43. int32_t CommandHandler(uint32_t event, int32_t rc, bool * abort_more, void * data, size_t data_size)
  44. {
  45. if (event == MGMT_EVT_OP_CMD_RECV)
  46. {
  47. GetFlashHandler().DoAction(ExternalFlashManager::Action::WAKE_UP);
  48. }
  49. else if (event == MGMT_EVT_OP_CMD_DONE)
  50. {
  51. GetFlashHandler().DoAction(ExternalFlashManager::Action::SLEEP);
  52. }
  53. return MGMT_ERR_EOK;
  54. }
  55. mgmt_callback sUploadCallback = {
  56. .callback = UploadConfirmHandler,
  57. .event_id = MGMT_EVT_OP_IMG_MGMT_DFU_CHUNK,
  58. };
  59. mgmt_callback sCommandCallback = {
  60. .callback = CommandHandler,
  61. .event_id = (MGMT_EVT_OP_CMD_RECV | MGMT_EVT_OP_CMD_DONE),
  62. };
  63. } // namespace
  64. DFUOverSMP DFUOverSMP::sDFUOverSMP;
  65. void DFUOverSMP::Init()
  66. {
  67. const char * name = bt_get_name();
  68. mAdvertisingItems[0] = BT_DATA(BT_DATA_FLAGS, &kAdvertisingFlags, sizeof(kAdvertisingFlags));
  69. mAdvertisingItems[1] = BT_DATA(BT_DATA_NAME_COMPLETE, name, static_cast<uint8_t>(strlen(name)));
  70. mAdvertisingRequest.priority = kAdvertisingPriority;
  71. mAdvertisingRequest.options = kAdvertisingOptions;
  72. mAdvertisingRequest.minInterval = kAdvertisingIntervalMin;
  73. mAdvertisingRequest.maxInterval = kAdvertisingIntervalMax;
  74. mAdvertisingRequest.advertisingData = Span<bt_data>(mAdvertisingItems);
  75. mAdvertisingRequest.onStarted = [](int rc) {
  76. if (rc == 0)
  77. {
  78. ChipLogProgress(SoftwareUpdate, "SMP BLE advertising started");
  79. }
  80. else
  81. {
  82. ChipLogError(SoftwareUpdate, "Failed to start SMP BLE advertising: %d", rc);
  83. }
  84. };
  85. mgmt_callback_register(&sUploadCallback);
  86. mgmt_callback_register(&sCommandCallback);
  87. }
  88. void DFUOverSMP::ConfirmNewImage()
  89. {
  90. // Check if the image is run in the REVERT mode and eventually
  91. // confirm it to prevent reverting on the next boot.
  92. VerifyOrReturn(mcuboot_swap_type() == BOOT_SWAP_TYPE_REVERT);
  93. if (boot_write_img_confirmed())
  94. {
  95. ChipLogError(SoftwareUpdate, "Confirming firmware image failed, it will be reverted on the next boot");
  96. }
  97. else
  98. {
  99. ChipLogProgress(SoftwareUpdate, "New firmware image confirmed");
  100. }
  101. }
  102. void DFUOverSMP::StartServer()
  103. {
  104. VerifyOrReturn(!mIsStarted, ChipLogProgress(SoftwareUpdate, "DFU over SMP was already started"));
  105. // Synchronize access to the advertising arbiter that normally runs on the CHIP thread.
  106. PlatformMgr().LockChipStack();
  107. BLEAdvertisingArbiter::InsertRequest(mAdvertisingRequest);
  108. PlatformMgr().UnlockChipStack();
  109. mIsStarted = true;
  110. ChipLogProgress(DeviceLayer, "DFU over SMP started");
  111. }