Bluetooth: Mesh: Add Provisioner Over PB-GATT Support
Add support provisioner over pb-gatt.
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
diff --git a/include/bluetooth/mesh/main.h b/include/bluetooth/mesh/main.h
index 71fccd8..7ffba08 100644
--- a/include/bluetooth/mesh/main.h
+++ b/include/bluetooth/mesh/main.h
@@ -213,6 +213,17 @@
bt_mesh_prov_oob_info_t oob_info,
uint32_t *uri_hash);
+ /** @brief PB-GATT Unprovisioned Advertising has been received.
+ *
+ * This callback notifies the application that an PB-GATT
+ * unprovisioned Advertising has been received.
+ *
+ * @param uuid UUID
+ * @param oob_info OOB Information
+ */
+ void (*unprovisioned_beacon_gatt)(uint8_t uuid[16],
+ bt_mesh_prov_oob_info_t oob_info);
+
/** @brief Provisioning link has been opened.
*
* This callback notifies the application that a provisioning
@@ -424,6 +435,19 @@
int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
uint8_t attention_duration);
+/** @brief Provision a Mesh Node using PB-GATT
+ *
+ * @param uuid UUID
+ * @param net_idx Network Key Index
+ * @param addr Address to assign to remote device. If addr is 0,
+ * the lowest available address will be chosen.
+ * @param attention_duration The attention duration to be send to remote device
+ *
+ * @return Zero on success or (negative) error code otherwise.
+ */
+int bt_mesh_provision_gatt(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration);
+
/** @brief Check if the local node has been provisioned.
*
* This API can be used to check if the local node has been provisioned
diff --git a/subsys/bluetooth/mesh/CMakeLists.txt b/subsys/bluetooth/mesh/CMakeLists.txt
index d6f0baf..3b0ff51 100644
--- a/subsys/bluetooth/mesh/CMakeLists.txt
+++ b/subsys/bluetooth/mesh/CMakeLists.txt
@@ -39,10 +39,9 @@
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_ADV pb_adv.c)
-zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_GATT
- pb_gatt.c
- pb_gatt_srv.c
-)
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_GATT_COMMON pb_gatt.c)
+
+zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_GATT pb_gatt_srv.c)
zephyr_library_sources_ifdef(CONFIG_BT_MESH_PB_GATT_CLIENT pb_gatt_cli.c)
diff --git a/subsys/bluetooth/mesh/Kconfig b/subsys/bluetooth/mesh/Kconfig
index 522bc5f..63443af 100644
--- a/subsys/bluetooth/mesh/Kconfig
+++ b/subsys/bluetooth/mesh/Kconfig
@@ -62,7 +62,7 @@
config BT_MESH_PROVISIONER
bool "Provisioner support"
depends on BT_MESH_PROV
- depends on BT_MESH_PB_ADV
+ depends on BT_MESH_PB_ADV || BT_MESH_PB_GATT_CLIENT
help
Enable this option to have support for provisioning remote devices.
@@ -123,10 +123,26 @@
select BT_MESH_GATT
select BT_GATT_DYNAMIC_DB
+config BT_MESH_PB_GATT_COMMON
+ bool
+
+config BT_MESH_PB_GATT_CLIENT
+ bool "Provisioner support using GATT (PB-GATT)"
+ select BT_MESH_PROV
+ select BT_GATT_CLIENT
+ select BT_MESH_GATT_CLIENT
+ select BT_MESH_PB_GATT_COMMON
+ select BT_MESH_PROVISIONER
+ depends on BT_CENTRAL
+ help
+ Enable this option to allow the provisioner provisioning the
+ device over GATT.
+
config BT_MESH_PB_GATT
bool "Provisioning support using GATT (PB-GATT)"
select BT_MESH_GATT_SERVER
select BT_MESH_PROV
+ select BT_MESH_PB_GATT_COMMON
help
Enable this option to allow the device to be provisioned over
GATT.
diff --git a/subsys/bluetooth/mesh/gatt_cli.c b/subsys/bluetooth/mesh/gatt_cli.c
index 02c4e1d..1bc06e9 100644
--- a/subsys/bluetooth/mesh/gatt_cli.c
+++ b/subsys/bluetooth/mesh/gatt_cli.c
@@ -33,6 +33,7 @@
#include "proxy_msg.h"
#include "proxy_cli.h"
#include "gatt_cli.h"
+#include "pb_gatt_cli.h"
static struct bt_mesh_gatt_server {
struct bt_conn *conn;
@@ -282,6 +283,11 @@
bt_mesh_proxy_cli_adv_recv(info, buf);
break;
#endif
+#if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
+ case BT_UUID_MESH_PROV_VAL:
+ bt_mesh_pb_gatt_cli_adv_recv(info, buf);
+ break;
+#endif
default:
break;
diff --git a/subsys/bluetooth/mesh/main.c b/subsys/bluetooth/mesh/main.c
index dfe850f..05fb793 100644
--- a/subsys/bluetooth/mesh/main.c
+++ b/subsys/bluetooth/mesh/main.c
@@ -142,6 +142,25 @@
return -ENOTSUP;
}
+int bt_mesh_provision_gatt(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
+ return -EINVAL;
+ }
+
+ if (bt_mesh_subnet_get(net_idx) == NULL) {
+ return -EINVAL;
+ }
+
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT_CLIENT)) {
+ return bt_mesh_pb_gatt_open(uuid, net_idx, addr,
+ attention_duration);
+ }
+
+ return -ENOTSUP;
+}
+
void bt_mesh_reset(void)
{
if (!atomic_test_bit(bt_mesh.flags, BT_MESH_VALID)) {
diff --git a/subsys/bluetooth/mesh/pb_gatt.c b/subsys/bluetooth/mesh/pb_gatt.c
index 83e1fe6..1d83d2d 100644
--- a/subsys/bluetooth/mesh/pb_gatt.c
+++ b/subsys/bluetooth/mesh/pb_gatt.c
@@ -14,6 +14,7 @@
#include "pb_gatt.h"
#include "proxy_msg.h"
#include "pb_gatt_srv.h"
+#include "pb_gatt_cli.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_PROV)
#define LOG_MODULE_NAME bt_mesh_pb_gatt
@@ -57,12 +58,23 @@
static void protocol_timeout(struct k_work *work)
{
- if (!link.conn) {
- /* Already disconnected */
+ if (!atomic_test_bit(bt_mesh_prov_link.flags, LINK_ACTIVE)) {
return;
}
+ /* If connection failed or timeout, not allow establish connection */
+ if (IS_ENABLED(CONFIG_BT_MESH_PB_GATT_CLIENT) &&
+ atomic_test_bit(bt_mesh_prov_link.flags, PROVISIONER)) {
+ if (link.conn) {
+ (void)bt_conn_disconnect(link.conn,
+ BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+ } else {
+ (void)bt_mesh_pb_gatt_cli_setup(NULL);
+ }
+ }
+
BT_DBG("Protocol timeout");
+
link_closed(PROV_BEARER_LINK_STATUS_TIMEOUT);
}
@@ -87,7 +99,7 @@
return 0;
}
-int bt_mesh_pb_gatt_open(struct bt_conn *conn)
+int bt_mesh_pb_gatt_start(struct bt_conn *conn)
{
BT_DBG("conn %p", (void *)conn);
@@ -117,6 +129,55 @@
return 0;
}
+#if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
+int bt_mesh_pb_gatt_cli_start(struct bt_conn *conn)
+{
+ BT_DBG("conn %p", (void *)conn);
+
+ if (link.conn) {
+ return -EBUSY;
+ }
+
+ link.conn = bt_conn_ref(conn);
+ k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT);
+
+ return 0;
+}
+
+int bt_mesh_pb_gatt_cli_open(struct bt_conn *conn)
+{
+ BT_DBG("conn %p", (void *)conn);
+
+ if (link.conn != conn) {
+ BT_DBG("Not connected");
+ return -ENOTCONN;
+ }
+
+ link.cb->link_opened(&pb_gatt, link.cb_data);
+
+ return 0;
+}
+
+static int prov_link_open(const uint8_t uuid[16], k_timeout_t timeout,
+ const struct prov_bearer_cb *cb, void *cb_data)
+{
+ BT_DBG("uuid %s", bt_hex(uuid, 16));
+
+ link.cb = cb;
+ link.cb_data = cb_data;
+
+ k_work_reschedule(&link.prot_timer, timeout);
+
+ return bt_mesh_pb_gatt_cli_setup(uuid);
+}
+
+static void prov_link_close(enum prov_bearer_link_status status)
+{
+ (void)bt_conn_disconnect(link.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
+}
+#endif
+
+#if defined(CONFIG_BT_MESH_PB_GATT)
static int link_accept(const struct prov_bearer_cb *cb, void *cb_data)
{
int err;
@@ -135,6 +196,7 @@
return 0;
}
+#endif
static void buf_send_end(struct bt_conn *conn, void *user_data)
{
@@ -155,7 +217,8 @@
k_work_reschedule(&link.prot_timer, PROTOCOL_TIMEOUT);
- return bt_mesh_pb_gatt_send(link.conn, buf, buf_send_end, NULL);
+ return bt_mesh_proxy_msg_send(link.conn, BT_MESH_PROXY_PROV,
+ buf, buf_send_end, NULL);
}
static void clear_tx(void)
@@ -175,7 +238,13 @@
const struct prov_bearer pb_gatt = {
.type = BT_MESH_PROV_GATT,
+#if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
+ .link_open = prov_link_open,
+ .link_close = prov_link_close,
+#endif
+#if defined(CONFIG_BT_MESH_PB_GATT)
.link_accept = link_accept,
+#endif
.send = buf_send,
.clear_tx = clear_tx,
};
diff --git a/subsys/bluetooth/mesh/pb_gatt.h b/subsys/bluetooth/mesh/pb_gatt.h
index 6b9d7de..68e0652 100644
--- a/subsys/bluetooth/mesh/pb_gatt.h
+++ b/subsys/bluetooth/mesh/pb_gatt.h
@@ -9,3 +9,6 @@
int bt_mesh_pb_gatt_start(struct bt_conn *conn);
int bt_mesh_pb_gatt_close(struct bt_conn *conn);
int bt_mesh_pb_gatt_recv(struct bt_conn *conn, struct net_buf_simple *buf);
+
+int bt_mesh_pb_gatt_cli_open(struct bt_conn *conn);
+int bt_mesh_pb_gatt_cli_start(struct bt_conn *conn);
diff --git a/subsys/bluetooth/mesh/pb_gatt_cli.c b/subsys/bluetooth/mesh/pb_gatt_cli.c
index 60e9a40..9329560 100644
--- a/subsys/bluetooth/mesh/pb_gatt_cli.c
+++ b/subsys/bluetooth/mesh/pb_gatt_cli.c
@@ -58,11 +58,13 @@
pb_gatt_msg_recv);
server.target = NULL;
+
+ bt_mesh_pb_gatt_cli_start(conn);
}
static void pb_gatt_link_open(struct bt_conn *conn)
{
- bt_mesh_pb_gatt_start(conn);
+ bt_mesh_pb_gatt_cli_open(conn);
}
static void pb_gatt_disconnected(struct bt_conn *conn)
diff --git a/subsys/bluetooth/mesh/pb_gatt_cli.h b/subsys/bluetooth/mesh/pb_gatt_cli.h
new file mode 100644
index 0000000..6ec0b52
--- /dev/null
+++ b/subsys/bluetooth/mesh/pb_gatt_cli.h
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2021 Xiaomi Corporation
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+
+int bt_mesh_pb_gatt_cli_setup(const uint8_t uuid[16]);
+
+void bt_mesh_pb_gatt_cli_adv_recv(const struct bt_le_scan_recv_info *info,
+ struct net_buf_simple *buf);
diff --git a/subsys/bluetooth/mesh/pb_gatt_srv.c b/subsys/bluetooth/mesh/pb_gatt_srv.c
index 5f2489e..cb67279 100644
--- a/subsys/bluetooth/mesh/pb_gatt_srv.c
+++ b/subsys/bluetooth/mesh/pb_gatt_srv.c
@@ -148,7 +148,7 @@
return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
}
- bt_mesh_pb_gatt_open(conn);
+ bt_mesh_pb_gatt_start(conn);
return sizeof(value);
}
@@ -220,17 +220,6 @@
BT_DATA(BT_DATA_SVC_DATA16, prov_svc_data, sizeof(prov_svc_data)),
};
-int bt_mesh_pb_gatt_send(struct bt_conn *conn, struct net_buf_simple *buf,
- bt_gatt_complete_func_t end, void *user_data)
-{
- if (!cli || cli->conn != conn) {
- BT_ERR("No PB-GATT Client found");
- return -ENOTCONN;
- }
-
- return bt_mesh_proxy_msg_send(conn, BT_MESH_PROXY_PROV, buf, end, user_data);
-}
-
static size_t gatt_prov_adv_create(struct bt_data prov_sd[1])
{
const struct bt_mesh_prov *prov = bt_mesh_prov_get();
diff --git a/subsys/bluetooth/mesh/pb_gatt_srv.h b/subsys/bluetooth/mesh/pb_gatt_srv.h
index 105f7b9..24a2306 100644
--- a/subsys/bluetooth/mesh/pb_gatt_srv.h
+++ b/subsys/bluetooth/mesh/pb_gatt_srv.h
@@ -10,9 +10,6 @@
#include <bluetooth/gatt.h>
-int bt_mesh_pb_gatt_send(struct bt_conn *conn, struct net_buf_simple *buf,
- bt_gatt_complete_func_t end, void *user_data);
-
int bt_mesh_pb_gatt_enable(void);
int bt_mesh_pb_gatt_disable(void);
diff --git a/subsys/bluetooth/mesh/provisioner.c b/subsys/bluetooth/mesh/provisioner.c
index e5b5fe5..e1c947a 100644
--- a/subsys/bluetooth/mesh/provisioner.c
+++ b/subsys/bluetooth/mesh/provisioner.c
@@ -726,9 +726,10 @@
return 0;
}
-#if defined(CONFIG_BT_MESH_PB_ADV)
-int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
- uint8_t attention_duration)
+static int bt_mesh_provisioner_open(const struct prov_bearer *bearer,
+ const uint8_t uuid[16],
+ uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
{
int err;
@@ -746,7 +747,7 @@
prov_device.addr = addr;
prov_device.net_idx = net_idx;
prov_device.attention_duration = attention_duration;
- bt_mesh_prov_link.bearer = &pb_adv;
+ bt_mesh_prov_link.bearer = bearer;
bt_mesh_prov_link.role = &role_provisioner;
err = bt_mesh_prov_link.bearer->link_open(prov_device.uuid, PROTOCOL_TIMEOUT,
@@ -757,4 +758,19 @@
return err;
}
+
+#if defined(CONFIG_BT_MESH_PB_ADV)
+int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ return bt_mesh_provisioner_open(&pb_adv, uuid, net_idx, addr, attention_duration);
+}
+#endif
+
+#if defined(CONFIG_BT_MESH_PB_GATT_CLIENT)
+int bt_mesh_pb_gatt_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration)
+{
+ return bt_mesh_provisioner_open(&pb_gatt, uuid, net_idx, addr, attention_duration);
+}
#endif
diff --git a/subsys/bluetooth/mesh/provisioner.h b/subsys/bluetooth/mesh/provisioner.h
index ac58ab3..0745ff3 100644
--- a/subsys/bluetooth/mesh/provisioner.h
+++ b/subsys/bluetooth/mesh/provisioner.h
@@ -7,3 +7,6 @@
int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
uint8_t attention_duration);
+
+int bt_mesh_pb_gatt_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr,
+ uint8_t attention_duration);