Encapsulate notification send (sync/async) into DfuService::NotificationManager;
This commit is contained in:
parent
07f74cee63
commit
f6aa41c214
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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];
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue