Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect and bond with a passkey #796

Merged
merged 4 commits into from
Dec 9, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/components/ble/BatteryInformationService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
11 changes: 9 additions & 2 deletions src/components/ble/BleController.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Pinetime {
public:
using BleAddress = std::array<uint8_t, 6>;
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 {
Expand Down Expand Up @@ -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;
Expand All @@ -57,6 +63,7 @@ namespace Pinetime {
FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle;
BleAddress address;
AddressTypes addressType;
uint32_t pairingKey = 0;
};
}
}
}
106 changes: 77 additions & 29 deletions src/components/ble/NimbleController.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "components/ble/NimbleController.h"
#include <cstring>

#include <hal/nrf_rtc.h>
#define min // workaround: nimble's min/max macros conflict with libstdc++
#define max
#include <host/ble_gap.h>
#include <host/ble_hs.h>
#include <host/ble_hs_id.h>
#include <host/util/util.h>
#include <controller/ble_ll.h>
#undef max
#undef min
#include <services/gap/ble_svc_gap.h>
Expand Down Expand Up @@ -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");

rc = ble_hs_util_ensure_addr(0);
evergreen22 marked this conversation as resolved.
Show resolved Hide resolved
ASSERT(rc == 0);

nptr->StartAdvertising();
nptr->StartAdvertising();
}

int GAPEventCallback(struct ble_gap_event* event, void* arg) {
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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));
Expand All @@ -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<const uint8_t*>(deviceName);
evergreen22 marked this conversation as resolved.
Show resolved Hide resolved
rsp_fields.name_len = strlen(deviceName);
rsp_fields.name_is_complete = 1;

int rc;
rc = ble_gap_adv_set_fields(&fields);
evergreen22 marked this conversation as resolved.
Show resolved Hide resolved
ASSERT(rc == 0);

Expand All @@ -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. */
Expand All @@ -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;
Expand All @@ -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) {
evergreen22 marked this conversation as resolved.
Show resolved Hide resolved
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,
Expand All @@ -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.
Expand All @@ -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 "
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/displayapp/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ namespace Pinetime {
Metronome,
Motion,
Steps,
PassKey,
QuickSettings,
Settings,
SettingWatchFace,
Expand Down
9 changes: 9 additions & 0 deletions src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -214,6 +215,9 @@ void DisplayApp::Refresh() {
} else {
LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None);
}
case Messages::ShowPairingKey:
LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up);
break;
case Messages::TouchEvent: {
if (state != States::Running) {
break;
Expand Down Expand Up @@ -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<Screens::PassKey>(this, bleController.GetPairingKey());
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;

case Apps::Notifications:
currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal);
Expand Down
1 change: 1 addition & 0 deletions src/displayapp/Messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace Pinetime {
UpdateTimeOut,
DimScreen,
RestoreBrightness,
ShowPairingKey,
AlarmTriggered
};
}
Expand Down
24 changes: 24 additions & 0 deletions src/displayapp/screens/PassKey.cpp
Original file line number Diff line number Diff line change
@@ -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());
}

21 changes: 21 additions & 0 deletions src/displayapp/screens/PassKey.h
Original file line number Diff line number Diff line change
@@ -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;
};
}
}
}
Loading