Reformatted all the files according to clang-format style

This commit is contained in:
Avamander
2021-04-18 20:28:14 +03:00
parent e56ebb8bd6
commit 40d45d923b
179 changed files with 10119 additions and 10688 deletions

View File

@@ -12,50 +12,42 @@ constexpr ble_uuid16_t AlertNotificationClient::unreadAlertStatusUuid;
constexpr ble_uuid16_t AlertNotificationClient::controlPointUuid;
namespace {
int
OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service,
void *arg) {
auto client = static_cast<AlertNotificationClient *>(arg);
int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnDiscoveryEvent(conn_handle, error, service);
}
int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg) {
auto client = static_cast<AlertNotificationClient *>(arg);
int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle,
const struct ble_gatt_error* error,
const struct ble_gatt_chr* chr,
void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr);
}
int OnAlertNotificationDescriptorDiscoveryEventCallback(uint16_t conn_handle,
const struct ble_gatt_error *error,
uint16_t chr_val_handle,
const struct ble_gatt_dsc *dsc,
void *arg) {
auto client = static_cast<AlertNotificationClient *>(arg);
int OnAlertNotificationDescriptorDiscoveryEventCallback(
uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc);
}
int NewAlertSubcribeCallback(uint16_t conn_handle,
const struct ble_gatt_error *error,
struct ble_gatt_attr *attr,
void *arg) {
auto client = static_cast<AlertNotificationClient *>(arg);
int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnNewAlertSubcribe(conn_handle, error, attr);
}
}
AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager) :
systemTask{systemTask}, notificationManager{notificationManager} {
AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager)
: systemTask {systemTask}, notificationManager {notificationManager} {
}
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_svc *service) {
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) {
if (service == nullptr && error->status == BLE_HS_EDONE) {
if (isDiscovered) {
NRF_LOG_INFO("ANS Discovery found, starting characteristics discovery");
ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle,
OnAlertNotificationCharacteristicDiscoveredCallback, this);
ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle, OnAlertNotificationCharacteristicDiscoveredCallback, this);
} else {
NRF_LOG_INFO("ANS not found");
onServiceDiscovered(connectionHandle);
@@ -63,7 +55,7 @@ bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const
return true;
}
if (service != nullptr && ble_uuid_cmp(((ble_uuid_t *) &ansServiceUuid), &service->uuid.u) == 0) {
if (service != nullptr && ble_uuid_cmp(((ble_uuid_t*) &ansServiceUuid), &service->uuid.u) == 0) {
NRF_LOG_INFO("ANS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle);
ansStartHandle = service->start_handle;
ansEndHandle = service->end_handle;
@@ -72,8 +64,9 @@ bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const
return false;
}
int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic) {
int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle,
const ble_gatt_error* error,
const ble_gatt_chr* characteristic) {
if (error->status != 0 && error->status != BLE_HS_EDONE) {
NRF_LOG_INFO("ANS Characteristic discovery ERROR");
onServiceDiscovered(connectionHandle);
@@ -83,41 +76,34 @@ int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connection
if (characteristic == nullptr && error->status == BLE_HS_EDONE) {
NRF_LOG_INFO("ANS Characteristic discovery complete");
if (isCharacteristicDiscovered) {
ble_gattc_disc_all_dscs(connectionHandle,
newAlertHandle, ansEndHandle,
OnAlertNotificationDescriptorDiscoveryEventCallback, this);
ble_gattc_disc_all_dscs(connectionHandle, newAlertHandle, ansEndHandle, OnAlertNotificationDescriptorDiscoveryEventCallback, this);
} else
onServiceDiscovered(connectionHandle);
} else {
if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : supportedNewAlertCategoryUuid");
supportedNewAlertCategoryHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : supportedUnreadAlertCategoryUuid");
supportedUnreadAlertCategoryHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : newAlertUuid");
newAlertHandle = characteristic->val_handle;
newAlertDefHandle = characteristic->def_handle;
isCharacteristicDiscovered = true;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : unreadAlertStatusUuid");
unreadAlertStatusHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &controlPointUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &controlPointUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : controlPointUuid");
controlPointHandle = characteristic->val_handle;
} else NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
} else
NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
}
return 0;
}
int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error *error,
ble_gatt_attr *attribute) {
int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute) {
if (error->status == 0) {
NRF_LOG_INFO("ANS New alert subscribe OK");
} else {
@@ -128,12 +114,12 @@ int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const
return 0;
}
int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc *descriptor) {
const ble_gatt_dsc* descriptor) {
if (error->status == 0) {
if (characteristicValueHandle == newAlertHandle &&
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &descriptor->uuid.u)) {
if (characteristicValueHandle == newAlertHandle && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &descriptor->uuid.u)) {
if (newAlertDescriptorHandle == 0) {
NRF_LOG_INFO("ANS Descriptor discovered : %d", descriptor->handle);
newAlertDescriptorHandle = descriptor->handle;
@@ -151,16 +137,17 @@ int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connect
return 0;
}
void AlertNotificationClient::OnNotification(ble_gap_event *event) {
void AlertNotificationClient::OnNotification(ble_gap_event* event) {
if (event->notify_rx.attr_handle == newAlertHandle) {
constexpr size_t stringTerminatorSize = 1; // end of string '\0'
constexpr size_t headerSize = 3;
const auto maxMessageSize{NotificationManager::MaximumMessageSize()};
const auto maxBufferSize{maxMessageSize + headerSize};
const auto maxMessageSize {NotificationManager::MaximumMessageSize()};
const auto maxBufferSize {maxMessageSize + headerSize};
// Ignore notifications with empty message
const auto packetLen = OS_MBUF_PKTLEN(event->notify_rx.om);
if(packetLen <= headerSize) return;
if (packetLen <= headerSize)
return;
size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize);
auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize));

View File

@@ -19,68 +19,52 @@ namespace Pinetime {
class NotificationManager;
class AlertNotificationClient : public BleClient {
public:
explicit AlertNotificationClient(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager);
public:
explicit AlertNotificationClient(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager);
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service);
int OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error *error, ble_gatt_attr *attribute);
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor);
void OnNotification(ble_gap_event *event);
void Reset();
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service);
int OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute);
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc* descriptor);
void OnNotification(ble_gap_event* event);
void Reset();
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
private:
static constexpr uint16_t ansServiceId{0x1811};
static constexpr uint16_t supportedNewAlertCategoryId = 0x2a47;
static constexpr uint16_t supportedUnreadAlertCategoryId = 0x2a48;
static constexpr uint16_t newAlertId = 0x2a46;
static constexpr uint16_t unreadAlertStatusId = 0x2a45;
static constexpr uint16_t controlPointId = 0x2a44;
private:
static constexpr uint16_t ansServiceId {0x1811};
static constexpr uint16_t supportedNewAlertCategoryId = 0x2a47;
static constexpr uint16_t supportedUnreadAlertCategoryId = 0x2a48;
static constexpr uint16_t newAlertId = 0x2a46;
static constexpr uint16_t unreadAlertStatusId = 0x2a45;
static constexpr uint16_t controlPointId = 0x2a44;
static constexpr ble_uuid16_t ansServiceUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = ansServiceId
};
static constexpr ble_uuid16_t supportedNewAlertCategoryUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = supportedNewAlertCategoryId
};
static constexpr ble_uuid16_t supportedUnreadAlertCategoryUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = supportedUnreadAlertCategoryId
};
static constexpr ble_uuid16_t newAlertUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = newAlertId
};
static constexpr ble_uuid16_t unreadAlertStatusUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = unreadAlertStatusId
};
static constexpr ble_uuid16_t controlPointUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = controlPointId
};
static constexpr ble_uuid16_t ansServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansServiceId};
static constexpr ble_uuid16_t supportedNewAlertCategoryUuid {.u {.type = BLE_UUID_TYPE_16}, .value = supportedNewAlertCategoryId};
static constexpr ble_uuid16_t supportedUnreadAlertCategoryUuid {.u {.type = BLE_UUID_TYPE_16},
.value = supportedUnreadAlertCategoryId};
static constexpr ble_uuid16_t newAlertUuid {.u {.type = BLE_UUID_TYPE_16}, .value = newAlertId};
static constexpr ble_uuid16_t unreadAlertStatusUuid {.u {.type = BLE_UUID_TYPE_16}, .value = unreadAlertStatusId};
static constexpr ble_uuid16_t controlPointUuid {.u {.type = BLE_UUID_TYPE_16}, .value = controlPointId};
uint16_t ansStartHandle = 0;
uint16_t ansEndHandle = 0;
uint16_t supportedNewAlertCategoryHandle = 0;
uint16_t supportedUnreadAlertCategoryHandle = 0;
uint16_t newAlertHandle = 0;
uint16_t newAlertDescriptorHandle = 0;
uint16_t newAlertDefHandle = 0;
uint16_t unreadAlertStatusHandle = 0;
uint16_t controlPointHandle = 0;
bool isDiscovered = false;
Pinetime::System::SystemTask &systemTask;
Pinetime::Controllers::NotificationManager &notificationManager;
std::function<void(uint16_t)> onServiceDiscovered;
bool isCharacteristicDiscovered = false;
bool isDescriptorFound = false;
uint16_t ansStartHandle = 0;
uint16_t ansEndHandle = 0;
uint16_t supportedNewAlertCategoryHandle = 0;
uint16_t supportedUnreadAlertCategoryHandle = 0;
uint16_t newAlertHandle = 0;
uint16_t newAlertDescriptorHandle = 0;
uint16_t newAlertDefHandle = 0;
uint16_t unreadAlertStatusHandle = 0;
uint16_t controlPointHandle = 0;
bool isDiscovered = false;
Pinetime::System::SystemTask& systemTask;
Pinetime::Controllers::NotificationManager& notificationManager;
std::function<void(uint16_t)> onServiceDiscovered;
bool isCharacteristicDiscovered = false;
bool isDescriptorFound = false;
};
}
}

View File

