From 2ead5725b14bff1dc6f9972ee0a7b970f16a339e Mon Sep 17 00:00:00 2001 From: Lingao Meng Date: Mon, 7 Feb 2022 17:25:09 +0800 Subject: [PATCH] Bluetooth: Mesh: Add Provisioner Over PB-GATT Support Add support provisioner over pb-gatt. Signed-off-by: Lingao Meng --- include/bluetooth/mesh/main.h | 24 +++++++++ subsys/bluetooth/mesh/CMakeLists.txt | 7 ++- subsys/bluetooth/mesh/Kconfig | 18 ++++++- subsys/bluetooth/mesh/gatt_cli.c | 6 +++ subsys/bluetooth/mesh/main.c | 19 +++++++ subsys/bluetooth/mesh/pb_gatt.c | 77 ++++++++++++++++++++++++++-- subsys/bluetooth/mesh/pb_gatt.h | 3 ++ subsys/bluetooth/mesh/pb_gatt_cli.c | 4 +- subsys/bluetooth/mesh/pb_gatt_cli.h | 11 ++++ subsys/bluetooth/mesh/pb_gatt_srv.c | 13 +---- subsys/bluetooth/mesh/pb_gatt_srv.h | 3 -- subsys/bluetooth/mesh/provisioner.c | 24 +++++++-- subsys/bluetooth/mesh/provisioner.h | 3 ++ 13 files changed, 183 insertions(+), 29 deletions(-) create mode 100644 subsys/bluetooth/mesh/pb_gatt_cli.h diff --git a/include/bluetooth/mesh/main.h b/include/bluetooth/mesh/main.h index 71fccd80ce4..7ffba084b71 100644 --- a/include/bluetooth/mesh/main.h +++ b/include/bluetooth/mesh/main.h @@ -213,6 +213,17 @@ struct bt_mesh_prov { 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(const uint8_t net_key[16], uint16_t net_idx, 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 d6f0baf2424..3b0ff517414 100644 --- a/subsys/bluetooth/mesh/CMakeLists.txt +++ b/subsys/bluetooth/mesh/CMakeLists.txt @@ -39,10 +39,9 @@ zephyr_library_sources_ifdef(CONFIG_BT_MESH_PROVISIONER provisioner.c) 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 522bc5f9134..63443af8763 100644 --- a/subsys/bluetooth/mesh/Kconfig +++ b/subsys/bluetooth/mesh/Kconfig @@ -62,7 +62,7 @@ config BT_MESH_PB_ADV_RETRANS_TIMEOUT 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 @@ config BT_MESH_GATT_SERVER 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 02c4e1d675c..1bc06e930ae 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 @@ static void gatt_advertising_recv(const struct bt_le_scan_recv_info *info, 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 dfe850f0d61..05fb79301fe 100644 --- a/subsys/bluetooth/mesh/main.c +++ b/subsys/bluetooth/mesh/main.c @@ -142,6 +142,25 @@ int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t add 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 83e1fe6ebaf..1d83d2d0efb 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 link_closed(enum prov_bearer_link_status status) 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 @@ int bt_mesh_pb_gatt_recv(struct bt_conn *conn, struct net_buf_simple *buf) 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 @@ int bt_mesh_pb_gatt_close(struct bt_conn *conn) 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 @@ static int link_accept(const struct prov_bearer_cb *cb, void *cb_data) return 0; } +#endif static void buf_send_end(struct bt_conn *conn, void *user_data) { @@ -155,7 +217,8 @@ static int buf_send(struct net_buf_simple *buf, prov_bearer_send_complete_t cb, 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 @@ void pb_gatt_reset(void) 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 6b9d7de8e22..68e06523f15 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 60e9a40fa0b..9329560b945 100644 --- a/subsys/bluetooth/mesh/pb_gatt_cli.c +++ b/subsys/bluetooth/mesh/pb_gatt_cli.c @@ -58,11 +58,13 @@ static void pb_gatt_connected(struct bt_conn *conn, void *user_data) 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 00000000000..6ec0b5271dc --- /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 5f2489ed6e1..cb67279f736 100644 --- a/subsys/bluetooth/mesh/pb_gatt_srv.c +++ b/subsys/bluetooth/mesh/pb_gatt_srv.c @@ -148,7 +148,7 @@ static ssize_t prov_ccc_write(struct bt_conn *conn, 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 @@ static const struct bt_data prov_ad[] = { 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 105f7b9a3cf..24a23069251 100644 --- a/subsys/bluetooth/mesh/pb_gatt_srv.h +++ b/subsys/bluetooth/mesh/pb_gatt_srv.h @@ -10,9 +10,6 @@ #include -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 e5b5fe50b3e..e1c947a6909 100644 --- a/subsys/bluetooth/mesh/provisioner.c +++ b/subsys/bluetooth/mesh/provisioner.c @@ -726,9 +726,10 @@ int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[BT_PUB_KEY_LEN]) 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 @@ int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, 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 @@ int bt_mesh_pb_adv_open(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, 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 ac58ab383a3..0745ff34820 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);