Encapsulate notification send (sync/async) into DfuService::NotificationManager;

This commit is contained in:
JF 2020-06-01 17:35:28 +02:00
parent 07f74cee63
commit f6aa41c214
2 changed files with 78 additions and 66 deletions

View file

@ -17,8 +17,8 @@ int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle,
} }
void NotificationTimerCallback(TimerHandle_t xTimer) { void NotificationTimerCallback(TimerHandle_t xTimer) {
auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID(xTimer)); auto notificationManager = static_cast<DfuService::NotificationManager *>(pvTimerGetTimerID(xTimer));
dfuService->OnNotificationTimer(); notificationManager->OnNotificationTimer();
} }
void TimeoutTimerCallback(TimerHandle_t xTimer) { void TimeoutTimerCallback(TimerHandle_t xTimer) {
@ -70,7 +70,6 @@ DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Contr
0 0
}, },
} { } {
notificationTimer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback);
timeoutTimer = xTimerCreate ("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback); 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}; uint8_t data[]{16, 1, 1};
SendNotification(connectionHandle, data, 3); notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
state = States::Init; state = States::Init;
} }
return 0; 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); std::memcpy(tempBuffer + offset, om->om_data, om->om_len);
if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) { if (nbPacketReceived > 0 && (nbPacketReceived % nbPacketsToNotify) == 0) {
#if 1
spiNorFlash.Write(writeOffset + ((nbPacketReceived - nbPacketsToNotify) * 20), tempBuffer, 200); spiNorFlash.Write(writeOffset + ((nbPacketReceived - nbPacketsToNotify) * 20), tempBuffer, 200);
#endif
} }
bytesReceived += om->om_len; bytesReceived += om->om_len;
bleController.FirmwareUpdateCurrentBytes(bytesReceived); bleController.FirmwareUpdateCurrentBytes(bytesReceived);
//NRF_LOG_INFO("[DFU] -> Bytes received : %d in %d packets", bytesReceived, nbPacketReceived);
if ((nbPacketReceived % nbPacketsToNotify) == 0 && bytesReceived != applicationSize) { if ((nbPacketReceived % nbPacketsToNotify) == 0 && bytesReceived != applicationSize) {
uint8_t data[5]{static_cast<uint8_t>(Opcodes::PacketReceiptNotification), uint8_t data[5]{static_cast<uint8_t>(Opcodes::PacketReceiptNotification),
(uint8_t) (bytesReceived & 0x000000FFu), (uint8_t) (bytesReceived >> 8u), (uint8_t) (bytesReceived & 0x000000FFu), (uint8_t) (bytesReceived >> 8u),
(uint8_t) (bytesReceived >> 16u), (uint8_t) (bytesReceived >> 24u)}; (uint8_t) (bytesReceived >> 16u), (uint8_t) (bytesReceived >> 24u)};
NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived); 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 (bytesReceived == applicationSize) {
if ((nbPacketReceived % nbPacketsToNotify) != 0) { if ((nbPacketReceived % nbPacketsToNotify) != 0) {
auto remaningPacket = nbPacketReceived % nbPacketsToNotify; auto remaningPacket = nbPacketReceived % nbPacketsToNotify;
uint32_t spiOffset = writeOffset + ((nbPacketReceived - remaningPacket) * 20);
spiNorFlash.Write(writeOffset + ((nbPacketReceived - remaningPacket) * 20), tempBuffer, 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<uint8_t>(Opcodes::ReceiveFirmwareImage), static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
static_cast<uint8_t>(ErrorCodes::NoError)}; static_cast<uint8_t>(ErrorCodes::NoError)};
NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received!"); NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received!");
SendNotification(connectionHandle, data, 3); notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
state = States::Validate; 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"); NRF_LOG_INFO("[DFU] -> Init DFU parameters %s", isInitComplete ? " complete" : " not complete");
if (isInitComplete) { if (isInitComplete) {
notificationBuffer[0] = static_cast<uint8_t>(Opcodes::Response); uint8_t data[3] {
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::InitDFUParameters); static_cast<uint8_t>(Opcodes::Response),
notificationBuffer[2] = (isInitComplete ? uint8_t{1} : uint8_t{0}); static_cast<uint8_t>(Opcodes::InitDFUParameters),
notificationSize = 3; (isInitComplete ? uint8_t{1} : uint8_t{0})
notificatonConnectionHandle = connectionHandle; };
xTimerStart(notificationTimer, 0); notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
return 0; return 0;
} }
} }
@ -279,21 +270,19 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
if(Validate()){ if(Validate()){
state = States::Validated; state = States::Validated;
uint8_t data[3] {
notificationBuffer[0] = static_cast<uint8_t>(Opcodes::Response); static_cast<uint8_t>(Opcodes::Response),
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::ValidateFirmware); static_cast<uint8_t>(Opcodes::ValidateFirmware),
notificationBuffer[2] = static_cast<uint8_t>(ErrorCodes::NoError); static_cast<uint8_t>(ErrorCodes::NoError)
notificationSize = 3; };
notificatonConnectionHandle = connectionHandle; notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
xTimerStart(notificationTimer, 0);
} else { } else {
notificationBuffer[0] = static_cast<uint8_t>(Opcodes::Response); uint8_t data[3] {
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::ValidateFirmware); static_cast<uint8_t>(Opcodes::Response),
notificationBuffer[2] = static_cast<uint8_t>(ErrorCodes::CrcError); static_cast<uint8_t>(Opcodes::ValidateFirmware),
notificationSize = 3; static_cast<uint8_t>(ErrorCodes::CrcError)
notificatonConnectionHandle = connectionHandle; };
xTimerStart(notificationTimer, 0); notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
} }
return 0; 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 DfuService::ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc) {
uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc; uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc;
@ -376,13 +361,6 @@ void DfuService::WriteMagicNumber() {
spiNorFlash.Write(offset, reinterpret_cast<uint8_t *>(magic), 4 * sizeof(uint32_t)); spiNorFlash.Write(offset, reinterpret_cast<uint8_t *>(magic), 4 * sizeof(uint32_t));
} }
void DfuService::OnNotificationTimer() {
if(notificationSize > 0) {
SendNotification(notificatonConnectionHandle, notificationBuffer, notificationSize);
notificationSize = 0;
}
}
void DfuService::OnTimeout() { void DfuService::OnTimeout() {
Reset(); Reset();
} }
@ -396,10 +374,44 @@ void DfuService::Reset() {
bootloaderSize = 0; bootloaderSize = 0;
applicationSize = 0; applicationSize = 0;
expectedCrc = 0; expectedCrc = 0;
notificatonConnectionHandle = 0; notificationManager.Reset();
notificationSize = 0;
xTimerStop(notificationTimer, 0);
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error); bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
bleController.StopFirmwareUpdate(); bleController.StopFirmwareUpdate();
systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished); 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);
}