@@ -11,8 +11,7 @@ constexpr ble_uuid16_t AlertNotificationService::ansUuid;
constexpr ble_uuid16_t AlertNotificationService::ansCharUuid;
constexpr ble_uuid128_t AlertNotificationService::notificationEventUuid;
int AlertNotificationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
int AlertNotificationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto anService = static_cast<AlertNotificationService*>(arg);
return anService->OnAlert(conn_handle, attr_handle, ctxt);
}
@@ -26,62 +25,52 @@ void AlertNotificationService::Init() {
ASSERT(res == 0);
}
AlertNotificationService::AlertNotificationService ( System::SystemTask& systemTask, NotificationManager& notificationManager )
: characteristicDefinition{
{
.uuid = (ble_uuid_t *) &ansCharUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE
},
{
.uuid = (ble_uuid_t *) &notificationEventUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &ansUuid,
.characteristics = characteristicDefinition
},
{
0
},
}, systemTask{systemTask}, notificationManager{notificationManager} {
AlertNotificationService::AlertNotificationService(System::SystemTask& systemTask, NotificationManager& notificationManager)
: characteristicDefinition {{.uuid = (ble_uuid_t*) &ansCharUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE},
{.uuid = (ble_uuid_t*) &notificationEventUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &ansUuid,
.characteristics = characteristicDefinition},
{0},
},
systemTask {systemTask},
notificationManager {notificationManager} {
}
int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
constexpr size_t stringTerminatorSize = 1; // end of string '\0'
constexpr size_t headerSize = 3;
const auto maxMessageSize {NotificationManager::MaximumMessageSize()};
const auto maxBufferSize{maxMessageSize + headerSize};
const auto maxBufferSize {maxMessageSize + headerSize};
// Ignore notifications with empty message
const auto packetLen = OS_MBUF_PKTLEN(ctxt->om);
if(packetLen <= headerSize) return 0;
if (packetLen <= headerSize)
return 0;
size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize);
auto messageSize = std::min(maxMessageSize, (bufferSize-headerSize));
auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize));
Categories category;
NotificationManager::Notification notif;
os_mbuf_copydata(ctxt->om, headerSize, messageSize-1, notif.message.data());
os_mbuf_copydata(ctxt->om, headerSize, messageSize - 1, notif.message.data());
os_mbuf_copydata(ctxt->om, 0, 1, &category);
notif.message[messageSize-1] = '\0';
notif.message[messageSize - 1] = '\0';
notif.size = messageSize;
// TODO convert all ANS categories to NotificationController categories
switch(category) {
switch (category) {
case Categories::Call:
notif.category = Pinetime::Controllers::NotificationManager::Categories::IncomingCall;
break;
@@ -99,7 +88,7 @@ int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle
void AlertNotificationService::AcceptIncomingCall() {
auto response = IncomingCallResponses::Answer;
auto *om = ble_hs_mbuf_from_flat(&response, 1);
auto* om = ble_hs_mbuf_from_flat(&response, 1);
uint16_t connectionHandle = systemTask.nimble().connHandle();
@@ -112,7 +101,7 @@ void AlertNotificationService::AcceptIncomingCall() {
void AlertNotificationService::RejectIncomingCall() {
auto response = IncomingCallResponses::Reject;
auto *om = ble_hs_mbuf_from_flat(&response, 1);
auto* om = ble_hs_mbuf_from_flat(&response, 1);
uint16_t connectionHandle = systemTask.nimble().connHandle();
@@ -125,7 +114,7 @@ void AlertNotificationService::RejectIncomingCall() {
void AlertNotificationService::MuteIncomingCall() {
auto response = IncomingCallResponses::Mute;
auto *om = ble_hs_mbuf_from_flat(&response, 1);
auto* om = ble_hs_mbuf_from_flat(&response, 1);
uint16_t connectionHandle = systemTask.nimble().connHandle();

View File

@@ -7,8 +7,9 @@
#undef max
#undef min
//00020001-78fc-48fe-8e23-433b3a1942d0
#define NOTIFICATION_EVENT_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x01, 0x00, 0x02, 0x00}
// 00020001-78fc-48fe-8e23-433b3a1942d0
#define NOTIFICATION_EVENT_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x01, 0x00, 0x02, 0x00 }
namespace Pinetime {
@@ -19,64 +20,49 @@ namespace Pinetime {
class NotificationManager;
class AlertNotificationService {
public:
AlertNotificationService(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager);
void Init();
public:
AlertNotificationService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager);
void Init();
int OnAlert(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnAlert(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
void AcceptIncomingCall();
void RejectIncomingCall();
void MuteIncomingCall();
void AcceptIncomingCall();
void RejectIncomingCall();
void MuteIncomingCall();
enum class IncomingCallResponses : uint8_t {
Reject = 0x00,
Answer = 0x01,
Mute = 0x02
};
enum class IncomingCallResponses : uint8_t { Reject = 0x00, Answer = 0x01, Mute = 0x02 };
private:
enum class Categories : uint8_t {
SimpleAlert = 0x00,
Email = 0x01,
News = 0x02,
Call = 0x03,
MissedCall = 0x04,
MmsSms = 0x05,
VoiceMail = 0x06,
Schedule = 0x07,
HighPrioritizedAlert = 0x08,
InstantMessage = 0x09,
All = 0xff
};
private:
enum class Categories : uint8_t {
SimpleAlert = 0x00,
Email = 0x01,
News = 0x02,
Call = 0x03,
MissedCall = 0x04,
MmsSms = 0x05,
VoiceMail = 0x06,
Schedule = 0x07,
HighPrioritizedAlert = 0x08,
InstantMessage = 0x09,
All = 0xff
};
static constexpr uint16_t ansId {0x1811};
static constexpr uint16_t ansCharId {0x2a46};
static constexpr uint16_t ansId {0x1811};
static constexpr uint16_t ansCharId {0x2a46};
static constexpr ble_uuid16_t ansUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ansId
};
static constexpr ble_uuid16_t ansUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansId};
static constexpr ble_uuid16_t ansCharUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ansCharId
};
static constexpr ble_uuid16_t ansCharUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansCharId};
static constexpr ble_uuid128_t notificationEventUuid {
.u { .type = BLE_UUID_TYPE_128 },
.value = NOTIFICATION_EVENT_SERVICE_UUID_BASE
};
static constexpr ble_uuid128_t notificationEventUuid {.u {.type = BLE_UUID_TYPE_128}, .value = NOTIFICATION_EVENT_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
Pinetime::System::SystemTask &systemTask;
NotificationManager &notificationManager;
Pinetime::System::SystemTask& systemTask;
NotificationManager& notificationManager;
uint16_t eventHandle;
uint16_t eventHandle;
};
}
}

View File

@@ -7,39 +7,26 @@ using namespace Pinetime::Controllers;
constexpr ble_uuid16_t BatteryInformationService::batteryInformationServiceUuid;
constexpr ble_uuid16_t BatteryInformationService::batteryLevelUuid;
int BatteryInformationServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
int BatteryInformationServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto* batteryInformationService = static_cast<BatteryInformationService*>(arg);
return batteryInformationService->OnBatteryServiceRequested(conn_handle, attr_handle, ctxt);
}
BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController) :
batteryController{batteryController},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &batteryLevelUuid,
.access_cb = BatteryInformationServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
.val_handle = &batteryLevelHandle
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &batteryInformationServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
}{
BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController)
: batteryController {batteryController},
characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid,
.access_cb = BatteryInformationServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
.val_handle = &batteryLevelHandle},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &batteryInformationServiceUuid,
.characteristics = characteristicDefinition},
{0},
} {
}
void BatteryInformationService::Init() {
@@ -51,9 +38,10 @@ void BatteryInformationService::Init() {
ASSERT(res == 0);
}
int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle,
ble_gatt_access_ctxt *context) {
if(attributeHandle == batteryLevelHandle) {
int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHandle,
uint16_t attributeHandle,
ble_gatt_access_ctxt* context) {
if (attributeHandle == batteryLevelHandle) {
NRF_LOG_INFO("BATTERY : handle = %d", batteryLevelHandle);
static uint8_t batteryValue = batteryController.PercentRemaining();
int res = os_mbuf_append(context->om, &batteryValue, 1);

View File

@@ -12,33 +12,25 @@ namespace Pinetime {
namespace Controllers {
class Battery;
class BatteryInformationService {
public:
BatteryInformationService(Controllers::Battery& batteryController);
void Init();
public:
BatteryInformationService(Controllers::Battery& batteryController);
void Init();
int
OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
int OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
private:
Controllers::Battery& batteryController;
static constexpr uint16_t batteryInformationServiceId {0x180F};
static constexpr uint16_t batteryLevelId {0x2A19};
private:
Controllers::Battery& batteryController;
static constexpr uint16_t batteryInformationServiceId {0x180F};
static constexpr uint16_t batteryLevelId {0x2A19};
static constexpr ble_uuid16_t batteryInformationServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = batteryInformationServiceId
};
static constexpr ble_uuid16_t batteryInformationServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = batteryInformationServiceId};
static constexpr ble_uuid16_t batteryLevelUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = batteryLevelId
};
static constexpr ble_uuid16_t batteryLevelUuid {.u {.type = BLE_UUID_TYPE_16}, .value = batteryLevelId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t batteryLevelHandle;
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t batteryLevelHandle;
};
}
}

View File

@@ -3,10 +3,10 @@
#include <functional>
namespace Pinetime {
namespace Controllers{
namespace Controllers {
class BleClient {
public:
virtual void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) = 0;
public:
virtual void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) = 0;
};
}
}

View File

