diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e727b2b0..fecd09dd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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_hci_ev.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_pwr2.c libs/mynewt-nimble/porting/nimble/src/os_mbuf.c @@ -421,6 +422,7 @@ list(APPEND SOURCE_FILES displayapp/screens/BatteryInfo.cpp displayapp/screens/Steps.cpp displayapp/screens/Timer.cpp + displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp displayapp/Colors.cpp diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 9a3f86f5..82df7b15 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .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}, {0}}, serviceDefinition { diff --git a/src/components/ble/BleController.h b/src/components/ble/BleController.h index 2cba26a9..72b87663 100644 --- a/src/components/ble/BleController.h +++ b/src/components/ble/BleController.h @@ -9,7 +9,7 @@ namespace Pinetime { public: using BleAddress = std::array; enum class FirmwareUpdateStates { Idle, Running, Validated, Error }; - enum class AddressTypes { Public, Random }; + enum class AddressTypes { Public, Random, RPA_Public, RPA_Random }; Ble() = default; bool IsConnected() const { @@ -48,6 +48,12 @@ namespace Pinetime { void AddressType(AddressTypes t) { addressType = t; } + void SetPairingKey(uint32_t k) { + pairingKey = k; + } + uint32_t GetPairingKey() const { + return pairingKey; + } private: bool isConnected = false; @@ -57,6 +63,7 @@ namespace Pinetime { FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle; BleAddress address; AddressTypes addressType; + uint32_t pairingKey = 0; }; } -} \ No newline at end of file +} diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 43a8b0d6..01901e0a 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -1,4 +1,6 @@ #include "components/ble/NimbleController.h" +#include + #include #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max @@ -6,6 +8,7 @@ #include #include #include +#include #undef max #undef min #include @@ -45,16 +48,18 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, } 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) { - int rc; + int rc; - rc = ble_hs_util_ensure_addr(0); - ASSERT(rc == 0); + NRF_LOG_INFO("Nimble is synced"); - nptr->StartAdvertising(); + rc = ble_hs_util_ensure_addr(0); + ASSERT(rc == 0); + + nptr->StartAdvertising(); } int GAPEventCallback(struct ble_gap_event* event, void* arg) { @@ -69,6 +74,7 @@ void NimbleController::Init() { nptr = this; ble_hs_cfg.reset_cb = nimble_on_reset; 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_gatt_init(); @@ -97,8 +103,22 @@ void NimbleController::Init() { Pinetime::Controllers::Ble::BleAddress address; rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr); ASSERT(rc == 0); - bleController.AddressType((addrType == 0) ? Ble::AddressTypes::Public : Ble::AddressTypes::Random); + 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(); ASSERT(rc == 0); @@ -108,17 +128,10 @@ void NimbleController::Init() { } void NimbleController::StartAdvertising() { - int rc; - - /* set adv parameters */ struct ble_gap_adv_params adv_params; 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; - /* fill all fields and parameters with zeros */ memset(&adv_params, 0, sizeof(adv_params)); memset(&fields, 0, sizeof(fields)); memset(&rsp_fields, 0, sizeof(rsp_fields)); @@ -141,10 +154,11 @@ void NimbleController::StartAdvertising() { 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 = reinterpret_cast(deviceName); rsp_fields.name_len = strlen(deviceName); rsp_fields.name_is_complete = 1; + int rc; rc = ble_gap_adv_set_fields(&fields); ASSERT(rc == 0); @@ -159,15 +173,14 @@ 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"); - 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(); break; case BLE_GAP_EVENT_CONNECT: - 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("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) { /* Connection failed; resume advertising. */ @@ -186,10 +199,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; case BLE_GAP_EVENT_DISCONNECT: - NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_DISCONNECT"); - NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); - /* Connection terminated; resume advertising. */ + NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); + NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); currentTimeClient.Reset(); alertNotificationClient.Reset(); connectionHandle = BLE_HS_CONN_HANDLE_NONE; @@ -199,18 +211,45 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; case BLE_GAP_EVENT_CONN_UPDATE: - NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONN_UPDATE"); /* 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; case BLE_GAP_EVENT_ENC_CHANGE: /* 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); + break; + + case BLE_GAP_EVENT_PASSKEY_ACTION: + /* Authentication has been requested for this connection. + * Standards insist that the rand() PRNG be deterministic. + * Use the nimble TRNG 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; 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", event->subscribe.conn_handle, event->subscribe.attr_handle, @@ -234,11 +273,11 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; 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", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); break; 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 * establish a new secure link. This app sacrifices security for * convenience: just throw away the old bond and accept the new link. @@ -257,6 +296,8 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { case BLE_GAP_EVENT_NOTIFY_RX: { /* 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); NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d " @@ -268,10 +309,17 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { alertNotificationClient.OnNotification(event); } 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: - // NRF_LOG_INFO("Advertising event : %d", event->type); + NRF_LOG_INFO("UNHANDLED GAP event : %d", event->type); break; } return 0; diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index d340efee..935a61a1 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -25,6 +25,7 @@ namespace Pinetime { Metronome, Motion, Steps, + PassKey, QuickSettings, Settings, SettingWatchFace, diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 80155187..08a76467 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -29,6 +29,7 @@ #include "displayapp/screens/FlashLight.h" #include "displayapp/screens/BatteryInfo.h" #include "displayapp/screens/Steps.h" +#include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "drivers/Cst816s.h" @@ -288,6 +289,9 @@ void DisplayApp::Refresh() { // Added to remove warning // What should happen here? break; + case Messages::ShowPairingKey: + LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); + break; } } @@ -351,6 +355,11 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); break; + case Apps::PassKey: + currentScreen = std::make_unique(this, bleController.GetPairingKey()); + ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; + case Apps::Notifications: currentScreen = std::make_unique( this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 29e09eb3..b22d6c3c 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -19,6 +19,7 @@ namespace Pinetime { UpdateTimeOut, DimScreen, RestoreBrightness, + ShowPairingKey, AlarmTriggered }; } diff --git a/src/displayapp/screens/PassKey.cpp b/src/displayapp/screens/PassKey.cpp new file mode 100644 index 00000000..66bf0c24 --- /dev/null +++ b/src/displayapp/screens/PassKey.cpp @@ -0,0 +1,17 @@ +#include "PassKey.h" +#include "displayapp/DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + +PassKey::PassKey(Pinetime::Applications::DisplayApp* app, uint32_t key) : Screen(app) { + lpasskey = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00)); + lv_obj_set_style_local_text_font(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lpasskey, "%06u", key); + lv_obj_align(lpasskey, nullptr, LV_ALIGN_CENTER, 0, -20); +} + +PassKey::~PassKey() { + lv_obj_clean(lv_scr_act()); +} + diff --git a/src/displayapp/screens/PassKey.h b/src/displayapp/screens/PassKey.h new file mode 100644 index 00000000..34e0d593 --- /dev/null +++ b/src/displayapp/screens/PassKey.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Screen.h" +#include + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class PassKey : public Screen { + public: + PassKey(DisplayApp* app, uint32_t key); + ~PassKey() override; + + private: + lv_obj_t* lpasskey; + }; + } + } +} diff --git a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h index 94b72cb6..b3f23411 100644 --- a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h +++ b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h @@ -699,11 +699,11 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_BONDING -#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_BONDING (1) #endif #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 #ifndef MYNEWT_VAL_BLE_SM_KEYPRESS @@ -711,7 +711,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_LEGACY -#define MYNEWT_VAL_BLE_SM_LEGACY (1) +#define MYNEWT_VAL_BLE_SM_LEGACY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS @@ -719,7 +719,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_MITM -#define MYNEWT_VAL_BLE_SM_MITM (0) +#define MYNEWT_VAL_BLE_SM_MITM (1) #endif #ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG @@ -727,11 +727,11 @@ #endif #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 #ifndef MYNEWT_VAL_BLE_SM_SC -#define MYNEWT_VAL_BLE_SM_SC (0) +#define MYNEWT_VAL_BLE_SM_SC (1) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS @@ -739,7 +739,7 @@ #endif #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 #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) */ #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 #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG diff --git a/src/sdk_config.h b/src/sdk_config.h index 38d47a7f..7634dca1 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -12580,4 +12580,4 @@ #endif // <<< end of configuration section >>> -#endif // SDK_CONFIG_H \ No newline at end of file +#endif // SDK_CONFIG_H diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index b7142704..516f6462 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -22,6 +22,7 @@ namespace Pinetime { DisableSleeping, OnNewDay, OnChargingEvent, + OnPairing, SetOffAlarm, StopRinging, MeasureBatteryTimerExpired, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 1120b80d..2fb4de51 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -396,6 +396,13 @@ void SystemTask::Work() { case Messages::BatteryPercentageUpdated: nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); break; + case Messages::OnPairing: + if (isSleeping && !isWakingUp) { + GoToRunning(); + } + motorController.RunForDuration(35); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); + break; default: break;