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

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

@ -17,8 +17,8 @@ int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle,
}
void NotificationTimerCallback(TimerHandle_t xTimer) {
auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID(xTimer));
dfuService->OnNotificationTimer();
auto notificationManager = static_cast<DfuService::NotificationManager *>(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<uint8_t>(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<uint8_t>(Opcodes::ReceiveFirmwareImage),
static_cast<uint8_t>(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<uint8_t>(Opcodes::Response);
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::InitDFUParameters);
notificationBuffer[2] = (isInitComplete ? uint8_t{1} : uint8_t{0});
notificationSize = 3;
notificatonConnectionHandle = connectionHandle;
xTimerStart(notificationTimer, 0);
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(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<uint8_t>(Opcodes::Response);
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::ValidateFirmware);
notificationBuffer[2] = static_cast<uint8_t>(ErrorCodes::NoError);
notificationSize = 3;
notificatonConnectionHandle = connectionHandle;
xTimerStart(notificationTimer, 0);
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(ErrorCodes::NoError)
};
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
} else {
notificationBuffer[0] = static_cast<uint8_t>(Opcodes::Response);
notificationBuffer[1] = static_cast<uint8_t>(Opcodes::ValidateFirmware);
notificationBuffer[2] = static_cast<uint8_t>(ErrorCodes::CrcError);
notificationSize = 3;
notificatonConnectionHandle = connectionHandle;
xTimerStart(notificationTimer, 0);
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(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<uint8_t *>(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);
}

@ -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;
};
}
}