@@ -25,5 +25,3 @@ void Ble::FirmwareUpdateTotalBytes(uint32_t totalBytes) {
void Ble::FirmwareUpdateCurrentBytes(uint32_t currentBytes) {
firmwareUpdateCurrentBytes = currentBytes;
}

View File

@@ -6,39 +6,57 @@
namespace Pinetime {
namespace Controllers {
class Ble {
public:
using BleAddress = std::array<uint8_t, 6>;
enum class FirmwareUpdateStates {Idle, Running, Validated, Error};
enum class AddressTypes { Public, Random };
public:
using BleAddress = std::array<uint8_t, 6>;
enum class FirmwareUpdateStates { Idle, Running, Validated, Error };
enum class AddressTypes { Public, Random };
Ble() = default;
bool IsConnected() const {return isConnected;}
void Connect();
void Disconnect();
Ble() = default;
bool IsConnected() const {
return isConnected;
}
void Connect();
void Disconnect();
void StartFirmwareUpdate();
void StopFirmwareUpdate();
void FirmwareUpdateTotalBytes(uint32_t totalBytes);
void FirmwareUpdateCurrentBytes(uint32_t currentBytes);
void State(FirmwareUpdateStates state) { firmwareUpdateState = state; }
void StartFirmwareUpdate();
void StopFirmwareUpdate();
void FirmwareUpdateTotalBytes(uint32_t totalBytes);
void FirmwareUpdateCurrentBytes(uint32_t currentBytes);
void State(FirmwareUpdateStates state) {
firmwareUpdateState = state;
}
bool IsFirmwareUpdating() const { return isFirmwareUpdating; }
uint32_t FirmwareUpdateTotalBytes() const { return firmwareUpdateTotalBytes; }
uint32_t FirmwareUpdateCurrentBytes() const { return firmwareUpdateCurrentBytes; }
FirmwareUpdateStates State() const { return firmwareUpdateState; }
bool IsFirmwareUpdating() const {
return isFirmwareUpdating;
}
uint32_t FirmwareUpdateTotalBytes() const {
return firmwareUpdateTotalBytes;
}
uint32_t FirmwareUpdateCurrentBytes() const {
return firmwareUpdateCurrentBytes;
}
FirmwareUpdateStates State() const {
return firmwareUpdateState;
}
void Address(BleAddress&& addr) { address = addr; }
const BleAddress& Address() const { return address; }
void AddressType(AddressTypes t) { addressType = t;}
private:
bool isConnected = false;
bool isFirmwareUpdating = false;
uint32_t firmwareUpdateTotalBytes = 0;
uint32_t firmwareUpdateCurrentBytes = 0;
FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle;
BleAddress address;
AddressTypes addressType;
void Address(BleAddress&& addr) {
address = addr;
}
const BleAddress& Address() const {
return address;
}
void AddressType(AddressTypes t) {
addressType = t;
}
private:
bool isConnected = false;
bool isFirmwareUpdating = false;
uint32_t firmwareUpdateTotalBytes = 0;
uint32_t firmwareUpdateCurrentBytes = 0;
FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle;
BleAddress address;
AddressTypes addressType;
};
}
}

View File

@@ -9,39 +9,37 @@ constexpr ble_uuid16_t CurrentTimeClient::ctsServiceUuid;
constexpr ble_uuid16_t CurrentTimeClient::currentTimeCharacteristicUuid;
namespace {
int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) {
auto client = static_cast<CurrentTimeClient *>(arg);
int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) {
auto client = static_cast<CurrentTimeClient*>(arg);
return client->OnDiscoveryEvent(conn_handle, error, service);
}
int OnCurrentTimeCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg) {
auto client = static_cast<CurrentTimeClient *>(arg);
int OnCurrentTimeCharacteristicDiscoveredCallback(uint16_t conn_handle,
const struct ble_gatt_error* error,
const struct ble_gatt_chr* chr,
void* arg) {
auto client = static_cast<CurrentTimeClient*>(arg);
return client->OnCharacteristicDiscoveryEvent(conn_handle, error, chr);
}
int CurrentTimeReadCallback(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) {
auto client = static_cast<CurrentTimeClient *>(arg);
int CurrentTimeReadCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) {
auto client = static_cast<CurrentTimeClient*>(arg);
return client->OnCurrentTimeReadResult(conn_handle, error, attr);
}
}
CurrentTimeClient::CurrentTimeClient(DateTime &dateTimeController) : dateTimeController{dateTimeController} {
CurrentTimeClient::CurrentTimeClient(DateTime& dateTimeController) : dateTimeController {dateTimeController} {
}
void CurrentTimeClient::Init() {
}
bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_svc *service) {
bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) {
if (service == nullptr && error->status == BLE_HS_EDONE) {
if (isDiscovered) {
NRF_LOG_INFO("CTS found, starting characteristics discovery");
ble_gattc_disc_all_chrs(connectionHandle, ctsStartHandle, ctsEndHandle,
OnCurrentTimeCharacteristicDiscoveredCallback, this);
ble_gattc_disc_all_chrs(connectionHandle, ctsStartHandle, ctsEndHandle, OnCurrentTimeCharacteristicDiscoveredCallback, this);
} else {
NRF_LOG_INFO("CTS not found");
onServiceDiscovered(connectionHandle);
@@ -49,7 +47,7 @@ bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_ga
return true;
}
if (service != nullptr && ble_uuid_cmp(((ble_uuid_t *) &ctsServiceUuid), &service->uuid.u) == 0) {
if (service != nullptr && ble_uuid_cmp(((ble_uuid_t*) &ctsServiceUuid), &service->uuid.u) == 0) {
NRF_LOG_INFO("CTS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle);
isDiscovered = true;
ctsStartHandle = service->start_handle;
@@ -59,8 +57,9 @@ bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_ga
return false;
}
int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic) {
int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle,
const ble_gatt_error* error,
const ble_gatt_chr* characteristic) {
if (characteristic == nullptr && error->status == BLE_HS_EDONE) {
if (isCharacteristicDiscovered) {
NRF_LOG_INFO("CTS Characteristic discovery complete, fetching time");
@@ -73,8 +72,7 @@ int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, cons
return 0;
}
if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &currentTimeCharacteristicUuid), &characteristic->uuid.u) == 0) {
if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &currentTimeCharacteristicUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("CTS Characteristic discovered : 0x%x", characteristic->val_handle);
isCharacteristicDiscovered = true;
currentTimeHandle = characteristic->val_handle;
@@ -82,17 +80,15 @@ int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, cons
return 0;
}
int CurrentTimeClient::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error,
const ble_gatt_attr *attribute) {
int CurrentTimeClient::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_attr* attribute) {
if (error->status == 0) {
// TODO check that attribute->handle equals the handle discovered in OnCharacteristicDiscoveryEvent
CtsData result;
os_mbuf_copydata(attribute->om, 0, sizeof(CtsData), &result);
NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year,
result.month, result.dayofmonth,
result.hour, result.minute, result.second);
dateTimeController.SetTime(result.year, result.month, result.dayofmonth,
0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
NRF_LOG_INFO(
"Received data: %d-%d-%d %d:%d:%d", result.year, result.month, result.dayofmonth, result.hour, result.minute, result.second);
dateTimeController.SetTime(
result.year, result.month, result.dayofmonth, 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
} else {
NRF_LOG_INFO("Error retrieving current time: %d", error->status);
}

View File

@@ -8,54 +8,51 @@
#include "BleClient.h"
namespace Pinetime {
namespace Controllers {
class DateTime;
namespace Controllers {
class DateTime;
class CurrentTimeClient : public BleClient {
class CurrentTimeClient : public BleClient {
public:
explicit CurrentTimeClient(DateTime& dateTimeController);
void Init();
void Reset();
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error, const ble_gatt_svc *service);
int OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error, const ble_gatt_attr *attribute);
static constexpr const ble_uuid16_t* Uuid() { return &CurrentTimeClient::ctsServiceUuid; }
static constexpr const ble_uuid16_t* CurrentTimeCharacteristicUuid() { return &CurrentTimeClient::currentTimeCharacteristicUuid; }
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
explicit CurrentTimeClient(DateTime& dateTimeController);
void Init();
void Reset();
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service);
int OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_attr* attribute);
static constexpr const ble_uuid16_t* Uuid() {
return &CurrentTimeClient::ctsServiceUuid;
}
static constexpr const ble_uuid16_t* CurrentTimeCharacteristicUuid() {
return &CurrentTimeClient::currentTimeCharacteristicUuid;
}
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
private:
typedef struct __attribute__((packed)) {
uint16_t year;
uint8_t month;
uint8_t dayofmonth;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t millis;
uint8_t reason;
} CtsData;
private:
typedef struct __attribute__((packed)) {
uint16_t year;
uint8_t month;
uint8_t dayofmonth;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t millis;
uint8_t reason;
} CtsData;
static constexpr uint16_t ctsServiceId {0x1805};
static constexpr uint16_t currentTimeCharacteristicId {0x2a2b};
static constexpr uint16_t ctsServiceId {0x1805};
static constexpr uint16_t currentTimeCharacteristicId {0x2a2b};
static constexpr ble_uuid16_t ctsServiceUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsServiceId
};
static constexpr ble_uuid16_t currentTimeCharacteristicUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = currentTimeCharacteristicId
};
static constexpr ble_uuid16_t ctsServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsServiceId};
static constexpr ble_uuid16_t currentTimeCharacteristicUuid {.u {.type = BLE_UUID_TYPE_16}, .value = currentTimeCharacteristicId};
DateTime& dateTimeController;
bool isDiscovered = false;
uint16_t ctsStartHandle;
uint16_t ctsEndHandle;
DateTime& dateTimeController;
bool isDiscovered = false;
uint16_t ctsStartHandle;
uint16_t ctsEndHandle;
bool isCharacteristicDiscovered = false;
uint16_t currentTimeHandle;
std::function<void(uint16_t)> onServiceDiscovered;
};
}
bool isCharacteristicDiscovered = false;
uint16_t currentTimeHandle;
std::function<void(uint16_t)> onServiceDiscovered;
};
}
}

View File

@@ -7,8 +7,7 @@ using namespace Pinetime::Controllers;
constexpr ble_uuid16_t CurrentTimeService::ctsUuid;
constexpr ble_uuid16_t CurrentTimeService::ctChrUuid;
int CTSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
int CTSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto cts = static_cast<CurrentTimeService*>(arg);
return cts->OnTimeAccessed(conn_handle, attr_handle, ctxt);
}
@@ -22,22 +21,19 @@ void CurrentTimeService::Init() {
ASSERT(res == 0);
}
int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
NRF_LOG_INFO("Setting time...");
NRF_LOG_INFO("Setting time...");
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
CtsData result;
os_mbuf_copydata(ctxt->om, 0, sizeof(CtsData), &result);
NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year,
result.month, result.dayofmonth,
result.hour, result.minute, result.second);
NRF_LOG_INFO(
"Received data: %d-%d-%d %d:%d:%d", result.year, result.month, result.dayofmonth, result.hour, result.minute, result.second);
m_dateTimeController.SetTime(result.year, result.month, result.dayofmonth,
0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
m_dateTimeController.SetTime(
result.year, result.month, result.dayofmonth, 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
CtsData currentDateTime;
@@ -49,39 +45,26 @@ int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handl
currentDateTime.second = m_dateTimeController.Seconds();
currentDateTime.millis = 0;
int res = os_mbuf_append(ctxt->om, &currentDateTime, sizeof(CtsData));
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
return 0;
}
CurrentTimeService::CurrentTimeService(DateTime &dateTimeController) :
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &ctChrUuid,
.access_cb = CTSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &ctsUuid,
.characteristics = characteristicDefinition
},
{
0
},
}, m_dateTimeController{dateTimeController} {
CurrentTimeService::CurrentTimeService(DateTime& dateTimeController)
: characteristicDefinition {{.uuid = (ble_uuid_t*) &ctChrUuid,
.access_cb = CTSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &ctsUuid,
.characteristics = characteristicDefinition},
{0},
},
m_dateTimeController {dateTimeController} {
}

View File

@@ -12,42 +12,35 @@
namespace Pinetime {
namespace Controllers {
class CurrentTimeService {
public:
CurrentTimeService(DateTime &dateTimeController);
void Init();
public:
CurrentTimeService(DateTime& dateTimeController);
void Init();
int OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
private:
static constexpr uint16_t ctsId {0x1805};
static constexpr uint16_t ctsCharId {0x2a2b};
private:
static constexpr uint16_t ctsId {0x1805};
static constexpr uint16_t ctsCharId {0x2a2b};
static constexpr ble_uuid16_t ctsUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsId
};
static constexpr ble_uuid16_t ctsUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsId};
static constexpr ble_uuid16_t ctChrUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsCharId
};
static constexpr ble_uuid16_t ctChrUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsCharId};
struct ble_gatt_chr_def characteristicDefinition[2];
struct ble_gatt_svc_def serviceDefinition[2];
struct ble_gatt_chr_def characteristicDefinition[2];
struct ble_gatt_svc_def serviceDefinition[2];
typedef struct __attribute__((packed)) {
uint16_t year;
uint8_t month;
uint8_t dayofmonth;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t millis;
uint8_t reason;
} CtsData;
typedef struct __attribute__((packed)) {
uint16_t year;
uint8_t month;
uint8_t dayofmonth;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t millis;
uint8_t reason;
} CtsData;
DateTime &m_dateTimeController;
DateTime& m_dateTimeController;
};
}
}

View File

@@ -10,8 +10,7 @@ constexpr ble_uuid16_t DeviceInformationService::deviceInfoUuid;
constexpr ble_uuid16_t DeviceInformationService::hwRevisionUuid;
constexpr ble_uuid16_t DeviceInformationService::swRevisionUuid;
int DeviceInformationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
int DeviceInformationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto deviceInformationService = static_cast<DeviceInformationService*>(arg);
return deviceInformationService->OnDeviceInfoRequested(conn_handle, attr_handle, ctxt);
}
@@ -25,10 +24,8 @@ void DeviceInformationService::Init() {
ASSERT(res == 0);
}
int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
const char *str;
int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
const char* str;
switch (ble_uuid_u16(ctxt->chr->uuid)) {
case manufacturerNameId:
@@ -57,60 +54,49 @@ int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
DeviceInformationService::DeviceInformationService() :
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &manufacturerNameUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t *) &modelNumberUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t *) &serialNumberUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t *) &fwRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t *) &hwRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t *) &swRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &deviceInfoUuid,
.characteristics = characteristicDefinition
},
{
0
},
}
{
DeviceInformationService::DeviceInformationService()
: characteristicDefinition {{
.uuid = (ble_uuid_t*) &manufacturerNameUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t*) &modelNumberUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t*) &serialNumberUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t*) &fwRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t*) &hwRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
.uuid = (ble_uuid_t*) &swRevisionUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &deviceInfoUuid,
.characteristics = characteristicDefinition},
{0},
} {
}

