drivers/nble: Sync smp code for firmware compatibility
This moves SMP related code to smp.c making code similar to the tree of firmware developers. Change-Id: I5b43dcbe40a721e11b64cbdd4203406e721f40cd Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
This commit is contained in:
parent
803de8d14e
commit
ed044a7279
|
@ -1,5 +1,5 @@
|
|||
subdir-ccflags-$(CONFIG_NBLE) +=-I$(srctree)/drivers/bluetooth
|
||||
|
||||
obj-$(CONFIG_NBLE) += gap.o conn.o gatt.o uart.o rpc_serialize.o \
|
||||
rpc_deserialize.o stubs.o \
|
||||
rpc_deserialize.o stubs.o smp.o \
|
||||
../../../net/bluetooth/uuid.o
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "gap_internal.h"
|
||||
#include "gatt_internal.h"
|
||||
#include "conn_internal.h"
|
||||
#include "smp.h"
|
||||
|
||||
#if !defined(CONFIG_NBLE_DEBUG_CONN)
|
||||
#undef BT_DBG
|
||||
|
@ -392,6 +393,10 @@ static void notify_connected(struct bt_conn *conn)
|
|||
{
|
||||
struct bt_conn_cb *cb;
|
||||
|
||||
/* TODO: Add l2cap_connected callback if needed */
|
||||
|
||||
bt_smp_connected(conn);
|
||||
|
||||
for (cb = callback_list; cb; cb = cb->_next) {
|
||||
if (cb->connected) {
|
||||
cb->connected(conn, 0);
|
||||
|
@ -404,6 +409,7 @@ static void notify_disconnected(struct bt_conn *conn)
|
|||
struct bt_conn_cb *cb;
|
||||
|
||||
bt_gatt_disconnected(conn);
|
||||
bt_smp_disconnected(conn);
|
||||
|
||||
/*
|
||||
* FIXME: When disconnected NBLE stops advertising, this should
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "uart.h"
|
||||
#include "conn.h"
|
||||
#include "rpc.h"
|
||||
#include "smp.h"
|
||||
|
||||
/* Set the firmware compatible with Nordic BLE RPC */
|
||||
static uint8_t compatible_firmware[4] = { '0', '5', '2', '7' };
|
||||
|
@ -45,17 +46,6 @@ struct nble nble;
|
|||
|
||||
static const struct bt_storage *storage;
|
||||
|
||||
#define BT_SMP_IO_DISPLAY_ONLY 0x00
|
||||
#define BT_SMP_IO_DISPLAY_YESNO 0x01
|
||||
#define BT_SMP_IO_KEYBOARD_ONLY 0x02
|
||||
#define BT_SMP_IO_NO_INPUT_OUTPUT 0x03
|
||||
#define BT_SMP_IO_KEYBOARD_DISPLAY 0x04
|
||||
|
||||
#define BT_SMP_OOB_NOT_PRESENT 0x00
|
||||
#define BT_SMP_OOB_PRESENT 0x01
|
||||
|
||||
#define BT_SMP_MAX_ENC_KEY_SIZE 16
|
||||
|
||||
#if defined(CONFIG_NBLE_DEBUG_GAP)
|
||||
static const char *bt_addr_le_str(const bt_addr_le_t *addr)
|
||||
{
|
||||
|
@ -367,189 +357,11 @@ void on_nble_common_rsp(const struct nble_common_rsp *rsp)
|
|||
BT_DBG("status %d", rsp->status);
|
||||
}
|
||||
|
||||
/* Security Manager event handling */
|
||||
|
||||
static uint8_t get_io_capa(void)
|
||||
{
|
||||
if (!nble.auth) {
|
||||
return BT_SMP_IO_NO_INPUT_OUTPUT;
|
||||
}
|
||||
|
||||
/* Passkey Confirmation is valid only for LE SC */
|
||||
if (nble.auth->passkey_display && nble.auth->passkey_entry &&
|
||||
nble.auth->passkey_confirm) {
|
||||
return BT_SMP_IO_KEYBOARD_DISPLAY;
|
||||
}
|
||||
|
||||
/* DisplayYesNo is useful only for LE SC */
|
||||
if (nble.auth->passkey_display &&
|
||||
nble.auth->passkey_confirm) {
|
||||
return BT_SMP_IO_DISPLAY_YESNO;
|
||||
}
|
||||
|
||||
if (nble.auth->passkey_entry) {
|
||||
return BT_SMP_IO_KEYBOARD_ONLY;
|
||||
}
|
||||
|
||||
if (nble.auth->passkey_display) {
|
||||
return BT_SMP_IO_DISPLAY_ONLY;
|
||||
}
|
||||
|
||||
return BT_SMP_IO_NO_INPUT_OUTPUT;
|
||||
}
|
||||
|
||||
static void send_dm_config(void)
|
||||
{
|
||||
struct nble_sm_config_req config = {
|
||||
.key_size = BT_SMP_MAX_ENC_KEY_SIZE,
|
||||
.oob_present = BT_SMP_OOB_NOT_PRESENT,
|
||||
};
|
||||
|
||||
config.io_caps = get_io_capa();
|
||||
|
||||
if (config.io_caps == BT_SMP_IO_NO_INPUT_OUTPUT) {
|
||||
config.options = BT_SMP_AUTH_BONDING;
|
||||
} else {
|
||||
config.options = BT_SMP_AUTH_BONDING | BT_SMP_AUTH_MITM;
|
||||
}
|
||||
|
||||
BT_DBG("io_caps %u options %u", config.io_caps, config.options);
|
||||
|
||||
nble_sm_config_req(&config);
|
||||
}
|
||||
|
||||
void on_nble_sm_config_rsp(struct nble_sm_config_rsp *rsp)
|
||||
{
|
||||
if (rsp->status) {
|
||||
BT_ERR("SM config failed, status %d", rsp->status);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("status %u", rsp->status);
|
||||
|
||||
/* Get bdaddr queued after SM setup */
|
||||
nble_get_bda_req(NULL);
|
||||
}
|
||||
|
||||
void on_nble_sm_common_rsp(const struct nble_sm_common_rsp *rsp)
|
||||
{
|
||||
if (rsp->status) {
|
||||
BT_ERR("GAP SM request failed: conn %p err %d", rsp->conn,
|
||||
rsp->status);
|
||||
|
||||
/* TODO: Handle error */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void on_nble_sm_status_evt(const struct nble_sm_status_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
if (ev->status) {
|
||||
BT_ERR("SM request failed, status %d", ev->status);
|
||||
return;
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("conn %p status %d evt_type %d sec_level %d enc_size %u",
|
||||
conn, ev->status, ev->evt_type, ev->enc_link_sec.sec_level,
|
||||
ev->enc_link_sec.enc_size);
|
||||
|
||||
/* TODO Handle events */
|
||||
switch (ev->evt_type) {
|
||||
case NBLE_GAP_SM_EVT_START_PAIRING:
|
||||
BT_DBG("Start pairing");
|
||||
if (conn->role == BT_HCI_ROLE_MASTER) {
|
||||
bt_conn_security(conn, ev->enc_link_sec.sec_level);
|
||||
}
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_BONDING_COMPLETE:
|
||||
BT_DBG("Bonding complete");
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_LINK_ENCRYPTED:
|
||||
BT_DBG("Link encrypted");
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_LINK_SECURITY_CHANGE:
|
||||
BT_DBG("Security change");
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Unknown event %d", ev->evt_type);
|
||||
break;
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
void on_nble_sm_passkey_disp_evt(const struct nble_sm_passkey_disp_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("conn %p passkey %u", conn, ev->passkey);
|
||||
|
||||
/* TODO: Check shall we store io_caps globally */
|
||||
if (get_io_capa() == BT_SMP_IO_DISPLAY_YESNO) {
|
||||
nble.auth->passkey_confirm(conn, ev->passkey);
|
||||
} else {
|
||||
nble.auth->passkey_display(conn, ev->passkey);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
void on_nble_sm_passkey_req_evt(const struct nble_sm_passkey_req_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev->key_type == NBLE_GAP_SM_PK_PASSKEY) {
|
||||
nble.auth->passkey_entry(conn);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
static int sm_error(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
struct nble_sm_passkey_reply_req req;
|
||||
|
||||
req.conn = conn;
|
||||
req.conn_handle = conn->handle;
|
||||
|
||||
req.params.type = NBLE_GAP_SM_REJECT;
|
||||
req.params.reason = reason;
|
||||
|
||||
nble_sm_passkey_reply_req(&req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_smp_auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
return sm_error(conn, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
|
||||
}
|
||||
|
||||
void on_nble_up(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
send_dm_config();
|
||||
bt_smp_init();
|
||||
}
|
||||
|
||||
void bt_storage_register(const struct bt_storage *bt_storage)
|
||||
|
|
405
drivers/bluetooth/nble/smp.c
Normal file
405
drivers/bluetooth/nble/smp.c
Normal file
|
@ -0,0 +1,405 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <atomic.h>
|
||||
|
||||
#include <nanokernel.h>
|
||||
#include <device.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/log.h>
|
||||
|
||||
#include <misc/util.h>
|
||||
|
||||
#include "gap_internal.h"
|
||||
#include "conn_internal.h"
|
||||
#include "conn.h"
|
||||
|
||||
#define BT_SMP_IO_DISPLAY_ONLY 0x00
|
||||
#define BT_SMP_IO_DISPLAY_YESNO 0x01
|
||||
#define BT_SMP_IO_KEYBOARD_ONLY 0x02
|
||||
#define BT_SMP_IO_NO_INPUT_OUTPUT 0x03
|
||||
#define BT_SMP_IO_KEYBOARD_DISPLAY 0x04
|
||||
|
||||
#define BT_SMP_OOB_NOT_PRESENT 0x00
|
||||
#define BT_SMP_OOB_PRESENT 0x01
|
||||
|
||||
#define BT_SMP_MAX_ENC_KEY_SIZE 16
|
||||
|
||||
enum {
|
||||
SMP_FLAG_CFM_DELAYED, /* if confirm should be send when TK is valid */
|
||||
SMP_FLAG_ENC_PENDING, /* if waiting for an encryption change event */
|
||||
SMP_FLAG_KEYS_DISTR, /* if keys distribution phase is in progress */
|
||||
SMP_FLAG_PAIRING, /* if pairing is in progress */
|
||||
SMP_FLAG_TIMEOUT, /* if SMP timeout occurred */
|
||||
SMP_FLAG_SC, /* if LE Secure Connections is used */
|
||||
SMP_FLAG_PKEY_SEND, /* if should send Public Key when available */
|
||||
SMP_FLAG_DHKEY_PENDING, /* if waiting for local DHKey */
|
||||
SMP_FLAG_DHKEY_SEND, /* if should generate and send DHKey Check */
|
||||
SMP_FLAG_USER, /* if waiting for user input */
|
||||
SMP_FLAG_BOND, /* if bonding */
|
||||
SMP_FLAG_SC_DEBUG_KEY, /* if Secure Connection are using debug key */
|
||||
SMP_FLAG_SEC_REQ, /* if Security Request was sent/received */
|
||||
};
|
||||
|
||||
enum pairing_method {
|
||||
JUST_WORKS, /* JustWorks pairing */
|
||||
PASSKEY_INPUT, /* Passkey Entry input */
|
||||
PASSKEY_DISPLAY, /* Passkey Entry display */
|
||||
PASSKEY_CONFIRM, /* Passkey confirm */
|
||||
PASSKEY_ROLE, /* Passkey Entry depends on role */
|
||||
};
|
||||
|
||||
struct bt_smp {
|
||||
/* The channel this context is associated with (nble conn object)*/
|
||||
struct bt_conn *conn;
|
||||
|
||||
/* Flags for SMP state machine */
|
||||
atomic_t flags;
|
||||
|
||||
/* Type of method used for pairing */
|
||||
uint8_t method;
|
||||
};
|
||||
|
||||
static struct bt_smp bt_smp_pool[CONFIG_BLUETOOTH_MAX_CONN];
|
||||
|
||||
static struct bt_smp *smp_chan_get(struct bt_conn *conn)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
|
||||
struct bt_smp *smp = &bt_smp_pool[i];
|
||||
|
||||
if (smp->conn == conn) {
|
||||
return smp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void smp_reset(struct bt_smp *smp)
|
||||
{
|
||||
smp->flags = 0;
|
||||
smp->method = 0;
|
||||
smp->conn = NULL;
|
||||
}
|
||||
|
||||
void bt_smp_connected(struct bt_conn *conn)
|
||||
{
|
||||
struct bt_smp *smp = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
|
||||
smp = &bt_smp_pool[i];
|
||||
|
||||
if (!smp->conn) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset flags and states */
|
||||
smp_reset(smp);
|
||||
|
||||
smp->conn = conn;
|
||||
}
|
||||
|
||||
void bt_smp_disconnected(struct bt_conn *conn)
|
||||
{
|
||||
struct bt_smp *smp = smp_chan_get(conn);
|
||||
|
||||
if (smp) {
|
||||
smp_reset(smp);
|
||||
}
|
||||
}
|
||||
|
||||
/* based on table 2.8 Core Spec 2.3.5.1 Vol. 3 Part H */
|
||||
static const uint8_t gen_method_legacy[5 /* remote */][5 /* local */] = {
|
||||
{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT },
|
||||
{ JUST_WORKS, JUST_WORKS, PASSKEY_INPUT, JUST_WORKS, PASSKEY_INPUT },
|
||||
{ PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS,
|
||||
PASSKEY_DISPLAY },
|
||||
{ JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS, JUST_WORKS },
|
||||
{ PASSKEY_DISPLAY, PASSKEY_DISPLAY, PASSKEY_INPUT, JUST_WORKS,
|
||||
PASSKEY_ROLE },
|
||||
};
|
||||
|
||||
static uint8_t get_io_capa(void)
|
||||
{
|
||||
if (!nble.auth) {
|
||||
return BT_SMP_IO_NO_INPUT_OUTPUT;
|
||||
}
|
||||
|
||||
/* Passkey Confirmation is valid only for LE SC */
|
||||
if (nble.auth->passkey_display && nble.auth->passkey_entry &&
|
||||
nble.auth->passkey_confirm) {
|
||||
return BT_SMP_IO_KEYBOARD_DISPLAY;
|
||||
}
|
||||
|
||||
/* DisplayYesNo is useful only for LE SC */
|
||||
if (nble.auth->passkey_display &&
|
||||
nble.auth->passkey_confirm) {
|
||||
return BT_SMP_IO_DISPLAY_YESNO;
|
||||
}
|
||||
|
||||
if (nble.auth->passkey_entry) {
|
||||
return BT_SMP_IO_KEYBOARD_ONLY;
|
||||
}
|
||||
|
||||
if (nble.auth->passkey_display) {
|
||||
return BT_SMP_IO_DISPLAY_ONLY;
|
||||
}
|
||||
|
||||
return BT_SMP_IO_NO_INPUT_OUTPUT;
|
||||
}
|
||||
|
||||
static uint8_t legacy_get_pair_method(struct bt_smp *smp, uint8_t remote_io)
|
||||
{
|
||||
uint8_t local_io = get_io_capa();
|
||||
uint8_t method;
|
||||
|
||||
BT_DBG("local_io %u remote_io %u", local_io, remote_io);
|
||||
|
||||
if (remote_io > BT_SMP_IO_KEYBOARD_DISPLAY)
|
||||
return JUST_WORKS;
|
||||
|
||||
method = gen_method_legacy[remote_io][local_io];
|
||||
|
||||
/* if both sides have KeyboardDisplay capabilities, initiator displays
|
||||
* and responder inputs
|
||||
*/
|
||||
if (method == PASSKEY_ROLE) {
|
||||
if (smp->conn->role == BT_HCI_ROLE_MASTER) {
|
||||
method = PASSKEY_DISPLAY;
|
||||
} else {
|
||||
method = PASSKEY_INPUT;
|
||||
}
|
||||
}
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
static uint8_t legacy_pairing_req(struct bt_smp *smp, uint8_t remote_io)
|
||||
{
|
||||
struct nble_sm_pairing_response_req params;
|
||||
|
||||
smp->method = legacy_get_pair_method(smp, remote_io);
|
||||
|
||||
BT_DBG("method %u remote_io %u", smp->method, remote_io);
|
||||
|
||||
/* ask for consent if pairing is not due to sending SecReq*/
|
||||
if (smp->method == JUST_WORKS &&
|
||||
!atomic_test_bit(&smp->flags, SMP_FLAG_SEC_REQ) &&
|
||||
nble.auth && nble.auth->pairing_confirm) {
|
||||
atomic_set_bit(&smp->flags, SMP_FLAG_USER);
|
||||
nble.auth->pairing_confirm(smp->conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: io caps */
|
||||
params.conn = smp->conn;
|
||||
params.conn_handle = smp->conn->handle;
|
||||
nble_sm_pairing_response_req(¶ms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void on_nble_sm_pairing_request_evt(const struct nble_sm_pairing_request_evt *evt)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
struct bt_smp *smp;
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
conn = bt_conn_lookup_handle(evt->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", evt->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
smp = smp_chan_get(conn);
|
||||
if (!smp) {
|
||||
BT_ERR("No smp");
|
||||
bt_conn_unref(conn);
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_set_bit(&smp->flags, SMP_FLAG_PAIRING);
|
||||
|
||||
legacy_pairing_req(smp, evt->sec_param.remote_io);
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
void send_dm_config(void)
|
||||
{
|
||||
struct nble_sm_config_req config = {
|
||||
.key_size = BT_SMP_MAX_ENC_KEY_SIZE,
|
||||
.oob_present = BT_SMP_OOB_NOT_PRESENT,
|
||||
};
|
||||
|
||||
config.io_caps = get_io_capa();
|
||||
|
||||
if (config.io_caps == BT_SMP_IO_NO_INPUT_OUTPUT) {
|
||||
config.options = BT_SMP_AUTH_BONDING;
|
||||
} else {
|
||||
config.options = BT_SMP_AUTH_BONDING | BT_SMP_AUTH_MITM;
|
||||
}
|
||||
|
||||
BT_DBG("io_caps %u options %u", config.io_caps, config.options);
|
||||
|
||||
nble_sm_config_req(&config);
|
||||
}
|
||||
|
||||
void on_nble_sm_config_rsp(struct nble_sm_config_rsp *rsp)
|
||||
{
|
||||
if (rsp->status) {
|
||||
BT_ERR("SM config failed, status %d", rsp->status);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("status %u", rsp->status);
|
||||
|
||||
/* Get bdaddr queued after SM setup */
|
||||
nble_get_bda_req(NULL);
|
||||
}
|
||||
|
||||
void on_nble_sm_common_rsp(const struct nble_sm_common_rsp *rsp)
|
||||
{
|
||||
if (rsp->status) {
|
||||
BT_ERR("GAP SM request failed: conn %p err %d", rsp->conn,
|
||||
rsp->status);
|
||||
|
||||
/* TODO: Handle error */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void on_nble_sm_status_evt(const struct nble_sm_status_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
if (ev->status) {
|
||||
BT_ERR("SM request failed, status %d", ev->status);
|
||||
return;
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("conn %p status %d evt_type %d sec_level %d enc_size %u",
|
||||
conn, ev->status, ev->evt_type, ev->enc_link_sec.sec_level,
|
||||
ev->enc_link_sec.enc_size);
|
||||
|
||||
/* TODO Handle events */
|
||||
switch (ev->evt_type) {
|
||||
case NBLE_GAP_SM_EVT_START_PAIRING:
|
||||
BT_DBG("Start pairing");
|
||||
if (conn->role == BT_HCI_ROLE_MASTER) {
|
||||
bt_conn_security(conn, ev->enc_link_sec.sec_level);
|
||||
}
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_BONDING_COMPLETE:
|
||||
BT_DBG("Bonding complete");
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_LINK_ENCRYPTED:
|
||||
BT_DBG("Link encrypted");
|
||||
break;
|
||||
case NBLE_GAP_SM_EVT_LINK_SECURITY_CHANGE:
|
||||
BT_DBG("Security change");
|
||||
break;
|
||||
default:
|
||||
BT_ERR("Unknown event %d", ev->evt_type);
|
||||
break;
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
void on_nble_sm_passkey_disp_evt(const struct nble_sm_passkey_disp_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
BT_DBG("conn %p passkey %u", conn, ev->passkey);
|
||||
|
||||
/* TODO: Check shall we store io_caps globally */
|
||||
if (get_io_capa() == BT_SMP_IO_DISPLAY_YESNO) {
|
||||
nble.auth->passkey_confirm(conn, ev->passkey);
|
||||
} else {
|
||||
nble.auth->passkey_display(conn, ev->passkey);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
void on_nble_sm_passkey_req_evt(const struct nble_sm_passkey_req_evt *ev)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_handle(ev->conn_handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Unable to find conn for handle %u", ev->conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ev->key_type == NBLE_GAP_SM_PK_PASSKEY) {
|
||||
nble.auth->passkey_entry(conn);
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
static int sm_error(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
struct nble_sm_passkey_reply_req req;
|
||||
|
||||
req.conn = conn;
|
||||
req.conn_handle = conn->handle;
|
||||
|
||||
req.params.type = NBLE_GAP_SM_REJECT;
|
||||
req.params.reason = reason;
|
||||
|
||||
nble_sm_passkey_reply_req(&req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_smp_auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
return sm_error(conn, BT_SMP_ERR_PASSKEY_ENTRY_FAILED);
|
||||
}
|
||||
|
||||
int bt_smp_init(void)
|
||||
{
|
||||
BT_DBG("");
|
||||
|
||||
send_dm_config();
|
||||
|
||||
return 0;
|
||||
}
|
19
drivers/bluetooth/nble/smp.h
Normal file
19
drivers/bluetooth/nble/smp.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
void bt_smp_connected(struct bt_conn *conn);
|
||||
void bt_smp_disconnected(struct bt_conn *conn);
|
||||
int bt_smp_init(void);
|
Loading…
Reference in a new issue