diff --git a/src/Components/Ble/DfuService.cpp b/src/Components/Ble/DfuService.cpp index 38a550f0..a170fdfa 100644 --- a/src/Components/Ble/DfuService.cpp +++ b/src/Components/Ble/DfuService.cpp @@ -17,8 +17,8 @@ int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle, } void NotificationTimerCallback(TimerHandle_t xTimer) { - auto dfuService = static_cast(pvTimerGetTimerID(xTimer)); - dfuService->OnNotificationTimer(); + auto notificationManager = static_cast(pvTimerGetTimerID(xTimer)); + notificationManager->OnNotificationTimer(); } void TimeoutTimerCallback(TimerHandle_t xTimer) { @@ -70,7 +70,6 @@ DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Contr 0 }, } { - notificationTimer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback); timeoutTimer = xTimerCreate ("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback); } @@ -132,7 +131,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) { } uint8_t data[]{16, 1, 1}; - SendNotification(connectionHandle, data, 3); + notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3); state = States::Init; } return 0; @@ -162,30 +161,22 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) { std::memcpy(tempBuffer + offset, om->om_data, om->om_len); if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) { -#if 1 spiNorFlash.Write(writeOffset + ((nbPacketReceived - nbPacketsToNotify) * 20), tempBuffer, 200); -#endif } - bytesReceived += om->om_len; bleController.FirmwareUpdateCurrentBytes(bytesReceived); - //NRF_LOG_INFO("[DFU] -> Bytes received : %d in %d packets", bytesReceived, nbPacketReceived); - - if ((nbPacketReceived % nbPacketsToNotify) == 0 && bytesReceived != applicationSize) { uint8_t data[5]{static_cast(Opcodes::PacketReceiptNotification), (uint8_t) (bytesReceived & 0x000000FFu), (uint8_t) (bytesReceived >> 8u), (uint8_t) (bytesReceived >> 16u), (uint8_t) (bytesReceived >> 24u)}; NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived); - SendNotification(connectionHandle, data, 5); + notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5); } if (bytesReceived == applicationSize) { if ((nbPacketReceived % nbPacketsToNotify) != 0) { auto remaningPacket = nbPacketReceived % nbPacketsToNotify; - uint32_t spiOffset = writeOffset + ((nbPacketReceived - remaningPacket) * 20); - spiNorFlash.Write(writeOffset + ((nbPacketReceived - remaningPacket) * 20), tempBuffer, remaningPacket * 20); } @@ -196,7 +187,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) { static_cast(Opcodes::ReceiveFirmwareImage), static_cast(ErrorCodes::NoError)}; NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received!"); - SendNotification(connectionHandle, data, 3); + notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3); state = States::Validate; } } @@ -247,12 +238,12 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) { NRF_LOG_INFO("[DFU] -> Init DFU parameters %s", isInitComplete ? " complete" : " not complete"); if (isInitComplete) { - notificationBuffer[0] = static_cast(Opcodes::Response); - notificationBuffer[1] = static_cast(Opcodes::InitDFUParameters); - notificationBuffer[2] = (isInitComplete ? uint8_t{1} : uint8_t{0}); - notificationSize = 3; - notificatonConnectionHandle = connectionHandle; - xTimerStart(notificationTimer, 0); + uint8_t data[3] { + static_cast(Opcodes::Response), + static_cast(Opcodes::InitDFUParameters), + (isInitComplete ? uint8_t{1} : uint8_t{0}) + }; + notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3); return 0; } } @@ -279,21 +270,19 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) { if(Validate()){ state = States::Validated; - - notificationBuffer[0] = static_cast(Opcodes::Response); - notificationBuffer[1] = static_cast(Opcodes::ValidateFirmware); - notificationBuffer[2] = static_cast(ErrorCodes::NoError); - notificationSize = 3; - notificatonConnectionHandle = connectionHandle; - xTimerStart(notificationTimer, 0); - + uint8_t data[3] { + static_cast(Opcodes::Response), + static_cast(Opcodes::ValidateFirmware), + static_cast(ErrorCodes::NoError) + }; + notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3); } else { - notificationBuffer[0] = static_cast(Opcodes::Response); - notificationBuffer[1] = static_cast(Opcodes::ValidateFirmware); - notificationBuffer[2] = static_cast(ErrorCodes::CrcError); - notificationSize = 3; - notificatonConnectionHandle = connectionHandle; - xTimerStart(notificationTimer, 0); + uint8_t data[3] { + static_cast(Opcodes::Response), + static_cast(Opcodes::ValidateFirmware), + static_cast(ErrorCodes::CrcError) + }; + notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3); } return 0; @@ -314,11 +303,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) { } } -void DfuService::SendNotification(uint16_t connectionHandle, const uint8_t *data, const size_t size) { - auto *om = ble_hs_mbuf_from_flat(data, size); - auto ret = ble_gattc_notify_custom(connectionHandle, controlPointCharacteristicHandle, om); - ASSERT(ret == 0); -} + uint16_t DfuService::ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc) { uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc; @@ -376,13 +361,6 @@ void DfuService::WriteMagicNumber() { spiNorFlash.Write(offset, reinterpret_cast(magic), 4 * sizeof(uint32_t)); } -void DfuService::OnNotificationTimer() { - if(notificationSize > 0) { - SendNotification(notificatonConnectionHandle, notificationBuffer, notificationSize); - notificationSize = 0; - } -} - void DfuService::OnTimeout() { Reset(); } @@ -396,10 +374,44 @@ void DfuService::Reset() { bootloaderSize = 0; applicationSize = 0; expectedCrc = 0; - notificatonConnectionHandle = 0; - notificationSize = 0; - xTimerStop(notificationTimer, 0); + notificationManager.Reset(); bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); bleController.StopFirmwareUpdate(); systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished); } + +DfuService::NotificationManager::NotificationManager() { + timer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback); +} + +bool DfuService::NotificationManager::AsyncSend(uint16_t connection, uint16_t charactHandle, uint8_t *data, size_t s) { + if(size != 0 || s > 10) + return false; + + connectionHandle = connection; + characteristicHandle = charactHandle; + size = s; + std::memcpy(buffer, data, size); + xTimerStart(timer, 0); + return true; +} + +void DfuService::NotificationManager::OnNotificationTimer() { + if(size > 0) { + Send(connectionHandle, characteristicHandle, buffer, size); + size = 0; + } +} + +void DfuService::NotificationManager::Send(uint16_t connection, uint16_t charactHandle, const uint8_t *data, const size_t s) { + auto *om = ble_hs_mbuf_from_flat(data, s); + auto ret = ble_gattc_notify_custom(connection, charactHandle, om); + ASSERT(ret == 0); +} + +void DfuService::NotificationManager::Reset() { + connectionHandle = 0; + characteristicHandle = 0; + size = 0; + xTimerStop(timer, 0); +} diff --git a/src/Components/Ble/DfuService.h b/src/Components/Ble/DfuService.h index 73846c86..b0eccdf5 100644 --- a/src/Components/Ble/DfuService.h +++ b/src/Components/Ble/DfuService.h @@ -19,17 +19,28 @@ namespace Pinetime { public: DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController, Pinetime::Drivers::SpiNorFlash &spiNorFlash); - void Init(); - bool Validate(); - int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); - void OnNotificationTimer(); void OnTimeout(); - void Reset(); + class NotificationManager { + public: + NotificationManager(); + bool AsyncSend(uint16_t connection, uint16_t charactHandle, uint8_t *data, size_t size); + void Send(uint16_t connection, uint16_t characteristicHandle, const uint8_t *data, const size_t s); + private: + TimerHandle_t timer; + uint16_t connectionHandle = 0; + uint16_t characteristicHandle = 0; + size_t size = 0; + uint8_t buffer[10]; + public: + void OnNotificationTimer(); + void Reset(); + }; + private: Pinetime::System::SystemTask &systemTask; Pinetime::Controllers::Ble &bleController; @@ -117,24 +128,13 @@ namespace Pinetime { uint16_t expectedCrc = 0; int SendDfuRevision(os_mbuf *om) const; - - void SendNotification(uint16_t connectionHandle, const uint8_t *data, const size_t size); - int WritePacketHandler(uint16_t connectionHandle, os_mbuf *om); - int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om); - uint8_t tempBuffer[200]; - uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc); - void WriteMagicNumber(); - TimerHandle_t notificationTimer; TimerHandle_t timeoutTimer; - - uint16_t notificatonConnectionHandle = 0; - size_t notificationSize = 0; - uint8_t notificationBuffer[10]; + NotificationManager notificationManager; }; } } \ No newline at end of file