View File

@@ -9,69 +9,44 @@
namespace Pinetime {
namespace Controllers {
class DeviceInformationService {
public:
DeviceInformationService();
void Init();
public:
DeviceInformationService();
void Init();
int OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
private:
static constexpr uint16_t deviceInfoId {0x180a};
static constexpr uint16_t manufacturerNameId {0x2a29};
static constexpr uint16_t modelNumberId {0x2a24};
static constexpr uint16_t serialNumberId {0x2a25};
static constexpr uint16_t fwRevisionId {0x2a26};
static constexpr uint16_t hwRevisionId {0x2a27};
static constexpr uint16_t swRevisionId {0x2a28};
private:
static constexpr uint16_t deviceInfoId {0x180a};
static constexpr uint16_t manufacturerNameId {0x2a29};
static constexpr uint16_t modelNumberId {0x2a24};
static constexpr uint16_t serialNumberId {0x2a25};
static constexpr uint16_t fwRevisionId {0x2a26};
static constexpr uint16_t hwRevisionId {0x2a27};
static constexpr uint16_t swRevisionId {0x2a28};
static constexpr const char* manufacturerName = "PINE64";
static constexpr const char* modelNumber = "PineTime";
static constexpr const char* hwRevision = "1.0.0";
static constexpr const char* serialNumber = "0";
static constexpr const char* fwRevision = Version::VersionString();
static constexpr const char* swRevision = "InfiniTime";
static constexpr const char* manufacturerName = "PINE64";
static constexpr const char* modelNumber = "PineTime";
static constexpr const char* hwRevision = "1.0.0";
static constexpr const char* serialNumber = "0";
static constexpr const char* fwRevision = Version::VersionString();
static constexpr const char* swRevision = "InfiniTime";
static constexpr ble_uuid16_t deviceInfoUuid {.u {.type = BLE_UUID_TYPE_16}, .value = deviceInfoId};
static constexpr ble_uuid16_t deviceInfoUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = deviceInfoId
};
static constexpr ble_uuid16_t manufacturerNameUuid {.u {.type = BLE_UUID_TYPE_16}, .value = manufacturerNameId};
static constexpr ble_uuid16_t manufacturerNameUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = manufacturerNameId
};
static constexpr ble_uuid16_t modelNumberUuid {.u {.type = BLE_UUID_TYPE_16}, .value = modelNumberId};
static constexpr ble_uuid16_t modelNumberUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = modelNumberId
};
static constexpr ble_uuid16_t serialNumberUuid {.u {.type = BLE_UUID_TYPE_16}, .value = serialNumberId};
static constexpr ble_uuid16_t serialNumberUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = serialNumberId
};
static constexpr ble_uuid16_t fwRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = fwRevisionId};
static constexpr ble_uuid16_t fwRevisionUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = fwRevisionId
};
static constexpr ble_uuid16_t hwRevisionUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = hwRevisionId
};
static constexpr ble_uuid16_t swRevisionUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = swRevisionId
};
struct ble_gatt_chr_def characteristicDefinition[7];
struct ble_gatt_svc_def serviceDefinition[2];
static constexpr ble_uuid16_t hwRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = hwRevisionId};
static constexpr ble_uuid16_t swRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = swRevisionId};
struct ble_gatt_chr_def characteristicDefinition[7];
struct ble_gatt_svc_def serviceDefinition[2];
};
}
}

View File