View file

@ -19,17 +19,28 @@ namespace Pinetime {
public: public:
DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController, DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
Pinetime::Drivers::SpiNorFlash &spiNorFlash); Pinetime::Drivers::SpiNorFlash &spiNorFlash);
void Init(); void Init();
bool Validate(); bool Validate();
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context); int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
void OnNotificationTimer();
void OnTimeout(); void OnTimeout();
void Reset(); 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: private:
Pinetime::System::SystemTask &systemTask; Pinetime::System::SystemTask &systemTask;
Pinetime::Controllers::Ble &bleController; Pinetime::Controllers::Ble &bleController;
@ -117,24 +128,13 @@ namespace Pinetime {
uint16_t expectedCrc = 0; uint16_t expectedCrc = 0;
int SendDfuRevision(os_mbuf *om) const; 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 WritePacketHandler(uint16_t connectionHandle, os_mbuf *om);
int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om); int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om);
uint8_t tempBuffer[200]; uint8_t tempBuffer[200];
uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc); uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);
void WriteMagicNumber(); void WriteMagicNumber();
TimerHandle_t notificationTimer;
TimerHandle_t timeoutTimer; TimerHandle_t timeoutTimer;
NotificationManager notificationManager;
uint16_t notificatonConnectionHandle = 0;
size_t notificationSize = 0;
uint8_t notificationBuffer[10];
}; };
} }
} }