Merge branch 'develop' into patch-weather

This commit is contained in:
Avamander 2021-12-09 22:20:29 +02:00 committed by GitHub
commit e8c1302cd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 306 additions and 62 deletions

View File

@ -154,6 +154,7 @@ set(NIMBLE_SRC
libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c
libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c
libs/mynewt-nimble/nimble/controller/src/ble_ll_rfmgmt.c libs/mynewt-nimble/nimble/controller/src/ble_ll_rfmgmt.c
libs/mynewt-nimble/nimble/controller/src/ble_ll_resolv.c
libs/mynewt-nimble/porting/nimble/src/os_cputime.c libs/mynewt-nimble/porting/nimble/src/os_cputime.c
libs/mynewt-nimble/porting/nimble/src/os_cputime_pwr2.c libs/mynewt-nimble/porting/nimble/src/os_cputime_pwr2.c
libs/mynewt-nimble/porting/nimble/src/os_mbuf.c libs/mynewt-nimble/porting/nimble/src/os_mbuf.c
@ -430,6 +431,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/BatteryInfo.cpp displayapp/screens/BatteryInfo.cpp
displayapp/screens/Steps.cpp displayapp/screens/Steps.cpp
displayapp/screens/Timer.cpp displayapp/screens/Timer.cpp
displayapp/screens/PassKey.cpp
displayapp/screens/Error.cpp displayapp/screens/Error.cpp
displayapp/screens/Alarm.cpp displayapp/screens/Alarm.cpp
displayapp/Colors.cpp displayapp/Colors.cpp

View File

@ -8,7 +8,7 @@ void ButtonTimerCallback(TimerHandle_t xTimer) {
} }
void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) {
buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, systemTask, ButtonTimerCallback); buttonTimer = xTimerCreate("buttonTimer", pdMS_TO_TICKS(200), pdFALSE, systemTask, ButtonTimerCallback);
} }
ButtonActions ButtonHandler::HandleEvent(Events event) { ButtonActions ButtonHandler::HandleEvent(Events event) {

View File

@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte
characteristicDefinition {{.uuid = &batteryLevelUuid.u, characteristicDefinition {{.uuid = &batteryLevelUuid.u,
.access_cb = BatteryInformationServiceCallback, .access_cb = BatteryInformationServiceCallback,
.arg = this, .arg = this,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &batteryLevelHandle}, .val_handle = &batteryLevelHandle},
{0}}, {0}},
serviceDefinition { serviceDefinition {

View File

@ -9,7 +9,7 @@ namespace Pinetime {
public: public:
using BleAddress = std::array<uint8_t, 6>; using BleAddress = std::array<uint8_t, 6>;
enum class FirmwareUpdateStates { Idle, Running, Validated, Error }; enum class FirmwareUpdateStates { Idle, Running, Validated, Error };
enum class AddressTypes { Public, Random }; enum class AddressTypes { Public, Random, RPA_Public, RPA_Random };
Ble() = default; Ble() = default;
bool IsConnected() const { bool IsConnected() const {
@ -48,6 +48,12 @@ namespace Pinetime {
void AddressType(AddressTypes t) { void AddressType(AddressTypes t) {
addressType = t; addressType = t;
} }
void SetPairingKey(uint32_t k) {
pairingKey = k;
}
uint32_t GetPairingKey() const {
return pairingKey;
}
private: private:
bool isConnected = false; bool isConnected = false;
@ -57,6 +63,7 @@ namespace Pinetime {
FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle; FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle;
BleAddress address; BleAddress address;
AddressTypes addressType; AddressTypes addressType;
uint32_t pairingKey = 0;
}; };
} }
} }

View File

@ -1,4 +1,6 @@
#include "components/ble/NimbleController.h" #include "components/ble/NimbleController.h"
#include <cstring>
#include <hal/nrf_rtc.h> #include <hal/nrf_rtc.h>
#define min // workaround: nimble's min/max macros conflict with libstdc++ #define min // workaround: nimble's min/max macros conflict with libstdc++
#define max #define max
@ -6,13 +8,16 @@
#include <host/ble_hs.h> #include <host/ble_hs.h>
#include <host/ble_hs_id.h> #include <host/ble_hs_id.h>
#include <host/util/util.h> #include <host/util/util.h>
#undef max #include <controller/ble_ll.h>
#undef min #include <controller/ble_hw.h>
#include <services/gap/ble_svc_gap.h> #include <services/gap/ble_svc_gap.h>
#include <services/gatt/ble_svc_gatt.h> #include <services/gatt/ble_svc_gatt.h>
#undef max
#undef min
#include "components/ble/BleController.h" #include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/datetime/DateTimeController.h" #include "components/datetime/DateTimeController.h"
#include "components/fs/FS.h"
#include "systemtask/SystemTask.h" #include "systemtask/SystemTask.h"
using namespace Pinetime::Controllers; using namespace Pinetime::Controllers;
@ -24,13 +29,16 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
Controllers::Battery& batteryController, Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController, Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController) Controllers::MotionController& motionController,
Pinetime::Controllers::FS& fs)
: systemTask {systemTask}, : systemTask {systemTask},
bleController {bleController}, bleController {bleController},
dateTimeController {dateTimeController}, dateTimeController {dateTimeController},
notificationManager {notificationManager}, notificationManager {notificationManager},
spiNorFlash {spiNorFlash}, spiNorFlash {spiNorFlash},
fs {fs},
dfuService {systemTask, bleController, spiNorFlash}, dfuService {systemTask, bleController, spiNorFlash},
currentTimeClient {dateTimeController}, currentTimeClient {dateTimeController},
anService {systemTask, notificationManager}, anService {systemTask, notificationManager},
alertNotificationClient {systemTask, notificationManager}, alertNotificationClient {systemTask, notificationManager},
@ -41,21 +49,23 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
batteryInformationService {batteryController}, batteryInformationService {batteryController},
immediateAlertService {systemTask, notificationManager}, immediateAlertService {systemTask, notificationManager},
heartRateService {systemTask, heartRateController}, heartRateService {systemTask, heartRateController},
motionService{systemTask, motionController}, motionService {systemTask, motionController},
serviceDiscovery({&currentTimeClient, &alertNotificationClient}) { serviceDiscovery({&currentTimeClient, &alertNotificationClient}) {
} }
void nimble_on_reset(int reason) { void nimble_on_reset(int reason) {
NRF_LOG_INFO("Resetting state; reason=%d\n", reason); NRF_LOG_INFO("Nimble lost sync, resetting state; reason=%d", reason);
} }
void nimble_on_sync(void) { void nimble_on_sync(void) {
int rc; int rc;
rc = ble_hs_util_ensure_addr(0); NRF_LOG_INFO("Nimble is synced");
ASSERT(rc == 0);
nptr->StartAdvertising(); rc = ble_hs_util_ensure_addr(0);
ASSERT(rc == 0);
nptr->StartAdvertising();
} }
int GAPEventCallback(struct ble_gap_event* event, void* arg) { int GAPEventCallback(struct ble_gap_event* event, void* arg) {
@ -70,6 +80,7 @@ void NimbleController::Init() {
nptr = this; nptr = this;
ble_hs_cfg.reset_cb = nimble_on_reset; ble_hs_cfg.reset_cb = nimble_on_reset;
ble_hs_cfg.sync_cb = nimble_on_sync; ble_hs_cfg.sync_cb = nimble_on_sync;
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
ble_svc_gap_init(); ble_svc_gap_init();
ble_svc_gatt_init(); ble_svc_gatt_init();
@ -99,28 +110,38 @@ void NimbleController::Init() {
Pinetime::Controllers::Ble::BleAddress address; Pinetime::Controllers::Ble::BleAddress address;
rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr); rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr);
ASSERT(rc == 0); ASSERT(rc == 0);
bleController.AddressType((addrType == 0) ? Ble::AddressTypes::Public : Ble::AddressTypes::Random);
bleController.Address(std::move(address)); bleController.Address(std::move(address));
switch (addrType) {
case BLE_OWN_ADDR_PUBLIC:
bleController.AddressType(Ble::AddressTypes::Public);
break;
case BLE_OWN_ADDR_RANDOM:
bleController.AddressType(Ble::AddressTypes::Random);
break;
case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
bleController.AddressType(Ble::AddressTypes::RPA_Public);
break;
case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
bleController.AddressType(Ble::AddressTypes::RPA_Random);
break;
}
rc = ble_gatts_start(); rc = ble_gatts_start();
ASSERT(rc == 0); ASSERT(rc == 0);
if (!ble_gap_adv_active() && !bleController.IsConnected()) RestoreBond();
if (!ble_gap_adv_active() && !bleController.IsConnected()) {
StartAdvertising(); StartAdvertising();
}
} }
void NimbleController::StartAdvertising() { void NimbleController::StartAdvertising() {
int rc;
/* set adv parameters */
struct ble_gap_adv_params adv_params; struct ble_gap_adv_params adv_params;
struct ble_hs_adv_fields fields; struct ble_hs_adv_fields fields;
/* advertising payload is split into advertising data and advertising
response, because all data cannot fit into single packet; name of device
is sent as response to scan request */
struct ble_hs_adv_fields rsp_fields; struct ble_hs_adv_fields rsp_fields;
/* fill all fields and parameters with zeros */
memset(&adv_params, 0, sizeof(adv_params)); memset(&adv_params, 0, sizeof(adv_params));
memset(&fields, 0, sizeof(fields)); memset(&fields, 0, sizeof(fields));
memset(&rsp_fields, 0, sizeof(rsp_fields)); memset(&rsp_fields, 0, sizeof(rsp_fields));
@ -143,10 +164,11 @@ void NimbleController::StartAdvertising() {
fields.uuids128_is_complete = 1; fields.uuids128_is_complete = 1;
fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
rsp_fields.name = (uint8_t*) deviceName; rsp_fields.name = reinterpret_cast<const uint8_t*>(deviceName);
rsp_fields.name_len = strlen(deviceName); rsp_fields.name_len = strlen(deviceName);
rsp_fields.name_is_complete = 1; rsp_fields.name_is_complete = 1;
int rc;
rc = ble_gap_adv_set_fields(&fields); rc = ble_gap_adv_set_fields(&fields);
ASSERT(rc == 0); ASSERT(rc == 0);
@ -161,15 +183,14 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
switch (event->type) { switch (event->type) {
case BLE_GAP_EVENT_ADV_COMPLETE: case BLE_GAP_EVENT_ADV_COMPLETE:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE"); NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE");
NRF_LOG_INFO("reason=%d; status=%d", event->adv_complete.reason, event->connect.status); NRF_LOG_INFO("reason=%d; status=%0X", event->adv_complete.reason, event->connect.status);
StartAdvertising(); StartAdvertising();
break; break;
case BLE_GAP_EVENT_CONNECT: case BLE_GAP_EVENT_CONNECT:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONNECT");
/* A new connection was established or a connection attempt failed. */ /* 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("Connect event : BLE_GAP_EVENT_CONNECT");
NRF_LOG_INFO("connection %s; status=%0X ", event->connect.status == 0 ? "established" : "failed", event->connect.status);
if (event->connect.status != 0) { if (event->connect.status != 0) {
/* Connection failed; resume advertising. */ /* Connection failed; resume advertising. */
@ -188,10 +209,14 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
break; break;
case BLE_GAP_EVENT_DISCONNECT: case BLE_GAP_EVENT_DISCONNECT:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_DISCONNECT"); /* Connection terminated; resume advertising. */
NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT");
NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason);
/* Connection terminated; resume advertising. */ if (event->disconnect.conn.sec_state.bonded) {
PersistBond(event->disconnect.conn);
}
currentTimeClient.Reset(); currentTimeClient.Reset();
alertNotificationClient.Reset(); alertNotificationClient.Reset();
connectionHandle = BLE_HS_CONN_HANDLE_NONE; connectionHandle = BLE_HS_CONN_HANDLE_NONE;
@ -201,18 +226,67 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
break; break;
case BLE_GAP_EVENT_CONN_UPDATE: case BLE_GAP_EVENT_CONN_UPDATE:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONN_UPDATE");
/* The central has updated the connection parameters. */ /* The central has updated the connection parameters. */
NRF_LOG_INFO("update status=%d ", event->conn_update.status); NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE");
NRF_LOG_INFO("update status=%0X ", event->conn_update.status);
break;
case BLE_GAP_EVENT_CONN_UPDATE_REQ:
/* The central has requested updated connection parameters */
NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE_REQ");
NRF_LOG_INFO("update request : itvl_min=%d itvl_max=%d latency=%d supervision=%d",
event->conn_update_req.peer_params->itvl_min,
event->conn_update_req.peer_params->itvl_max,
event->conn_update_req.peer_params->latency,
event->conn_update_req.peer_params->supervision_timeout);
break; break;
case BLE_GAP_EVENT_ENC_CHANGE: case BLE_GAP_EVENT_ENC_CHANGE:
/* Encryption has been enabled or disabled for this connection. */ /* Encryption has been enabled or disabled for this connection. */
NRF_LOG_INFO("encryption change event; status=%d ", event->enc_change.status); NRF_LOG_INFO("Security event : BLE_GAP_EVENT_ENC_CHANGE");
NRF_LOG_INFO("encryption change event; status=%0X ", event->enc_change.status);
if (event->enc_change.status == 0) {
struct ble_gap_conn_desc desc;
ble_gap_conn_find(event->enc_change.conn_handle, &desc);
if (desc.sec_state.bonded) {
PersistBond(desc);
}
NRF_LOG_INFO("new state: encrypted=%d authenticated=%d bonded=%d key_size=%d",
desc.sec_state.encrypted,
desc.sec_state.authenticated,
desc.sec_state.bonded,
desc.sec_state.key_size);
}
break;
case BLE_GAP_EVENT_PASSKEY_ACTION:
/* Authentication has been requested for this connection.
*
* BLE authentication is determined by the combination of I/O capabilities
* on the central and peripheral. When the peripheral is display only and
* the central has a keyboard and display then passkey auth is selected.
* When both the central and peripheral have displays and support yes/no
* buttons then numeric comparison is selected. We currently advertise
* display capability only so we only handle the "display" action here.
*
* Standards insist that the rand() PRNG be deterministic.
* Use the nimble TRNG here since rand() is predictable.
*/
NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION");
if (event->passkey.params.action == BLE_SM_IOACT_DISP) {
struct ble_sm_io pkey = {0};
pkey.action = event->passkey.params.action;
pkey.passkey = ble_ll_rand() % 1000000;
bleController.SetPairingKey(pkey.passkey);
systemTask.PushMessage(Pinetime::System::Messages::OnPairing);
ble_sm_inject_io(event->passkey.conn_handle, &pkey);
}
break; break;
case BLE_GAP_EVENT_SUBSCRIBE: case BLE_GAP_EVENT_SUBSCRIBE:
NRF_LOG_INFO("subscribe event; conn_handle=%d attr_handle=%d " NRF_LOG_INFO("Subscribe event; conn_handle=%d attr_handle=%d "
"reason=%d prevn=%d curn=%d previ=%d curi=???\n", "reason=%d prevn=%d curn=%d previ=%d curi=???\n",
event->subscribe.conn_handle, event->subscribe.conn_handle,
event->subscribe.attr_handle, event->subscribe.attr_handle,
@ -221,26 +295,24 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
event->subscribe.cur_notify, event->subscribe.cur_notify,
event->subscribe.prev_indicate); event->subscribe.prev_indicate);
if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { if (event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) {
heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
} } else if (event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) {
else if(event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) {
heartRateService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); heartRateService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
motionService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
} } else if (event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) {
else if(event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) {
heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle);
} }
break; break;
case BLE_GAP_EVENT_MTU: case BLE_GAP_EVENT_MTU:
NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n", NRF_LOG_INFO("MTU Update event; conn_handle=%d cid=%d mtu=%d", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value);
event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value);
break; break;
case BLE_GAP_EVENT_REPEAT_PAIRING: { case BLE_GAP_EVENT_REPEAT_PAIRING: {
NRF_LOG_INFO("Pairing event : BLE_GAP_EVENT_REPEAT_PAIRING");
/* We already have a bond with the peer, but it is attempting to /* We already have a bond with the peer, but it is attempting to
* establish a new secure link. This app sacrifices security for * establish a new secure link. This app sacrifices security for
* convenience: just throw away the old bond and accept the new link. * convenience: just throw away the old bond and accept the new link.
@ -259,6 +331,8 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
case BLE_GAP_EVENT_NOTIFY_RX: { case BLE_GAP_EVENT_NOTIFY_RX: {
/* Peer sent us a notification or indication. */ /* Peer sent us a notification or indication. */
/* Attribute data is contained in event->notify_rx.attr_data. */
NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_RX");
size_t notifSize = OS_MBUF_PKTLEN(event->notify_rx.om); size_t notifSize = OS_MBUF_PKTLEN(event->notify_rx.om);
NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d " NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d "
@ -270,10 +344,17 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
alertNotificationClient.OnNotification(event); alertNotificationClient.OnNotification(event);
} break; } break;
/* Attribute data is contained in event->notify_rx.attr_data. */
case BLE_GAP_EVENT_NOTIFY_TX:
NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_TX");
break;
case BLE_GAP_EVENT_IDENTITY_RESOLVED:
NRF_LOG_INFO("Identity event : BLE_GAP_EVENT_IDENTITY_RESOLVED");
break;
default: default:
// NRF_LOG_INFO("Advertising event : %d", event->type); NRF_LOG_INFO("UNHANDLED GAP event : %d", event->type);
break; break;
} }
return 0; return 0;
@ -294,3 +375,82 @@ void NimbleController::NotifyBatteryLevel(uint8_t level) {
batteryInformationService.NotifyBatteryLevel(connectionHandle, level); batteryInformationService.NotifyBatteryLevel(connectionHandle, level);
} }
} }
void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) {
union ble_store_key key;
union ble_store_value our_sec, peer_sec, peer_cccd_set[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)] = {0};
int rc;
memset(&key, 0, sizeof key);
memset(&our_sec, 0, sizeof our_sec);
key.sec.peer_addr = desc.peer_id_addr;
rc = ble_store_read_our_sec(&key.sec, &our_sec.sec);
if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) {
return;
}
memcpy(&bondId, &our_sec.sec, sizeof bondId);
memset(&key, 0, sizeof key);
memset(&peer_sec, 0, sizeof peer_sec);
key.sec.peer_addr = desc.peer_id_addr;
rc += ble_store_read_peer_sec(&key.sec, &peer_sec.sec);
if (rc == 0) {
memset(&key, 0, sizeof key);
key.cccd.peer_addr = desc.peer_id_addr;
int peer_count = 0;
ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &peer_count);
for (int i = 0; i < peer_count; i++) {
key.cccd.idx = peer_count;
ble_store_read_cccd(&key.cccd, &peer_cccd_set[i].cccd);
}
/* Wakeup Spi and SpiNorFlash before accessing the file system
* This should be fixed in the FS driver
*/
systemTask.PushMessage(Pinetime::System::Messages::GoToRunning);
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
vTaskDelay(10);
lfs_file_t file_p;
rc = fs.FileOpen(&file_p, "/bond.dat", LFS_O_WRONLY | LFS_O_CREAT);
if (rc == 0) {
fs.FileWrite(&file_p, reinterpret_cast<uint8_t*>(&our_sec.sec), sizeof our_sec);
fs.FileWrite(&file_p, reinterpret_cast<uint8_t*>(&peer_sec.sec), sizeof peer_sec);
fs.FileWrite(&file_p, reinterpret_cast<const uint8_t*>(&peer_count), 1);
for (int i = 0; i < peer_count; i++) {
fs.FileWrite(&file_p, reinterpret_cast<uint8_t*>(&peer_cccd_set[i].cccd), sizeof(struct ble_store_value_cccd));
}
fs.FileClose(&file_p);
}
systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
}
}
void NimbleController::RestoreBond() {
lfs_file_t file_p;
union ble_store_value sec, cccd;
uint8_t peer_count = 0;
if (fs.FileOpen(&file_p, "/bond.dat", LFS_O_RDONLY) == 0) {
memset(&sec, 0, sizeof sec);
fs.FileRead(&file_p, reinterpret_cast<uint8_t*>(&sec.sec), sizeof sec);
ble_store_write_our_sec(&sec.sec);
memset(&sec, 0, sizeof sec);
fs.FileRead(&file_p, reinterpret_cast<uint8_t*>(&sec.sec), sizeof sec);
ble_store_write_peer_sec(&sec.sec);
fs.FileRead(&file_p, &peer_count, 1);
for (int i = 0; i < peer_count; i++) {
fs.FileRead(&file_p, reinterpret_cast<uint8_t*>(&cccd.cccd), sizeof(struct ble_store_value_cccd));
ble_store_write_cccd(&cccd.cccd);
}
fs.FileClose(&file_p);
fs.FileDelete("/bond.dat");
}
}

View File

@ -14,13 +14,14 @@
#include "components/ble/CurrentTimeService.h" #include "components/ble/CurrentTimeService.h"
#include "components/ble/DeviceInformationService.h" #include "components/ble/DeviceInformationService.h"
#include "components/ble/DfuService.h" #include "components/ble/DfuService.h"
#include "components/ble/HeartRateService.h"
#include "components/ble/ImmediateAlertService.h" #include "components/ble/ImmediateAlertService.h"
#include "components/ble/MusicService.h" #include "components/ble/MusicService.h"
#include "components/ble/NavigationService.h" #include "components/ble/NavigationService.h"
#include "components/ble/ServiceDiscovery.h" #include "components/ble/ServiceDiscovery.h"
#include "components/ble/HeartRateService.h"
#include "components/ble/MotionService.h" #include "components/ble/MotionService.h"
#include "components/ble/weather/WeatherService.h" #include "components/ble/weather/WeatherService.h"
#include "components/fs/FS.h"
namespace Pinetime { namespace Pinetime {
namespace Drivers { namespace Drivers {
@ -46,7 +47,8 @@ namespace Pinetime {
Controllers::Battery& batteryController, Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController, Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController); Controllers::MotionController& motionController,
Pinetime::Controllers::FS& fs);
void Init(); void Init();
void StartAdvertising(); void StartAdvertising();
int OnGAPEvent(ble_gap_event* event); int OnGAPEvent(ble_gap_event* event);
@ -83,12 +85,16 @@ namespace Pinetime {
} }
private: private:
void PersistBond(struct ble_gap_conn_desc& desc);
void RestoreBond();
static constexpr const char* deviceName = "InfiniTime"; static constexpr const char* deviceName = "InfiniTime";
Pinetime::System::SystemTask& systemTask; Pinetime::System::SystemTask& systemTask;
Pinetime::Controllers::Ble& bleController; Pinetime::Controllers::Ble& bleController;
DateTime& dateTimeController; DateTime& dateTimeController;
Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Drivers::SpiNorFlash& spiNorFlash; Pinetime::Drivers::SpiNorFlash& spiNorFlash;
Pinetime::Controllers::FS& fs;
Pinetime::Controllers::DfuService dfuService; Pinetime::Controllers::DfuService dfuService;
DeviceInformationService deviceInformationService; DeviceInformationService deviceInformationService;
@ -103,18 +109,18 @@ namespace Pinetime {
ImmediateAlertService immediateAlertService; ImmediateAlertService immediateAlertService;
HeartRateService heartRateService; HeartRateService heartRateService;
MotionService motionService; MotionService motionService;
ServiceDiscovery serviceDiscovery;
uint8_t addrType; // 1 = Random, 0 = PUBLIC uint8_t addrType;
uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE;
uint8_t fastAdvCount = 0; uint8_t fastAdvCount = 0;
uint8_t bondId[16] = {0};
ble_uuid128_t dfuServiceUuid { ble_uuid128_t dfuServiceUuid {
.u {.type = BLE_UUID_TYPE_128}, .u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}}; .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}};
ServiceDiscovery serviceDiscovery;
}; };
static NimbleController* nptr; static NimbleController* nptr;
} }
} }

View File

@ -26,6 +26,7 @@ namespace Pinetime {
Motion, Motion,
Steps, Steps,
Weather, Weather,
PassKey,
QuickSettings, QuickSettings,
Settings, Settings,
SettingWatchFace, SettingWatchFace,

View File

@ -29,6 +29,7 @@
#include "displayapp/screens/FlashLight.h" #include "displayapp/screens/FlashLight.h"
#include "displayapp/screens/BatteryInfo.h" #include "displayapp/screens/BatteryInfo.h"
#include "displayapp/screens/Steps.h" #include "displayapp/screens/Steps.h"
#include "displayapp/screens/PassKey.h"
#include "displayapp/screens/Error.h" #include "displayapp/screens/Error.h"
#include "drivers/Cst816s.h" #include "drivers/Cst816s.h"
@ -214,6 +215,9 @@ void DisplayApp::Refresh() {
} else { } else {
LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None); LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None);
} }
case Messages::ShowPairingKey:
LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up);
break;
case Messages::TouchEvent: { case Messages::TouchEvent: {
if (state != States::Running) { if (state != States::Running) {
break; break;
@ -351,6 +355,11 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
break; break;
case Apps::PassKey:
currentScreen = std::make_unique<Screens::PassKey>(this, bleController.GetPairingKey());
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::Notifications: case Apps::Notifications:
currentScreen = std::make_unique<Screens::Notifications>( currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal); this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal);

View File

@ -19,6 +19,7 @@ namespace Pinetime {
UpdateTimeOut, UpdateTimeOut,
DimScreen, DimScreen,
RestoreBrightness, RestoreBrightness,
ShowPairingKey,
AlarmTriggered AlarmTriggered
}; };
} }

View File

@ -0,0 +1,24 @@
#include "PassKey.h"
#include "displayapp/DisplayApp.h"
using namespace Pinetime::Applications::Screens;
PassKey::PassKey(Pinetime::Applications::DisplayApp* app, uint32_t key) : Screen(app) {
passkeyLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00));
lv_obj_set_style_local_text_font(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
lv_label_set_text_fmt(passkeyLabel, "%06u", key);
lv_obj_align(passkeyLabel, nullptr, LV_ALIGN_CENTER, 0, -20);
backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_click(backgroundLabel, true);
lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
lv_obj_set_size(backgroundLabel, 240, 240);
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text(backgroundLabel, "");
}
PassKey::~PassKey() {
lv_obj_clean(lv_scr_act());
}

View File

@ -0,0 +1,21 @@
#pragma once
#include "Screen.h"
#include <lvgl/lvgl.h>
namespace Pinetime {
namespace Applications {
namespace Screens {
class PassKey : public Screen {
public:
PassKey(DisplayApp* app, uint32_t key);
~PassKey() override;
private:
lv_obj_t* passkeyLabel;
lv_obj_t* backgroundLabel;
};
}
}
}

View File

@ -699,11 +699,11 @@
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_BONDING #ifndef MYNEWT_VAL_BLE_SM_BONDING
#define MYNEWT_VAL_BLE_SM_BONDING (0) #define MYNEWT_VAL_BLE_SM_BONDING (1)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_IO_CAP #ifndef MYNEWT_VAL_BLE_SM_IO_CAP
#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) #define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_DISPLAY_ONLY)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_KEYPRESS #ifndef MYNEWT_VAL_BLE_SM_KEYPRESS
@ -711,7 +711,7 @@
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_LEGACY #ifndef MYNEWT_VAL_BLE_SM_LEGACY
#define MYNEWT_VAL_BLE_SM_LEGACY (1) #define MYNEWT_VAL_BLE_SM_LEGACY (0)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS #ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS
@ -719,7 +719,7 @@
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_MITM #ifndef MYNEWT_VAL_BLE_SM_MITM
#define MYNEWT_VAL_BLE_SM_MITM (0) #define MYNEWT_VAL_BLE_SM_MITM (1)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG #ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG
@ -727,11 +727,11 @@
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST #ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST
#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) #define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (7)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_SC #ifndef MYNEWT_VAL_BLE_SM_SC
#define MYNEWT_VAL_BLE_SM_SC (0) #define MYNEWT_VAL_BLE_SM_SC (1)
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS
@ -739,7 +739,7 @@
#endif #endif
#ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST
#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) #define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (3)
#endif #endif
#ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS #ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS
@ -1089,7 +1089,7 @@
/* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ /* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY
#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (0) #define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1)
#endif #endif
#ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG

View File

@ -37,7 +37,7 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn)
* provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped
* since it has compatible prototype. * since it has compatible prototype.
*/ */
xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 200,
NULL, configMAX_PRIORITIES - 1, &ll_task_h); NULL, configMAX_PRIORITIES - 1, &ll_task_h);
#endif #endif
@ -46,6 +46,6 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn)
* have separate task for NimBLE host, but since something needs to handle * have separate task for NimBLE host, but since something needs to handle
* default queue it is just easier to make separate task which does this. * default queue it is just easier to make separate task which does this.
*/ */
xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 400, xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 600,
NULL, tskIDLE_PRIORITY + 1, &host_task_h); NULL, tskIDLE_PRIORITY + 1, &host_task_h);
} }

View File

@ -12580,4 +12580,4 @@
#endif #endif
// <<< end of configuration section >>> // <<< end of configuration section >>>
#endif // SDK_CONFIG_H #endif // SDK_CONFIG_H

View File

@ -22,6 +22,7 @@ namespace Pinetime {
DisableSleeping, DisableSleeping,
OnNewDay, OnNewDay,
OnChargingEvent, OnChargingEvent,
OnPairing,
SetOffAlarm, SetOffAlarm,
StopRinging, StopRinging,
MeasureBatteryTimerExpired, MeasureBatteryTimerExpired,

View File

@ -109,7 +109,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
batteryController, batteryController,
spiNorFlash, spiNorFlash,
heartRateController, heartRateController,
motionController) { motionController,
fs) {
} }
void SystemTask::Start() { void SystemTask::Start() {
@ -258,8 +259,9 @@ void SystemTask::Work() {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning); displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp); heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
if (!bleController.IsConnected()) if (!bleController.IsConnected()) {
nimbleController.RestartFastAdv(); nimbleController.RestartFastAdv();
}
isSleeping = false; isSleeping = false;
isWakingUp = false; isWakingUp = false;
@ -278,6 +280,9 @@ void SystemTask::Work() {
} }
} break; } break;
case Messages::GoToSleep: case Messages::GoToSleep:
if (doNotGoToSleep) {
break;
}
isGoingToSleep = true; isGoingToSleep = true;
NRF_LOG_INFO("[systemtask] Going to sleep"); NRF_LOG_INFO("[systemtask] Going to sleep");
xTimerStop(idleTimer, 0); xTimerStop(idleTimer, 0);
@ -396,6 +401,13 @@ void SystemTask::Work() {
case Messages::BatteryPercentageUpdated: case Messages::BatteryPercentageUpdated:
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
break; break;
case Messages::OnPairing:
if (isSleeping && !isWakingUp) {
GoToRunning();
}
motorController.RunForDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
break;
default: default:
break; break;
@ -497,7 +509,7 @@ void SystemTask::OnTouchEvent() {
} }
void SystemTask::PushMessage(System::Messages msg) { void SystemTask::PushMessage(System::Messages msg) {
if (msg == Messages::GoToSleep) { if (msg == Messages::GoToSleep && !doNotGoToSleep) {
isGoingToSleep = true; isGoingToSleep = true;
} }