@@ -11,67 +11,60 @@ constexpr ble_uuid128_t DfuService::controlPointCharacteristicUuid;
constexpr ble_uuid128_t DfuService::revisionCharacteristicUuid;
constexpr ble_uuid128_t DfuService::packetCharacteristicUuid;
int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg) {
auto dfuService = static_cast<DfuService *>(arg);
int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto dfuService = static_cast<DfuService*>(arg);
return dfuService->OnServiceData(conn_handle, attr_handle, ctxt);
}
void NotificationTimerCallback(TimerHandle_t xTimer) {
auto notificationManager = static_cast<DfuService::NotificationManager *>(pvTimerGetTimerID(xTimer));
auto notificationManager = static_cast<DfuService::NotificationManager*>(pvTimerGetTimerID(xTimer));
notificationManager->OnNotificationTimer();
}
void TimeoutTimerCallback(TimerHandle_t xTimer) {
auto dfuService = static_cast<DfuService *>(pvTimerGetTimerID(xTimer));
auto dfuService = static_cast<DfuService*>(pvTimerGetTimerID(xTimer));
dfuService->OnTimeout();
}
DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
Pinetime::Drivers::SpiNorFlash &spiNorFlash) :
systemTask{systemTask},
bleController{bleController},
dfuImage{spiNorFlash},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &packetCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
.val_handle = nullptr,
},
{
.uuid = (ble_uuid_t *) &controlPointCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY,
.val_handle = nullptr,
},
{
.uuid = (ble_uuid_t *) &revisionCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
.val_handle = &revision,
DfuService::DfuService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash)
: systemTask {systemTask},
bleController {bleController},
dfuImage {spiNorFlash},
characteristicDefinition {{
.uuid = (ble_uuid_t*) &packetCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
.val_handle = nullptr,
},
{
.uuid = (ble_uuid_t*) &controlPointCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY,
.val_handle = nullptr,
},
{
.uuid = (ble_uuid_t*) &revisionCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
.val_handle = &revision,
},
{
0
}
},
{0}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &serviceUuid,
.characteristics = characteristicDefinition
},
{
0
},
} {
timeoutTimer = xTimerCreate ("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback);
},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &serviceUuid,
.characteristics = characteristicDefinition},
{0},
} {
timeoutTimer = xTimerCreate("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback);
}
void DfuService::Init() {
@@ -83,55 +76,54 @@ void DfuService::Init() {
ASSERT(res == 0);
}
int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) {
if(bleController.IsFirmwareUpdating()){
int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context) {
if (bleController.IsFirmwareUpdating()) {
xTimerStart(timeoutTimer, 0);
}
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &packetCharacteristicUuid, nullptr,
&packetCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &controlPointCharacteristicUuid, nullptr,
&controlPointCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &revisionCharacteristicUuid, nullptr,
&revisionCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &packetCharacteristicUuid, nullptr, &packetCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &controlPointCharacteristicUuid, nullptr, &controlPointCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &revisionCharacteristicUuid, nullptr, &revisionCharacteristicHandle);
if (attributeHandle == packetCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
return WritePacketHandler(connectionHandle, context->om);
else return 0;
else
return 0;
} else if (attributeHandle == controlPointCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
return ControlPointHandler(connectionHandle, context->om);
else return 0;
else
return 0;
} else if (attributeHandle == revisionCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_READ_CHR)
return SendDfuRevision(context->om);
else return 0;
else
return 0;
} else {
NRF_LOG_INFO("[DFU] Unknown Characteristic : %d", attributeHandle);
return 0;
}
}
int DfuService::SendDfuRevision(os_mbuf *om) const {
int DfuService::SendDfuRevision(os_mbuf* om) const {
int res = os_mbuf_append(om, &revision, sizeof(revision));
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) {
switch (state) {
case States::Start: {
softdeviceSize = om->om_data[0] + (om->om_data[1] << 8) + (om->om_data[2] << 16) + (om->om_data[3] << 24);
bootloaderSize = om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
applicationSize = om->om_data[8] + (om->om_data[9] << 8) + (om->om_data[10] << 16) + (om->om_data[11] << 24);
bleController.FirmwareUpdateTotalBytes(applicationSize);
NRF_LOG_INFO("[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize,
bootloaderSize, applicationSize);
NRF_LOG_INFO(
"[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize, bootloaderSize, applicationSize);
dfuImage.Erase();
uint8_t data[]{16, 1, 1};
uint8_t data[] {16, 1, 1};
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
state = States::Init;
}
@@ -139,19 +131,22 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
case States::Init: {
uint16_t deviceType = om->om_data[0] + (om->om_data[1] << 8);
uint16_t deviceRevision = om->om_data[2] + (om->om_data[3] << 8);
uint32_t applicationVersion =
om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
uint32_t applicationVersion = om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
uint16_t softdeviceArrayLength = om->om_data[8] + (om->om_data[9] << 8);
uint16_t sd[softdeviceArrayLength];
for (int i = 0; i < softdeviceArrayLength; i++) {
sd[i] = om->om_data[10 + (i * 2)] + (om->om_data[10 + (i * 2) + 1] << 8);
}
expectedCrc =
om->om_data[10 + (softdeviceArrayLength * 2)] + (om->om_data[10 + (softdeviceArrayLength * 2) + 1] << 8);
expectedCrc = om->om_data[10 + (softdeviceArrayLength * 2)] + (om->om_data[10 + (softdeviceArrayLength * 2) + 1] << 8);
NRF_LOG_INFO(
"[DFU] -> Init data received : deviceType = %d, deviceRevision = %d, applicationVersion = %d, nb SD = %d, First SD = %d, CRC = %u",
deviceType, deviceRevision, applicationVersion, softdeviceArrayLength, sd[0], expectedCrc);
"[DFU] -> Init data received : deviceType = %d, deviceRevision = %d, applicationVersion = %d, nb SD = %d, First SD = %d, CRC = %u",
deviceType,
deviceRevision,
applicationVersion,
softdeviceArrayLength,
sd[0],
expectedCrc);
return 0;
}
@@ -163,16 +158,18 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
bleController.FirmwareUpdateCurrentBytes(bytesReceived);
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)};
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);
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5);
}
if (dfuImage.IsComplete()) {
uint8_t data[3]{static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
static_cast<uint8_t>(ErrorCodes::NoError)};
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ReceiveFirmwareImage),
static_cast<uint8_t>(ErrorCodes::NoError)};
NRF_LOG_INFO("[DFU] -> Send packet notification : all bytes received!");
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 3);
state = States::Validate;
@@ -186,7 +183,7 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
return 0;
}
int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
auto opcode = static_cast<Opcodes>(om->om_data[0]);
NRF_LOG_INFO("[DFU] -> ControlPointHandler");
@@ -214,8 +211,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Start DFU, mode %d not supported!", imageType);
return 0;
}
}
break;
} break;
case Opcodes::InitDFUParameters: {
if (state != States::Init) {
NRF_LOG_INFO("[DFU] -> Init DFU requested, but we are not in Init state");
@@ -225,11 +221,9 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Init DFU parameters %s", isInitComplete ? " complete" : " not complete");
if (isInitComplete) {
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::InitDFUParameters),
(isInitComplete ? uint8_t{1} : uint8_t{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;
}
@@ -257,26 +251,22 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Validate firmware image requested -- %d", connectionHandle);
if(dfuImage.Validate()){
if (dfuImage.Validate()) {
state = States::Validated;
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
NRF_LOG_INFO("Image OK");
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(ErrorCodes::NoError)
};
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 {
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
NRF_LOG_INFO("Image Error : bad CRC");
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(ErrorCodes::CrcError)
};
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);
}
@@ -318,11 +308,11 @@ void DfuService::Reset() {
}
DfuService::NotificationManager::NotificationManager() {
timer = xTimerCreate ("notificationTimer", 1000, pdFALSE, this, NotificationTimerCallback);
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)
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;
@@ -334,14 +324,14 @@ bool DfuService::NotificationManager::AsyncSend(uint16_t connection, uint16_t ch
}
void DfuService::NotificationManager::OnNotificationTimer() {
if(size > 0) {
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);
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);
}
@@ -354,27 +344,29 @@ void DfuService::NotificationManager::Reset() {
}
void DfuService::DfuImage::Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc) {
if(chunkSize != 20) return;
if (chunkSize != 20)
return;
this->chunkSize = chunkSize;
this->totalSize = totalSize;
this->expectedCrc = expectedCrc;
this->ready = true;
}
void DfuService::DfuImage::Append(uint8_t *data, size_t size) {
if(!ready) return;
void DfuService::DfuImage::Append(uint8_t* data, size_t size) {
if (!ready)
return;
ASSERT(size <= 20);
std::memcpy(tempBuffer + bufferWriteIndex, data, size);
bufferWriteIndex += size;
if(bufferWriteIndex == bufferSize) {
if (bufferWriteIndex == bufferSize) {
spiNorFlash.Write(writeOffset + totalWriteIndex, tempBuffer, bufferWriteIndex);
totalWriteIndex += bufferWriteIndex;
bufferWriteIndex = 0;
}
if(bufferWriteIndex > 0 && totalWriteIndex + bufferWriteIndex == totalSize) {
if (bufferWriteIndex > 0 && totalWriteIndex + bufferWriteIndex == totalSize) {
spiNorFlash.Write(writeOffset + totalWriteIndex, tempBuffer, bufferWriteIndex);
totalWriteIndex += bufferWriteIndex;
if (totalSize < maxSize)
@@ -383,15 +375,16 @@ void DfuService::DfuImage::Append(uint8_t *data, size_t size) {
}
void DfuService::DfuImage::WriteMagicNumber() {
uint32_t magic[4] = { // TODO When this variable is a static constexpr, the values written to the memory are not correct. Why?
0xf395c277,
0x7fefd260,
0x0f505235,
0x8079b62c,
uint32_t magic[4] = {
// TODO When this variable is a static constexpr, the values written to the memory are not correct. Why?
0xf395c277,
0x7fefd260,
0x0f505235,
0x8079b62c,
};
uint32_t offset = writeOffset + (maxSize - (4 * sizeof(uint32_t)));
spiNorFlash.Write(offset, reinterpret_cast<const uint8_t *>(magic), 4 * sizeof(uint32_t));
spiNorFlash.Write(offset, reinterpret_cast<const uint8_t*>(magic), 4 * sizeof(uint32_t));
}
void DfuService::DfuImage::Erase() {
@@ -421,7 +414,7 @@ bool DfuService::DfuImage::Validate() {
return (crc == expectedCrc);
}
uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc) {
uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const* p_data, uint32_t size, uint16_t const* p_crc) {
uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc;
for (uint32_t i = 0; i < size; i++) {
@@ -436,6 +429,7 @@ uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const *p_data, uint32_t size,
}
bool DfuService::DfuImage::IsComplete() {
if(!ready) return false;
if (!ready)
return false;
return totalWriteIndex == totalSize;
}

View File

@@ -20,146 +20,139 @@ namespace Pinetime {
class Ble;
class DfuService {
public:
DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
Pinetime::Drivers::SpiNorFlash &spiNorFlash);
void Init();
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
void OnTimeout();
public:
DfuService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash);
void Init();
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
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();
class NotificationManager {
};
class DfuImage {
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();
};
class DfuImage {
public:
DfuImage(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash{spiNorFlash} {}
void Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc);
void Erase();
void Append(uint8_t* data, size_t size);
bool Validate();
bool IsComplete();
DfuImage(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
}
void Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc);
void Erase();
void Append(uint8_t* data, size_t size);
bool Validate();
bool IsComplete();
private:
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
static constexpr size_t bufferSize = 200;
bool ready = false;
size_t chunkSize = 0;
size_t totalSize = 0;
size_t maxSize = 475136;
size_t bufferWriteIndex = 0;
size_t totalWriteIndex = 0;
static constexpr size_t writeOffset = 0x40000;
uint8_t tempBuffer[bufferSize];
uint16_t expectedCrc = 0;
void WriteMagicNumber();
uint16_t ComputeCrc(uint8_t const *p_data, uint32_t size, uint16_t const *p_crc);
};
private:
Pinetime::System::SystemTask &systemTask;
Pinetime::Controllers::Ble &bleController;
DfuImage dfuImage;
NotificationManager notificationManager;
static constexpr uint16_t dfuServiceId{0x1530};
static constexpr uint16_t packetCharacteristicId{0x1532};
static constexpr uint16_t controlPointCharacteristicId{0x1531};
static constexpr uint16_t revisionCharacteristicId{0x1534};
uint16_t revision{0x0008};
static constexpr ble_uuid128_t serviceUuid{
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}
};
static constexpr ble_uuid128_t packetCharacteristicUuid{
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00}
};
static constexpr ble_uuid128_t controlPointCharacteristicUuid{
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00}
};
static constexpr ble_uuid128_t revisionCharacteristicUuid{
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00}
};
struct ble_gatt_chr_def characteristicDefinition[4];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t packetCharacteristicHandle;
uint16_t controlPointCharacteristicHandle;
uint16_t revisionCharacteristicHandle;
enum class States : uint8_t {
Idle, Init, Start, Data, Validate, Validated
};
States state = States::Idle;
enum class ImageTypes : uint8_t {
NoImage = 0x00,
SoftDevice = 0x01,
Bootloader = 0x02,
SoftDeviceAndBootloader = 0x03,
Application = 0x04
};
enum class Opcodes : uint8_t {
StartDFU = 0x01,
InitDFUParameters = 0x02,
ReceiveFirmwareImage = 0x03,
ValidateFirmware = 0x04,
ActivateImageAndReset = 0x05,
PacketReceiptNotificationRequest = 0x08,
Response = 0x10,
PacketReceiptNotification = 0x11
};
enum class ErrorCodes {
NoError = 0x01,
InvalidState = 0x02,
NotSupported = 0x03,
DataSizeExceedsLimits = 0x04,
CrcError = 0x05,
OperationFailed = 0x06
};
uint8_t nbPacketsToNotify = 0;
uint32_t nbPacketReceived = 0;
uint32_t bytesReceived = 0;
uint32_t softdeviceSize = 0;
uint32_t bootloaderSize = 0;
uint32_t applicationSize = 0;
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
static constexpr size_t bufferSize = 200;
bool ready = false;
size_t chunkSize = 0;
size_t totalSize = 0;
size_t maxSize = 475136;
size_t bufferWriteIndex = 0;
size_t totalWriteIndex = 0;
static constexpr size_t writeOffset = 0x40000;
uint8_t tempBuffer[bufferSize];
uint16_t expectedCrc = 0;
int SendDfuRevision(os_mbuf *om) const;
int WritePacketHandler(uint16_t connectionHandle, os_mbuf *om);
int ControlPointHandler(uint16_t connectionHandle, os_mbuf *om);
void WriteMagicNumber();
uint16_t ComputeCrc(uint8_t const* p_data, uint32_t size, uint16_t const* p_crc);
};
TimerHandle_t timeoutTimer;
private:
Pinetime::System::SystemTask& systemTask;
Pinetime::Controllers::Ble& bleController;
DfuImage dfuImage;
NotificationManager notificationManager;
static constexpr uint16_t dfuServiceId {0x1530};
static constexpr uint16_t packetCharacteristicId {0x1532};
static constexpr uint16_t controlPointCharacteristicId {0x1531};
static constexpr uint16_t revisionCharacteristicId {0x1534};
uint16_t revision {0x0008};
static constexpr ble_uuid128_t serviceUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t packetCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t controlPointCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t revisionCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00}};
struct ble_gatt_chr_def characteristicDefinition[4];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t packetCharacteristicHandle;
uint16_t controlPointCharacteristicHandle;
uint16_t revisionCharacteristicHandle;
enum class States : uint8_t { Idle, Init, Start, Data, Validate, Validated };
States state = States::Idle;
enum class ImageTypes : uint8_t {
NoImage = 0x00,
SoftDevice = 0x01,
Bootloader = 0x02,
SoftDeviceAndBootloader = 0x03,
Application = 0x04
};
enum class Opcodes : uint8_t {
StartDFU = 0x01,
InitDFUParameters = 0x02,
ReceiveFirmwareImage = 0x03,
ValidateFirmware = 0x04,
ActivateImageAndReset = 0x05,
PacketReceiptNotificationRequest = 0x08,
Response = 0x10,
PacketReceiptNotification = 0x11
};
enum class ErrorCodes {
NoError = 0x01,
InvalidState = 0x02,
NotSupported = 0x03,
DataSizeExceedsLimits = 0x04,
CrcError = 0x05,
OperationFailed = 0x06
};
uint8_t nbPacketsToNotify = 0;
uint32_t nbPacketReceived = 0;
uint32_t bytesReceived = 0;
uint32_t softdeviceSize = 0;
uint32_t bootloaderSize = 0;
uint32_t applicationSize = 0;
uint16_t expectedCrc = 0;
int SendDfuRevision(os_mbuf* om) const;
int WritePacketHandler(uint16_t connectionHandle, os_mbuf* om);
int ControlPointHandler(uint16_t connectionHandle, os_mbuf* om);
TimerHandle_t timeoutTimer;
};
}
}

View File

@@ -8,39 +8,29 @@ constexpr ble_uuid16_t HeartRateService::heartRateServiceUuid;
constexpr ble_uuid16_t HeartRateService::heartRateMeasurementUuid;
namespace {
int HeartRateServiceServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
int HeartRateServiceServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto* heartRateService = static_cast<HeartRateService*>(arg);
return heartRateService->OnHeartRateRequested(conn_handle, attr_handle, ctxt);
}
}
// TODO Refactoring - remove dependency to SystemTask
HeartRateService::HeartRateService(Pinetime::System::SystemTask &system, Controllers::HeartRateController& heartRateController) :
system{system},
heartRateController{heartRateController},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &heartRateMeasurementUuid,
.access_cb = HeartRateServiceServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &heartRateMeasurementHandle
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &heartRateServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
}{
HeartRateService::HeartRateService(Pinetime::System::SystemTask& system, Controllers::HeartRateController& heartRateController)
: system {system},
heartRateController {heartRateController},
characteristicDefinition {{.uuid = (ble_uuid_t*) &heartRateMeasurementUuid,
.access_cb = HeartRateServiceServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &heartRateMeasurementHandle},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &heartRateServiceUuid,
.characteristics = characteristicDefinition},
{0},
} {
// TODO refactor to prevent this loop dependency (service depends on controller and controller depends on service)
heartRateController.SetService(this);
}
@@ -54,9 +44,8 @@ void HeartRateService::Init() {
ASSERT(res == 0);
}
int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle,
ble_gatt_access_ctxt *context) {
if(attributeHandle == heartRateMeasurementHandle) {
int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context) {
if (attributeHandle == heartRateMeasurementHandle) {
NRF_LOG_INFO("HEARTRATE : handle = %d", heartRateMeasurementHandle);
uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value
@@ -68,7 +57,7 @@ int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t a
void HeartRateService::OnNewHeartRateValue(uint8_t heartRateValue) {
uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value
auto *om = ble_hs_mbuf_from_flat(buffer, 2);
auto* om = ble_hs_mbuf_from_flat(buffer, 2);
uint16_t connectionHandle = system.nimble().connHandle();

View File

@@ -12,33 +12,26 @@ namespace Pinetime {
namespace Controllers {
class HeartRateController;
class HeartRateService {
public:
HeartRateService(Pinetime::System::SystemTask &system, Controllers::HeartRateController& heartRateController);
void Init();
int OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
void OnNewHeartRateValue(uint8_t hearRateValue);
public:
HeartRateService(Pinetime::System::SystemTask& system, Controllers::HeartRateController& heartRateController);
void Init();
int OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
void OnNewHeartRateValue(uint8_t hearRateValue);
private:
Pinetime::System::SystemTask &system;
Controllers::HeartRateController& heartRateController;
static constexpr uint16_t heartRateServiceId {0x180D};
static constexpr uint16_t heartRateMeasurementId {0x2A37};
private:
Pinetime::System::SystemTask& system;
Controllers::HeartRateController& heartRateController;
static constexpr uint16_t heartRateServiceId {0x180D};
static constexpr uint16_t heartRateMeasurementId {0x2A37};
static constexpr ble_uuid16_t heartRateServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = heartRateServiceId
};
static constexpr ble_uuid16_t heartRateServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = heartRateServiceId};
static constexpr ble_uuid16_t heartRateMeasurementUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = heartRateMeasurementId
};
static constexpr ble_uuid16_t heartRateMeasurementUuid {.u {.type = BLE_UUID_TYPE_16}, .value = heartRateMeasurementId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t heartRateMeasurementHandle;
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t heartRateMeasurementHandle;
};
}
}

View File

@@ -9,49 +9,42 @@ constexpr ble_uuid16_t ImmediateAlertService::immediateAlertServiceUuid;
constexpr ble_uuid16_t ImmediateAlertService::alertLevelUuid;
namespace {
int AlertLevelCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
auto *immediateAlertService = static_cast<ImmediateAlertService *>(arg);
int AlertLevelCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto* immediateAlertService = static_cast<ImmediateAlertService*>(arg);
return immediateAlertService->OnAlertLevelChanged(conn_handle, attr_handle, ctxt);
}
const char* ToString(ImmediateAlertService::Levels level) {
switch (level) {
case ImmediateAlertService::Levels::NoAlert: return "Alert : None";
case ImmediateAlertService::Levels::HighAlert: return "Alert : High";
case ImmediateAlertService::Levels::MildAlert: return "Alert : Mild";
default: return "";
case ImmediateAlertService::Levels::NoAlert:
return "Alert : None";
case ImmediateAlertService::Levels::HighAlert:
return "Alert : High";
case ImmediateAlertService::Levels::MildAlert:
return "Alert : Mild";
default:
return "";
}
}
}
ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager) :
systemTask{systemTask},
notificationManager{notificationManager},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &alertLevelUuid,
.access_cb = AlertLevelCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
.val_handle = &alertLevelHandle
},
{
0
}
},
serviceDefinition{
{
/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &immediateAlertServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
}{
ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager)
: systemTask {systemTask},
notificationManager {notificationManager},
characteristicDefinition {{.uuid = (ble_uuid_t*) &alertLevelUuid,
.access_cb = AlertLevelCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
.val_handle = &alertLevelHandle},
{0}},
serviceDefinition {
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &immediateAlertServiceUuid,
.characteristics = characteristicDefinition},
{0},
} {
}
void ImmediateAlertService::Init() {
@@ -63,9 +56,9 @@ void ImmediateAlertService::Init() {
ASSERT(res == 0);
}
int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context) {
if(attributeHandle == alertLevelHandle) {
if(context->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context) {
if (attributeHandle == alertLevelHandle) {
if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
auto alertLevel = static_cast<Levels>(context->om->om_data[0]);
auto* alertString = ToString(alertLevel);

View File

@@ -12,39 +12,28 @@ namespace Pinetime {
namespace Controllers {
class NotificationManager;
class ImmediateAlertService {
public:
enum class Levels : uint8_t {
NoAlert = 0,
MildAlert = 1,
HighAlert = 2
};
public:
enum class Levels : uint8_t { NoAlert = 0, MildAlert = 1, HighAlert = 2 };
ImmediateAlertService(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager);
void Init();
int OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
ImmediateAlertService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager);
void Init();
int OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
private:
Pinetime::System::SystemTask& systemTask;
NotificationManager& notificationManager;
private:
Pinetime::System::SystemTask& systemTask;
NotificationManager& notificationManager;
static constexpr uint16_t immediateAlertServiceId {0x1802};
static constexpr uint16_t alertLevelId {0x2A06};
static constexpr uint16_t immediateAlertServiceId {0x1802};
static constexpr uint16_t alertLevelId {0x2A06};
static constexpr ble_uuid16_t immediateAlertServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = immediateAlertServiceId
};
static constexpr ble_uuid16_t immediateAlertServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = immediateAlertServiceId};
static constexpr ble_uuid16_t alertLevelUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = alertLevelId
};
static constexpr ble_uuid16_t alertLevelUuid {.u {.type = BLE_UUID_TYPE_16}, .value = alertLevelId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t alertLevelHandle;
uint16_t alertLevelHandle;
};
}
}

View File

@@ -18,12 +18,12 @@
#include "MusicService.h"
#include "systemtask/SystemTask.h"
int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
auto musicService = static_cast<Pinetime::Controllers::MusicService *>(arg);
int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto musicService = static_cast<Pinetime::Controllers::MusicService*>(arg);
return musicService->OnCommand(conn_handle, attr_handle, ctxt);
}
Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &system) : m_system(system) {
Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask& system) : m_system(system) {
msUuid.value[14] = msId[0];
msUuid.value[15] = msId[1];
@@ -86,82 +86,51 @@ Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &
msShuffleCharUuid.value[13] = msShuffleCharId[1];
msShuffleCharUuid.value[14] = msId[0];
msShuffleCharUuid.value[15] = msId[1];
characteristicDefinition[0] = {.uuid = (ble_uuid_t *) (&msEventCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle
};
characteristicDefinition[1] = {.uuid = (ble_uuid_t *) (&msStatusCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[2] = {.uuid = (ble_uuid_t *) (&msTrackCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[3] = {.uuid = (ble_uuid_t *) (&msArtistCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[4] = {.uuid = (ble_uuid_t *) (&msAlbumCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[5] = {.uuid = (ble_uuid_t *) (&msPositionCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[6] = {.uuid = (ble_uuid_t *) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[7] = {.uuid = (ble_uuid_t *) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[8] = {.uuid = (ble_uuid_t *) (&msTrackNumberCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[9] = {.uuid = (ble_uuid_t *) (&msTrackTotalCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[10] = {.uuid = (ble_uuid_t *) (&msPlaybackSpeedCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[11] = {.uuid = (ble_uuid_t *) (&msRepeatCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[12] = {.uuid = (ble_uuid_t *) (&msShuffleCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[0] = {.uuid = (ble_uuid_t*) (&msEventCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle};
characteristicDefinition[1] = {
.uuid = (ble_uuid_t*) (&msStatusCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[2] = {
.uuid = (ble_uuid_t*) (&msTrackCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[3] = {
.uuid = (ble_uuid_t*) (&msArtistCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[4] = {
.uuid = (ble_uuid_t*) (&msAlbumCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[5] = {
.uuid = (ble_uuid_t*) (&msPositionCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[6] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[7] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[8] = {.uuid = (ble_uuid_t*) (&msTrackNumberCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[9] = {.uuid = (ble_uuid_t*) (&msTrackTotalCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[10] = {.uuid = (ble_uuid_t*) (&msPlaybackSpeedCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[11] = {
.uuid = (ble_uuid_t*) (&msRepeatCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[12] = {
.uuid = (ble_uuid_t*) (&msShuffleCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[13] = {0};
serviceDefinition[0] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &msUuid,
.characteristics = characteristicDefinition
};
serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &msUuid, .characteristics = characteristicDefinition};
serviceDefinition[1] = {0};
artistName = "Waiting for";
albumName = "";
trackName = "track information..";
@@ -177,41 +146,40 @@ void Pinetime::Controllers::MusicService::Init() {
int res = 0;
res = ble_gatts_count_cfg(serviceDefinition);
ASSERT(res == 0);
res = ble_gatts_add_svcs(serviceDefinition);
ASSERT(res == 0);
}
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
uint8_t data[notifSize + 1];
data[notifSize] = '\0';
os_mbuf_copydata(ctxt->om, 0, notifSize, data);
char *s = (char *) &data[0];
if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msArtistCharUuid) == 0) {
char* s = (char*) &data[0];
if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msArtistCharUuid) == 0) {
artistName = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackCharUuid) == 0) {
trackName = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msAlbumCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msAlbumCharUuid) == 0) {
albumName = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msStatusCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msStatusCharUuid) == 0) {
playing = s[0];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msRepeatCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msRepeatCharUuid) == 0) {
repeat = s[0];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msShuffleCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msShuffleCharUuid) == 0) {
shuffle = s[0];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msPositionCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msPositionCharUuid) == 0) {
trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTotalLengthCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTotalLengthCharUuid) == 0) {
trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackNumberCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackNumberCharUuid) == 0) {
trackNumber = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msTrackTotalCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackTotalCharUuid) == 0) {
tracksTotal = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &msPlaybackSpeedCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msPlaybackSpeedCharUuid) == 0) {
playbackSpeed = static_cast<float>(((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])) / 100.0f;
}
}
@@ -239,14 +207,14 @@ float Pinetime::Controllers::MusicService::getPlaybackSpeed() {
}
void Pinetime::Controllers::MusicService::event(char event) {
auto *om = ble_hs_mbuf_from_flat(&event, 1);
auto* om = ble_hs_mbuf_from_flat(&event, 1);
uint16_t connectionHandle = m_system.nimble().connHandle();
if (connectionHandle == 0 || connectionHandle == BLE_HS_CONN_HANDLE_NONE) {
return;
}
ble_gattc_notify_custom(connectionHandle, eventHandle, om);
}
@@ -257,4 +225,3 @@ int Pinetime::Controllers::MusicService::getProgress() {
int Pinetime::Controllers::MusicService::getTrackLength() {
return trackLength;
}

View File

@@ -26,40 +26,40 @@
#undef max
#undef min
//00000000-78fc-48fe-8e23-433b3a1942d0
#define MUSIC_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00}
// 00000000-78fc-48fe-8e23-433b3a1942d0
#define MUSIC_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 }
namespace Pinetime {
namespace System {
class SystemTask;
}
namespace Controllers {
class MusicService {
public:
explicit MusicService(Pinetime::System::SystemTask &system);
public:
explicit MusicService(Pinetime::System::SystemTask& system);
void Init();
int OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
void event(char event);
std::string getArtist();
std::string getTrack();
std::string getAlbum();
int getProgress();
int getTrackLength();
float getPlaybackSpeed();
bool isPlaying();
static const char EVENT_MUSIC_OPEN = 0xe0;
static const char EVENT_MUSIC_PLAY = 0x00;
static const char EVENT_MUSIC_PAUSE = 0x01;
@@ -67,12 +67,10 @@ namespace Pinetime {
static const char EVENT_MUSIC_PREV = 0x04;
static const char EVENT_MUSIC_VOLUP = 0x05;
static const char EVENT_MUSIC_VOLDOWN = 0x06;
enum MusicStatus {
NotPlaying = 0x00,
Playing = 0x01
};
private:
enum MusicStatus { NotPlaying = 0x00, Playing = 0x01 };
private:
static constexpr uint8_t msId[2] = {0x00, 0x00};
static constexpr uint8_t msEventCharId[2] = {0x01, 0x00};
static constexpr uint8_t msStatusCharId[2] = {0x02, 0x00};
@@ -86,84 +84,44 @@ namespace Pinetime {
static constexpr uint8_t msPlaybackSpeedCharId[2] = {0x0a, 0x00};
static constexpr uint8_t msRepeatCharId[2] = {0x0b, 0x00};
static constexpr uint8_t msShuffleCharId[2] = {0x0c, 0x00};
ble_uuid128_t msUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msEventCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msStatusCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msArtistCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msAlbumCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msPositionCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTotalLengthCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackNumberCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackTotalCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msPlaybackSpeedCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msRepeatCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msShuffleCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msEventCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msStatusCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msArtistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msAlbumCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msPositionCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTotalLengthCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackNumberCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackTotalCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msPlaybackSpeedCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msRepeatCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msShuffleCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[14];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t eventHandle;
std::string artistName;
std::string albumName;
std::string trackName;
bool playing;
int trackProgress;
int trackLength;
int trackNumber;
int tracksTotal;
float playbackSpeed;
bool repeat;
bool shuffle;
Pinetime::System::SystemTask &m_system;
Pinetime::System::SystemTask& m_system;
};
}
}

View File

@@ -20,12 +20,12 @@
#include "systemtask/SystemTask.h"
int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) {
auto navService = static_cast<Pinetime::Controllers::NavigationService *>(arg);
int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto navService = static_cast<Pinetime::Controllers::NavigationService*>(arg);
return navService->OnCommand(conn_handle, attr_handle, ctxt);
}
Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::SystemTask &system) : m_system(system) {
Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::SystemTask& system) : m_system(system) {
navUuid.value[14] = navId[0];
navUuid.value[15] = navId[1];
@@ -49,35 +49,25 @@ Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::Sy
navProgressCharUuid.value[14] = navId[0];
navProgressCharUuid.value[15] = navId[1];
characteristicDefinition[0] = {.uuid = (ble_uuid_t *) (&navFlagCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[0] = {
.uuid = (ble_uuid_t*) (&navFlagCharUuid), .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[1] = {.uuid = (ble_uuid_t *) (&navNarrativeCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[2] = {.uuid = (ble_uuid_t *) (&navManDistCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[3] = {.uuid = (ble_uuid_t *) (&navProgressCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[1] = {.uuid = (ble_uuid_t*) (&navNarrativeCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[2] = {.uuid = (ble_uuid_t*) (&navManDistCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[3] = {.uuid = (ble_uuid_t*) (&navProgressCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[4] = {0};
serviceDefinition[0] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &navUuid,
.characteristics = characteristicDefinition
};
serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &navUuid, .characteristics = characteristicDefinition};
serviceDefinition[1] = {0};
m_progress = 0;
@@ -92,45 +82,39 @@ void Pinetime::Controllers::NavigationService::Init() {
ASSERT(res == 0);
}
int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
uint8_t data[notifSize + 1];
data[notifSize] = '\0';
os_mbuf_copydata(ctxt->om, 0, notifSize, data);
char *s = (char *) &data[0];
if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &navFlagCharUuid) == 0) {
char* s = (char*) &data[0];
if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navFlagCharUuid) == 0) {
m_flag = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &navNarrativeCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navNarrativeCharUuid) == 0) {
m_narrative = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &navManDistCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navManDistCharUuid) == 0) {
m_manDist = s;
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t *) &navProgressCharUuid) == 0) {
} else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navProgressCharUuid) == 0) {
m_progress = data[0];
}
}
return 0;
}
std::string Pinetime::Controllers::NavigationService::getFlag()
{
return m_flag;
std::string Pinetime::Controllers::NavigationService::getFlag() {
return m_flag;
}
std::string Pinetime::Controllers::NavigationService::getNarrative()
{
return m_narrative;
std::string Pinetime::Controllers::NavigationService::getNarrative() {
return m_narrative;
}
std::string Pinetime::Controllers::NavigationService::getManDist()
{
return m_manDist;
std::string Pinetime::Controllers::NavigationService::getManDist() {
return m_manDist;
}
int Pinetime::Controllers::NavigationService::getProgress()
{
return m_progress;
int Pinetime::Controllers::NavigationService::getProgress() {
return m_progress;
}

View File

@@ -26,8 +26,9 @@
#undef max
#undef min
//c7e60000-78fc-48fe-8e23-433b3a1942d0
#define NAVIGATION_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00}
// c7e60000-78fc-48fe-8e23-433b3a1942d0
#define NAVIGATION_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 }
namespace Pinetime {
namespace System {
@@ -36,13 +37,12 @@ namespace Pinetime {
namespace Controllers {
class NavigationService {
public:
explicit NavigationService(Pinetime::System::SystemTask &system);
public:
explicit NavigationService(Pinetime::System::SystemTask& system);
void Init();
int OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
std::string getFlag();
@@ -52,34 +52,19 @@ namespace Pinetime {
int getProgress();
private:
private:
static constexpr uint8_t navId[2] = {0x01, 0x00};
static constexpr uint8_t navFlagCharId[2] = {0x01, 0x00};
static constexpr uint8_t navNarrativeCharId[2] = {0x02, 0x00};
static constexpr uint8_t navManDistCharId[2] = {0x03, 0x00};
static constexpr uint8_t navProgressCharId[2] = {0x04, 0x00};
ble_uuid128_t navUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navFlagCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navNarrativeCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navManDistCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navProgressCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navFlagCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navNarrativeCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navManDistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navProgressCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[5];
struct ble_gatt_svc_def serviceDefinition[2];
@@ -89,8 +74,7 @@ namespace Pinetime {
std::string m_manDist;
int m_progress;
Pinetime::System::SystemTask &m_system;
Pinetime::System::SystemTask& m_system;
};
}
}

View File

@@ -19,36 +19,37 @@ using namespace Pinetime::Controllers;
NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
DateTime& dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController) :
systemTask{systemTask},
bleController{bleController},
dateTimeController{dateTimeController},
notificationManager{notificationManager},
spiNorFlash{spiNorFlash},
dfuService{systemTask, bleController, spiNorFlash},
currentTimeClient{dateTimeController},
anService{systemTask, notificationManager},
alertNotificationClient{systemTask, notificationManager},
currentTimeService{dateTimeController},
musicService{systemTask},
navService{systemTask},
batteryInformationService{batteryController},
immediateAlertService{systemTask, notificationManager},
heartRateService{systemTask, heartRateController},
serviceDiscovery({&currentTimeClient, &alertNotificationClient}) {
DateTime& dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController)
: systemTask {systemTask},
bleController {bleController},
dateTimeController {dateTimeController},
notificationManager {notificationManager},
spiNorFlash {spiNorFlash},
dfuService {systemTask, bleController, spiNorFlash},
currentTimeClient {dateTimeController},
anService {systemTask, notificationManager},
alertNotificationClient {systemTask, notificationManager},
currentTimeService {dateTimeController},
musicService {systemTask},
navService {systemTask},
batteryInformationService {batteryController},
immediateAlertService {systemTask, notificationManager},
heartRateService {systemTask, heartRateController},
serviceDiscovery({&currentTimeClient, &alertNotificationClient}) {
}
int GAPEventCallback(struct ble_gap_event *event, void *arg) {
int GAPEventCallback(struct ble_gap_event* event, void* arg) {
auto nimbleController = static_cast<NimbleController*>(arg);
return nimbleController->OnGAPEvent(event);
}
void NimbleController::Init() {
while (!ble_hs_synced()) {}
while (!ble_hs_synced()) {
}
ble_svc_gap_init();
ble_svc_gatt_init();
@@ -81,7 +82,8 @@ void NimbleController::Init() {
}
void NimbleController::StartAdvertising() {
if(bleController.IsConnected() || ble_gap_conn_active() || ble_gap_adv_active()) return;
if (bleController.IsConnected() || ble_gap_conn_active() || ble_gap_adv_active())
return;
ble_svc_gap_device_name_set(deviceName);
@@ -101,29 +103,27 @@ void NimbleController::StartAdvertising() {
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
fields.flags = BLE_HS_ADV_F_DISC_GEN |
BLE_HS_ADV_F_BREDR_UNSUP;
// fields.uuids128 = BLE_UUID128(BLE_UUID128_DECLARE(
// 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
// 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff));
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
// fields.uuids128 = BLE_UUID128(BLE_UUID128_DECLARE(
// 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
// 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff));
fields.uuids128 = &dfuServiceUuid;
fields.num_uuids128 = 1;
fields.uuids128_is_complete = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
rsp_fields.name = (uint8_t *)deviceName;
rsp_fields.name = (uint8_t*) deviceName;
rsp_fields.name_len = strlen(deviceName);
rsp_fields.name_is_complete = 1;
ble_gap_adv_set_fields(&fields);
// ASSERT(res == 0); // TODO this one sometimes fails with error 22 (notsync)
// ASSERT(res == 0); // TODO this one sometimes fails with error 22 (notsync)
ble_gap_adv_rsp_set_fields(&rsp_fields);
// ASSERT(res == 0);
// ASSERT(res == 0);
ble_gap_adv_start(addrType, NULL, 180000,
&adv_params, GAPEventCallback, this);
// ASSERT(res == 0);// TODO I've disabled these ASSERT as they sometime asserts and reset the mcu.
ble_gap_adv_start(addrType, NULL, 180000, &adv_params, GAPEventCallback, this);
// ASSERT(res == 0);// TODO I've disabled these ASSERT as they sometime asserts and reset the mcu.
// For now, the advertising is restarted as soon as it ends. There may be a race condition
// that prevent the advertising from restarting reliably.
// I remove the assert to prevent this uncesseray crash, but in the long term, the management of
@@ -131,7 +131,7 @@ void NimbleController::StartAdvertising() {
// the application has been woken up, for example.
}
int NimbleController::OnGAPEvent(ble_gap_event *event) {
int NimbleController::OnGAPEvent(ble_gap_event* event) {
switch (event->type) {
case BLE_GAP_EVENT_ADV_COMPLETE:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE");
@@ -141,8 +141,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONNECT");
/* A new connection was established or a connection attempt failed. */
NRF_LOG_INFO("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed",
event->connect.status);
NRF_LOG_INFO("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed", event->connect.status);
if (event->connect.status != 0) {
/* Connection failed; resume advertising. */
@@ -154,8 +153,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
connectionHandle = event->connect.conn_handle;
// Service discovery is deffered via systemtask
}
}
break;
} break;
case BLE_GAP_EVENT_DISCONNECT:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_DISCONNECT");
NRF_LOG_INFO("disconnect; reason=%d", event->disconnect.reason);
@@ -178,19 +176,16 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
return 0;
case BLE_GAP_EVENT_SUBSCRIBE:
NRF_LOG_INFO("subscribe event; conn_handle=%d attr_handle=%d "
"reason=%d prevn=%d curn=%d previ=%d curi=???\n",
event->subscribe.conn_handle,
event->subscribe.attr_handle,
event->subscribe.reason,
event->subscribe.prev_notify,
event->subscribe.cur_notify,
event->subscribe.prev_indicate);
"reason=%d prevn=%d curn=%d previ=%d curi=???\n",
event->subscribe.conn_handle,
event->subscribe.attr_handle,
event->subscribe.reason,
event->subscribe.prev_notify,
event->subscribe.cur_notify,
event->subscribe.prev_indicate);
return 0;
case BLE_GAP_EVENT_MTU:
NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.channel_id,
event->mtu.value);
NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value);
return 0;
case BLE_GAP_EVENT_REPEAT_PAIRING: {
@@ -216,9 +211,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d "
"attr_len=%d",
event->notify_rx.indication ?
"indication" :
"notification",
event->notify_rx.indication ? "indication" : "notification",
event->notify_rx.conn_handle,
event->notify_rx.attr_handle,
notifSize);
@@ -229,7 +222,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
/* Attribute data is contained in event->notify_rx.attr_data. */
default:
// NRF_LOG_INFO("Advertising event : %d", event->type);
// NRF_LOG_INFO("Advertising event : %d", event->type);
break;
}
return 0;
@@ -239,8 +232,6 @@ void NimbleController::StartDiscovery() {
serviceDiscovery.StartDiscovery(connectionHandle);
}
uint16_t NimbleController::connHandle() {
return connectionHandle;
return connectionHandle;
}

View File

@@ -36,62 +36,69 @@ namespace Pinetime {
class NimbleController {
public:
NimbleController(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::Ble& bleController,
DateTime& dateTimeController, Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController);
void Init();
void StartAdvertising();
int OnGAPEvent(ble_gap_event *event);
public:
NimbleController(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
DateTime& dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController);
void Init();
void StartAdvertising();
int OnGAPEvent(ble_gap_event* event);
int OnDiscoveryEvent(uint16_t i, const ble_gatt_error *pError, const ble_gatt_svc *pSvc);
int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error *error, ble_gatt_attr *attribute);
int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor);
int OnDiscoveryEvent(uint16_t i, const ble_gatt_error* pError, const ble_gatt_svc* pSvc);
int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute);
int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc* descriptor);
void StartDiscovery();
void StartDiscovery();
Pinetime::Controllers::MusicService& music() {return musicService;};
Pinetime::Controllers::NavigationService& navigation() {return navService;};
Pinetime::Controllers::AlertNotificationService& alertService() {return anService;};
Pinetime::Controllers::MusicService& music() {
return musicService;
};
Pinetime::Controllers::NavigationService& navigation() {
return navService;
};
Pinetime::Controllers::AlertNotificationService& alertService() {
return anService;
};
uint16_t connHandle();
uint16_t connHandle();
private:
static constexpr const char* deviceName = "InfiniTime";
Pinetime::System::SystemTask& systemTask;
Pinetime::Controllers::Ble& bleController;
DateTime& dateTimeController;
Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
Pinetime::Controllers::DfuService dfuService;
private:
static constexpr const char* deviceName = "InfiniTime";
Pinetime::System::SystemTask& systemTask;
Pinetime::Controllers::Ble& bleController;
DateTime& dateTimeController;
Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
Pinetime::Controllers::DfuService dfuService;
DeviceInformationService deviceInformationService;
CurrentTimeClient currentTimeClient;
AlertNotificationService anService;
AlertNotificationClient alertNotificationClient;
CurrentTimeService currentTimeService;
MusicService musicService;
NavigationService navService;
BatteryInformationService batteryInformationService;
ImmediateAlertService immediateAlertService;
HeartRateService heartRateService;
DeviceInformationService deviceInformationService;
CurrentTimeClient currentTimeClient;
AlertNotificationService anService;
AlertNotificationClient alertNotificationClient;
CurrentTimeService currentTimeService;
MusicService musicService;
NavigationService navService;
BatteryInformationService batteryInformationService;
ImmediateAlertService immediateAlertService;
HeartRateService heartRateService;
uint8_t addrType; // 1 = Random, 0 = PUBLIC
uint16_t connectionHandle = 0;
uint8_t addrType; // 1 = Random, 0 = PUBLIC
uint16_t connectionHandle = 0;
ble_uuid128_t dfuServiceUuid {
.u { .type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}
};
ble_uuid128_t dfuServiceUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}};
ServiceDiscovery serviceDiscovery;
ServiceDiscovery serviceDiscovery;
};
}
}

View File

@@ -6,15 +6,15 @@ using namespace Pinetime::Controllers;
constexpr uint8_t NotificationManager::MessageSize;
void NotificationManager::Push(NotificationManager::Notification &&notif) {
void NotificationManager::Push(NotificationManager::Notification&& notif) {
notif.id = GetNextId();
notif.valid = true;
notifications[writeIndex] = std::move(notif);
writeIndex = (writeIndex + 1 < TotalNbNotifications) ? writeIndex + 1 : 0;
if(!empty)
if (!empty)
readIndex = (readIndex + 1 < TotalNbNotifications) ? readIndex + 1 : 0;
else empty = false;
else
empty = false;
newNotification = true;
}
@@ -30,40 +30,48 @@ NotificationManager::Notification::Id NotificationManager::GetNextId() {
}
NotificationManager::Notification NotificationManager::GetNext(NotificationManager::Notification::Id id) {
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;});
if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{};
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n) {
return n.valid && n.id == id;
});
if (currentIterator == notifications.end() || currentIterator->id != id)
return Notification {};
auto& lastNotification = notifications[readIndex];
NotificationManager::Notification result;
if(currentIterator == (notifications.end()-1))
if (currentIterator == (notifications.end() - 1))
result = *(notifications.begin());
else
result = *(currentIterator+1);
result = *(currentIterator + 1);
if(result.id <= id) return {};
if (result.id <= id)
return {};
result.index = (lastNotification.id - result.id)+1;
result.index = (lastNotification.id - result.id) + 1;
return result;
}
NotificationManager::Notification NotificationManager::GetPrevious(NotificationManager::Notification::Id id) {
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;});
if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{};
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n) {
return n.valid && n.id == id;
});
if (currentIterator == notifications.end() || currentIterator->id != id)
return Notification {};
auto& lastNotification = notifications[readIndex];
NotificationManager::Notification result;
if(currentIterator == notifications.begin())
result = *(notifications.end()-1);
if (currentIterator == notifications.begin())
result = *(notifications.end() - 1);
else
result = *(currentIterator-1);
result = *(currentIterator - 1);
if(result.id >= id) return {};
if (result.id >= id)
return {};
result.index = (lastNotification.id - result.id)+1;
result.index = (lastNotification.id - result.id) + 1;
return result;
}
@@ -76,7 +84,7 @@ bool NotificationManager::IsVibrationEnabled() {
}
void NotificationManager::ToggleVibrations() {
vibrationEnabled = !vibrationEnabled;
vibrationEnabled = !vibrationEnabled;
}
bool NotificationManager::ClearNewNotificationFlag() {
@@ -84,21 +92,23 @@ bool NotificationManager::ClearNewNotificationFlag() {
}
size_t NotificationManager::NbNotifications() const {
return std::count_if(notifications.begin(), notifications.end(), [](const Notification& n){ return n.valid;});
return std::count_if(notifications.begin(), notifications.end(), [](const Notification& n) {
return n.valid;
});
}
const char* NotificationManager::Notification::Message() const {
const char* itField = std::find(message.begin(), message.begin()+size-1, '\0');
if(itField != message.begin()+size-1) {
const char* ptr = (itField)+1;
const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
if (itField != message.begin() + size - 1) {
const char* ptr = (itField) + 1;
return ptr;
}
return const_cast<char*>(message.data());
}
const char* NotificationManager::Notification::Title() const {
const char * itField = std::find(message.begin(), message.begin()+size-1, '\0');
if(itField != message.begin()+size-1) {
const char* itField = std::find(message.begin(), message.begin() + size - 1, '\0');
if (itField != message.begin() + size - 1) {
return message.data();
}
return {};

View File

@@ -8,23 +8,35 @@
namespace Pinetime {
namespace Controllers {
class NotificationManager {
public:
enum class Categories {Unknown, SimpleAlert, Email, News, IncomingCall, MissedCall, Sms, VoiceMail, Schedule, HighProriotyAlert, InstantMessage };
static constexpr uint8_t MessageSize{100};
public:
enum class Categories {
Unknown,
SimpleAlert,
Email,
News,
IncomingCall,
MissedCall,
Sms,
VoiceMail,
Schedule,
HighProriotyAlert,
InstantMessage
};
static constexpr uint8_t MessageSize {100};
struct Notification {
using Id = uint8_t;
Id id;
bool valid = false;
uint8_t index;
uint8_t size;
std::array<char, MessageSize+1> message;
Categories category = Categories::Unknown;
struct Notification {
using Id = uint8_t;
Id id;
bool valid = false;
uint8_t index;
uint8_t size;
std::array<char, MessageSize + 1> message;
Categories category = Categories::Unknown;
const char* Message() const;
const char* Title() const;
};
Notification::Id nextId {0};
const char* Message() const;
const char* Title() const;
};
Notification::Id nextId {0};
void Push(Notification&& notif);
Notification GetLastNotification();
@@ -35,18 +47,20 @@ namespace Pinetime {
bool IsVibrationEnabled();
void ToggleVibrations();
static constexpr size_t MaximumMessageSize() { return MessageSize; };
static constexpr size_t MaximumMessageSize() {
return MessageSize;
};
size_t NbNotifications() const;
private:
Notification::Id GetNextId();
static constexpr uint8_t TotalNbNotifications = 5;
std::array<Notification, TotalNbNotifications> notifications;
uint8_t readIndex = 0;
uint8_t writeIndex = 0;
bool empty = true;
std::atomic<bool> newNotification{false};
bool vibrationEnabled = true;
private:
Notification::Id GetNextId();
static constexpr uint8_t TotalNbNotifications = 5;
std::array<Notification, TotalNbNotifications> notifications;
uint8_t readIndex = 0;
uint8_t writeIndex = 0;
bool empty = true;
std::atomic<bool> newNotification {false};
bool vibrationEnabled = true;
};
}
}

View File

@@ -4,8 +4,7 @@
using namespace Pinetime::Controllers;
ServiceDiscovery::ServiceDiscovery(std::array<BleClient*, 2>&& clients) : clients{clients} {
ServiceDiscovery::ServiceDiscovery(std::array<BleClient*, 2>&& clients) : clients {clients} {
}
void ServiceDiscovery::StartDiscovery(uint16_t connectionHandle) {
@@ -16,7 +15,7 @@ void ServiceDiscovery::StartDiscovery(uint16_t connectionHandle) {
void ServiceDiscovery::OnServiceDiscovered(uint16_t connectionHandle) {
clientIterator++;
if(clientIterator != clients.end()) {
if (clientIterator != clients.end()) {
DiscoverNextService(connectionHandle);
} else {
NRF_LOG_INFO("End of service discovery");
@@ -26,7 +25,7 @@ void ServiceDiscovery::OnServiceDiscovered(uint16_t connectionHandle) {
void ServiceDiscovery::DiscoverNextService(uint16_t connectionHandle) {
NRF_LOG_INFO("[Discovery] Discover next service");
auto discoverNextService = [this](uint16_t connectionHandle){
auto discoverNextService = [this](uint16_t connectionHandle) {
this->OnServiceDiscovered(connectionHandle);
};
(*clientIterator)->Discover(connectionHandle, discoverNextService);

View File

@@ -8,17 +8,16 @@ namespace Pinetime {
class BleClient;
class ServiceDiscovery {
public:
ServiceDiscovery(std::array<BleClient*, 2>&& bleClients);
public:
ServiceDiscovery(std::array<BleClient*, 2>&& bleClients);
void StartDiscovery(uint16_t connectionHandle);
void StartDiscovery(uint16_t connectionHandle);
private:
BleClient** clientIterator;
std::array<BleClient*, 2> clients;
void OnServiceDiscovered(uint16_t connectionHandle);
void DiscoverNextService(uint16_t connectionHandle);
private:
BleClient** clientIterator;
std::array<BleClient*, 2> clients;
void OnServiceDiscovered(uint16_t connectionHandle);
void DiscoverNextService(uint16_t connectionHandle);
};
}
}