Hi Brian, thanks for looking for my patches :-) On Tuesday, 1 July 2025, 20:52:35 CEST, Brian Gix wrote: > Hi Christian, > > I have not yet reviewed your patch set, but I do have a few > comments/questions to start off to learn the "theory of operation". > > GATT-Proxy mesh of course was always intended to be a temporary "Legacy > Support" feature. I think that the GATT specification was written in about 2017. It mentions "Legacy phones" where the OS does not allow to send arbitrary ADV messages. Has anything changed since then? > There should never need to be support for a BlueZ/Linux > based GATT Client, as the assumption is that if support for GATT-Proxy is > added, that it would be for the Server side only... I haven't thought about it yet... But as Linux is NOT a legacy system and all Mesh nodes need to support MESH-ADV, there should be no need for a GATT Proxy Client under Linux (exception: I use meshctl for testing my GATT Proxy Server) ... > A server that could accept incoming GATT/ATT-ACL connections and then > propagate GATT based mesh packets via ADV packets. That's what I am currently working on (although I haven't implemented the proxy's 'relaying' feature yet). > Once it is decided that a GATT Proxy server is a valid use case for the > mesh daemon, then it is also important the mesh daemon function as a fully > compliant client of the bluetoothd daemon. All ACL traffic *MUST* be > centralized in the bluetoothd daemon, with the mesh daemon appearing as a > standard dbus based client. Otherwise the concept of the GATT database of > all services (not just the GATT Mesh Proxy service) totally falls apart. I already expected that there must be a reason for a centralized GATT service per host. > The only possible exception to this is if it is written for a > multi-controler environment, where one BT controller is fully owned and > controlled by the mesh daemon, and used for GATT-Proxy messages only, and > the other BT controller(s) are shared with bluetoothd, and used for ADV > traffic. This is strongly discouraged however, because multi-controller > operation becomes fraught when there is not central control of the pool of > available controllers. And our main mission during mesh daemon development > was near-Zero impact on "classic bluetooth" operation. This is NOT what I intend (our embedded systems have only one Bluetooth controller, this must be sufficient). > So can you confirm that: > 1. You intend to add *GATT Server only* to the mesh daemon (no GATT clients > allowed)? Yes, I do not intend to implement a GATT client in bluetooth-meshd (although I mentioned this possibility in my previous answer to Luiz). > 2. That the GATT Server itself is *hosted* in bluetoothd itself, with no > ACL connections/L2CAP layer etc owned by the mesh daemon? Yes, I use the GATT server facility of bluetoothd in bluetooth-meshd (via D-Bus, not using non-documented interfaces). > 3. There is a valid use case (Mesh GATT Proxy Clients that cannot for some > reason issue Mesh ADV packets themselves)? Yes, my assumption is that mobile phones still don't support MESH ADV (at the the SMART+ app is a Mesh GATT Proxy Client). > Regards, > Brian Gix regards, Christian > > > On Tue, Jul 1, 2025 at 7:48 AM Christian Eggers <ceggers@xxxxxxx> wrote: > > > FIXME: net.c: determine whether data shall be sent via mesh_io or > > gatt_proxy > > --- > > Makefile.mesh | 3 +- > > mesh/gatt-proxy-svc.c | 294 ++++++++++++++++++++++++++++++++++++++++++ > > mesh/gatt-proxy-svc.h | 29 +++++ > > mesh/main.c | 3 + > > mesh/net-keys.c | 61 +++++++++ > > mesh/net-keys.h | 4 + > > mesh/net.c | 21 ++- > > mesh/net.h | 4 + > > mesh/prov-acceptor.c | 26 +++- > > 9 files changed, 440 insertions(+), 5 deletions(-) > > create mode 100644 mesh/gatt-proxy-svc.c > > create mode 100644 mesh/gatt-proxy-svc.h > > > > diff --git a/Makefile.mesh b/Makefile.mesh > > index 700d64fe9293..8a190f75de9d 100644 > > --- a/Makefile.mesh > > +++ b/Makefile.mesh > > @@ -40,7 +40,8 @@ mesh_sources = mesh/mesh.h mesh/mesh.c \ > > mesh/rpl.h mesh/rpl.c \ > > mesh/prv-beacon.h mesh/prvbeac-server.c \ > > mesh/mesh-defs.h \ > > - mesh/gatt-service.h mesh/gatt-service.c > > + mesh/gatt-service.h mesh/gatt-service.c \ > > + mesh/gatt-proxy-svc.h mesh/gatt-proxy-svc.c > > pkglibexec_PROGRAMS += mesh/bluetooth-meshd > > > > mesh/mesh.$(OBJEXT): ell/internal > > diff --git a/mesh/gatt-proxy-svc.c b/mesh/gatt-proxy-svc.c > > new file mode 100644 > > index 000000000000..e24543de718c > > --- /dev/null > > +++ b/mesh/gatt-proxy-svc.c > > @@ -0,0 +1,294 @@ > > +// SPDX-License-Identifier: LGPL-2.1-or-later > > +/* > > + * > > + * BlueZ - Bluetooth protocol stack for Linux > > + * > > + * Copyright (C) 2025 ARRI Lighting. All rights reserved. > > + * > > + * > > + */ > > + > > +#include <stdbool.h> > > +#include <stdlib.h> > > +#include <string.h> // memcpy() > > + > > +#include <ell/dbus.h> > > +#include <ell/queue.h> > > +#include <ell/timeout.h> > > +#include <ell/util.h> // ell_new(), l_free(), l_malloc() > > + > > +#include "mesh/gatt-service.h" > > +#include "mesh/mesh-io.h" // mesh_io_recv_func_t > > +#include "mesh/net.h" // mesh_net_attach_gatt(), > > + // mesh_net_detach_gatt() > > +#include "mesh/net-keys.h" // net_key_fill_adv_service_data(), > > + // net_key_get_next_id() > > +#include "mesh/util.h" // print_packet() > > +#include "mesh/gatt-proxy-svc.h" > > + > > +#define MESH_GATT_PROXY_SVC_UUID "0x1828" > > +#define MESH_GATT_PROXY_CHRC_DATA_IN "0x2ADD" > > +#define MESH_GATT_PROXY_CHRC_DATA_OUT "0x2ADE" > > + > > +#define MAX_PROXY_PDU_LEN 66 /* MshPRT_v1.1, section 7.2.2.2.7 */ > > + > > +struct gatt_io_reg { > > + mesh_io_recv_func_t cb; > > + void *user_data; > > + enum proxy_msg_type msg_type; > > +}; > > + > > +struct gatt_proxy_service { > > + struct gatt_service *gatt_service; > > + uint32_t current_adv_key_id; > > + struct l_timeout *adv_key_cycle_to; > > + bool txing; > > + struct l_queue *tx_deferred; > > + struct l_queue *rx_regs; > > +}; > > + > > +struct process_data { > > + enum proxy_msg_type msg_type; > > + const uint8_t *data; > > + uint8_t len; > > +}; > > + > > +static struct gatt_proxy_service *gatt_proxy_service; > > + > > +struct tx_deferred { > > + enum proxy_msg_type msg_type; > > + uint16_t len; > > + uint8_t data[]; > > +}; > > + > > +static struct gatt_io_reg *find_by_filter(struct l_queue *rx_regs, > > + enum proxy_msg_type > > msg_type) > > +{ > > + const struct l_queue_entry *entry; > > + > > + entry = l_queue_get_entries(rx_regs); > > + > > + for (; entry; entry = entry->next) { > > + struct gatt_io_reg *rx_reg = entry->data; > > + > > + if (rx_reg->msg_type == msg_type) > > + return rx_reg; > > + } > > + > > + return NULL; > > +} > > + > > +void gatt_proxy_service_register_recv_cb(struct gatt_proxy_service > > *gatt_proxy, > > + enum proxy_msg_type msg_type, > > + mesh_io_recv_func_t cb, > > + void *user_data) > > +{ > > + struct gatt_io_reg *rx_reg; > > + > > + if (gatt_proxy != gatt_proxy_service || !cb) > > + return; > > + > > + rx_reg = find_by_filter(gatt_proxy->rx_regs, msg_type); > > + > > + l_free(rx_reg); > > + l_queue_remove(gatt_proxy->rx_regs, rx_reg); > > + > > + rx_reg = l_malloc(sizeof(struct gatt_io_reg)); > > + rx_reg->cb = cb; > > + rx_reg->msg_type = msg_type; > > + rx_reg->user_data = user_data; > > + > > + l_queue_push_head(gatt_proxy->rx_regs, rx_reg); > > +} > > + > > +void > > +gatt_proxy_service_deregister_recv_cb(struct gatt_proxy_service > > *gatt_proxy, > > + enum proxy_msg_type > > msg_type) > > +{ > > + struct gatt_io_reg *rx_reg; > > + > > + if (gatt_proxy != gatt_proxy_service) > > + return; > > + > > + rx_reg = find_by_filter(gatt_proxy->rx_regs, msg_type); > > + > > + l_queue_remove(gatt_proxy->rx_regs, rx_reg); > > + l_free(rx_reg); > > +} > > + > > +void gatt_proxy_service_send(enum proxy_msg_type msg_type, > > + const void *data, uint8_t > > len) > > +{ > > + if (!gatt_proxy_service) > > + return; > > + > > + if (!gatt_proxy_service->txing) { > > + gatt_proxy_service->txing = true; > > + gatt_service_tx(gatt_proxy_service->gatt_service, msg_type, > > + data, len); > > + } else { > > + struct tx_deferred *tx_deferred; > > + > > +// print_packet("TX-Defer", data, len); > > + tx_deferred = l_malloc(len + sizeof(struct tx_deferred)); > > + tx_deferred->msg_type = msg_type; > > + tx_deferred->len = len; > > + memcpy(tx_deferred->data, data, len); > > + l_queue_push_tail(gatt_proxy_service->tx_deferred, > > tx_deferred); > > + } > > +} > > + > > +static void process_rx_callbacks(void *a, void *b) > > +{ > > + struct gatt_io_reg *rx_reg = a; > > + struct process_data *rx = b; > > + > > + if (rx->msg_type == rx_reg->msg_type) > > + rx_reg->cb(rx_reg->user_data, NULL, rx->data, rx->len); > > +} > > + > > +static void gatt_service_rx(void *user_data, enum proxy_msg_type msg_type, > > + const void *data, uint16_t > > len) > > +{ > > + struct gatt_proxy_service *gatt_proxy = user_data; > > + struct process_data rx = { > > + .msg_type = msg_type, > > + .data = data, > > + .len = len, > > + }; > > + > > + if (gatt_proxy != gatt_proxy_service) > > + return; > > + > > + print_packet("RX", data, len); > > + l_queue_foreach(gatt_proxy->rx_regs, process_rx_callbacks, &rx); > > +} > > + > > +static bool gatt_service_tx_cmplt(void *user_data) > > +{ > > + struct gatt_proxy_service *gatt_proxy = user_data; > > + struct tx_deferred *tx_deferred; > > + > > +// l_info("gatt_service_tx_cmplt"); > > + > > + if (gatt_proxy_service != gatt_proxy) > > + return false; > > + > > + if (!gatt_proxy->txing) > > + return false; > > + > > + gatt_proxy->txing = false; > > + > > + tx_deferred = l_queue_pop_head(gatt_proxy->tx_deferred); > > + if (!tx_deferred) > > + return false; > > + > > + gatt_proxy_service_send(tx_deferred->msg_type, > > + tx_deferred->data, > > tx_deferred->len); > > + l_free(tx_deferred); > > + return true; > > +} > > + > > +static bool gatt_service_fill_adv_service_data(void *user_data, > > + struct l_dbus_message_builder > > *builder) > > +{ > > + struct gatt_proxy_service *gatt_service = user_data; > > + > > + if (gatt_service != gatt_proxy_service) > > + return false; > > + > > + return > > net_key_fill_adv_service_data(gatt_service->current_adv_key_id, > > + builder); > > +} > > + > > +static void gatt_proxy_service_cycle_adv(struct l_timeout *timeout, > > + void *user_data) > > +{ > > + struct gatt_proxy_service *gatt_proxy = user_data; > > + uint32_t next_adv_key_id; > > + > > + if (gatt_proxy_service != gatt_proxy) > > + return; > > + > > + next_adv_key_id = > > net_key_get_next_id(gatt_proxy->current_adv_key_id); > > + if (!next_adv_key_id) > > + return; > > + > > + if (gatt_proxy->current_adv_key_id != next_adv_key_id) { > > + gatt_proxy->current_adv_key_id = next_adv_key_id; > > + gatt_service_adv_updated(gatt_proxy_service->gatt_service); > > + } > > + > > + l_timeout_modify(gatt_proxy->adv_key_cycle_to, 3); > > +} > > + > > +void gatt_proxy_service_set_current_adv_key(uint32_t id) > > +{ > > + if (!gatt_proxy_service) > > + return; > > + > > + gatt_proxy_service->current_adv_key_id = id; > > + gatt_service_adv_updated(gatt_proxy_service->gatt_service); > > +} > > + > > +void gatt_proxy_service_start(void) > > +{ > > + if (!gatt_proxy_service || gatt_proxy_service->gatt_service) > > + return; > > + > > + gatt_proxy_service->gatt_service = gatt_service_create( > > + MESH_GATT_PROXY_SVC_UUID, > > + MESH_GATT_PROXY_CHRC_DATA_IN, > > + MESH_GATT_PROXY_CHRC_DATA_OUT, > > + MAX_PROXY_PDU_LEN, > > + NULL, NULL, > > + gatt_service_rx, > > + gatt_service_tx_cmplt, > > + gatt_service_fill_adv_service_data, > > + gatt_proxy_service); > > + > > + gatt_proxy_service->adv_key_cycle_to = l_timeout_create(3, > > + > > gatt_proxy_service_cycle_adv, > > + gatt_proxy_service, NULL); > > + > > + mesh_net_attach_gatt(gatt_proxy_service); > > +} > > + > > +void gatt_proxy_service_stop(void) > > +{ > > + if (!gatt_proxy_service || !gatt_proxy_service->gatt_service) > > + return; > > + > > + mesh_net_detach_gatt(gatt_proxy_service); > > + l_timeout_remove(gatt_proxy_service->adv_key_cycle_to); > > + gatt_service_destroy(gatt_proxy_service->gatt_service, NULL, NULL); > > +} > > + > > +void gatt_proxy_service_create(void) > > +{ > > + if (gatt_proxy_service) > > + return; > > + > > + gatt_proxy_service = l_new(struct gatt_proxy_service, 1); > > + gatt_proxy_service->tx_deferred = l_queue_new(); > > + gatt_proxy_service->rx_regs = l_queue_new(); > > + > > + /* Check whether we have at least one key */ > > + if (!net_key_get_next_id(0)) > > + return; > > + > > + gatt_proxy_service_start(); > > +} > > + > > +void gatt_proxy_service_destroy(void) > > +{ > > + if (!gatt_proxy_service) > > + return; > > + > > + gatt_proxy_service_stop(); > > + > > + l_queue_destroy(gatt_proxy_service->rx_regs, l_free); > > + l_queue_destroy(gatt_proxy_service->tx_deferred, l_free); > > + l_free(gatt_proxy_service); > > + gatt_proxy_service = NULL; > > +} > > diff --git a/mesh/gatt-proxy-svc.h b/mesh/gatt-proxy-svc.h > > new file mode 100644 > > index 000000000000..5c640dc2c8ef > > --- /dev/null > > +++ b/mesh/gatt-proxy-svc.h > > @@ -0,0 +1,29 @@ > > +/* SPDX-License-Identifier: LGPL-2.1-or-later */ > > +/* > > + * > > + * BlueZ - Bluetooth protocol stack for Linux > > + * > > + * Copyright (C) 2025 ARRI Lighting. All rights reserved. > > + * > > + * > > + */ > > + > > +#include <stdint.h> > > + > > +enum proxy_msg_type; > > +struct gatt_proxy_service; > > + > > +void gatt_proxy_service_create(void); > > +void gatt_proxy_service_destroy(void); > > +void gatt_proxy_service_start(void); > > +void gatt_proxy_service_stop(void); > > +void gatt_proxy_service_set_current_adv_key(uint32_t id); > > +void gatt_proxy_service_register_recv_cb(struct gatt_proxy_service > > *gatt_proxy, > > + enum proxy_msg_type msg_type, > > + mesh_io_recv_func_t cb, > > + void *user_data); > > +void > > +gatt_proxy_service_deregister_recv_cb(struct gatt_proxy_service > > *gatt_proxy, > > + enum proxy_msg_type > > msg_type); > > +void gatt_proxy_service_send(enum proxy_msg_type msg_type, > > + const void *data, uint8_t > > len); > > diff --git a/mesh/main.c b/mesh/main.c > > index 5b8af4bc7345..b423fe70b8bd 100644 > > --- a/mesh/main.c > > +++ b/mesh/main.c > > @@ -31,6 +31,7 @@ > > #include "mesh/crypto.h" > > #include "mesh/dbus.h" > > #include "mesh/mesh-io.h" > > +#include "mesh/gatt-proxy-svc.h" > > #include "mesh/util.h" > > > > static const char *storage_dir; > > @@ -94,6 +95,8 @@ static void mesh_ready_callback(void *user_data, bool > > success) > > l_error("Failed to initialize mesh D-Bus resources"); > > l_main_quit(); > > } > > + > > + gatt_proxy_service_create(); > > } > > > > static void request_name_callback(struct l_dbus *dbus, bool success, > > diff --git a/mesh/net-keys.c b/mesh/net-keys.c > > index 42d498ce0ede..62ea4208af98 100644 > > --- a/mesh/net-keys.c > > +++ b/mesh/net-keys.c > > @@ -20,6 +20,7 @@ > > #include "mesh/util.h" > > #include "mesh/crypto.h" > > #include "mesh/mesh-io.h" > > +#include "mesh/gatt-proxy-svc.h" > > #include "mesh/net.h" > > #include "mesh/net-keys.h" > > > > @@ -29,6 +30,12 @@ > > /* This allows daemon to skip decryption on recently seen beacons */ > > #define BEACON_CACHE_MAX 10 > > > > +/* MshPRT_v1.1, section 7.2.2.2.1 */ > > +#define IDENTIFICATION_TYPE_NETWORK_ID 0x00 > > +#define IDENTIFICATION_TYPE_NODE_ID 0x01 > > +#define IDENTIFICATION_TYPE_PRV_NETWORK_ID 0x02 > > +#define IDENTIFICATION_TYPE_PRV_NODE_ID 0x03 > > + > > struct beacon_rx { > > uint8_t data[28]; > > uint32_t id; > > @@ -144,6 +151,9 @@ uint32_t net_key_add(const uint8_t flooding[16]) > > goto fail; > > > > key->id = ++last_flooding_id; > > + if (l_queue_isempty(keys)) > > + gatt_proxy_service_start(); > > + > > l_queue_push_tail(keys, key); > > return key->id; > > > > @@ -196,6 +206,9 @@ void net_key_unref(uint32_t id) > > l_timeout_remove(key->observe.timeout); > > l_queue_remove(keys, key); > > l_free(key); > > + > > + if (l_queue_isempty(keys)) > > + gatt_proxy_service_stop(); > > } > > } > > } > > @@ -663,6 +676,7 @@ bool net_key_beacon_refresh(uint32_t id, uint32_t ivi, > > bool kr, bool ivu, > > return false; > > > > print_packet("Set SNB to", key->snb, 23); > > + gatt_proxy_service_set_current_adv_key(key->id); > > } > > > > l_debug("Set Beacon: IVI: %8.8x, IVU: %d, KR: %d", ivi, ivu, kr); > > @@ -798,3 +812,50 @@ void net_key_cleanup(void) > > l_queue_destroy(beacons, l_free); > > beacons = NULL; > > } > > + > > +bool net_key_fill_adv_service_data(uint32_t id, > > + struct l_dbus_message_builder > > *builder) > > +{ > > + uint8_t identification_type = IDENTIFICATION_TYPE_NETWORK_ID; > > + struct net_key *key; > > + int i; > > + > > + key = l_queue_find(keys, match_id, L_UINT_TO_PTR(id)); > > + if (!key) > > + return false; > > + > > + l_dbus_message_builder_enter_array(builder, "y"); > > + l_dbus_message_builder_append_basic(builder, 'y', > > &identification_type); > > + > > + for (i = 0; i < sizeof(key->net_id); i++) > > + l_dbus_message_builder_append_basic(builder, 'y', > > + &(key->net_id[i])); > > + l_dbus_message_builder_leave_array(builder); > > + > > + return true; > > +} > > + > > +uint32_t net_key_get_next_id(uint32_t id) > > +{ > > + const struct l_queue_entry *entry; > > + struct net_key *key; > > + bool found = false; > > + > > + /* Try to find next key (after the given key id) */ > > + for (entry = l_queue_get_entries(keys); entry; entry = > > entry->next) { > > + key = entry->data; > > + > > + if (!found) > > + if (key->id == id) > > + found = true; > > + else > > + return key->id; > > + } > > + > > + /* If not found, return id of first key */ > > + key = l_queue_peek_head(keys); > > + if (key) > > + return key->id; > > + > > + return 0; > > +} > > diff --git a/mesh/net-keys.h b/mesh/net-keys.h > > index e73812481ddb..5a9d7868ab48 100644 > > --- a/mesh/net-keys.h > > +++ b/mesh/net-keys.h > > @@ -37,3 +37,7 @@ bool net_key_beacon_refresh(uint32_t id, uint32_t > > iv_index, bool kr, bool ivu, > > void net_key_beacon_enable(uint32_t id, bool mpb, uint8_t refresh_count); > > void net_key_beacon_disable(uint32_t id, bool mpb); > > uint32_t net_key_beacon_last_seen(uint32_t id); > > + > > +bool net_key_fill_adv_service_data(uint32_t id, > > + struct l_dbus_message_builder > > *builder); > > +uint32_t net_key_get_next_id(uint32_t id); > > diff --git a/mesh/net.c b/mesh/net.c > > index 1cf74c892ca0..a64cfbde6f4e 100644 > > --- a/mesh/net.c > > +++ b/mesh/net.c > > @@ -27,6 +27,8 @@ > > #include "mesh/net.h" > > #include "mesh/mesh-io.h" > > #include "mesh/friend.h" > > +#include "mesh/gatt-service.h" // PROXY_MSG_TYPE_NETWORK_PDU > > +#include "mesh/gatt-proxy-svc.h" // gatt_proxy_service_send() > > #include "mesh/mesh-config.h" > > #include "mesh/model.h" > > #include "mesh/appkey.h" > > @@ -2306,7 +2308,9 @@ static void send_msg_pkt_oneshot(void *user_data) > > /* No extra randomization when sending regular mesh messages */ > > info.u.gen.max_delay = DEFAULT_MIN_DELAY; > > > > - mesh_io_send(net->io, &info, tx->packet, tx->size); > > +// mesh_io_send(net->io, &info, tx->packet, tx->size); > > + gatt_proxy_service_send(PROXY_MSG_TYPE_NETWORK_PDU, > > + tx->packet + 1, tx->size - > > 1); > > l_free(tx); > > } > > > > @@ -3065,6 +3069,21 @@ struct mesh_io *mesh_net_detach(struct mesh_net > > *net) > > return io; > > } > > > > +void mesh_net_attach_gatt(struct gatt_proxy_service *gatt_proxy) > > +{ > > + gatt_proxy_service_register_recv_cb(gatt_proxy, > > + PROXY_MSG_TYPE_NETWORK_PDU, > > + net_msg_recv, NULL); > > +} > > + > > +void mesh_net_detach_gatt(struct gatt_proxy_service *gatt_proxy) > > +{ > > +// mesh_io_send_cancel(net->io, &type, 1); > > + > > + gatt_proxy_service_deregister_recv_cb(gatt_proxy, > > + > > PROXY_MSG_TYPE_NETWORK_PDU); > > +} > > + > > bool mesh_net_iv_index_update(struct mesh_net *net) > > { > > if (net->iv_upd_state != IV_UPD_NORMAL) > > diff --git a/mesh/net.h b/mesh/net.h > > index d385ba16efdd..1389e5c78d15 100644 > > --- a/mesh/net.h > > +++ b/mesh/net.h > > @@ -14,6 +14,8 @@ > > > > struct mesh_io; > > struct mesh_node; > > +struct mesh_io_recv_info; > > +struct gatt_proxy_service; > > > > #define DEV_ID 0 > > > > @@ -258,6 +260,8 @@ bool mesh_net_get_key(struct mesh_net *net, bool > > new_key, uint16_t idx, > > uint32_t > > *net_key_id); > > bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io); > > struct mesh_io *mesh_net_detach(struct mesh_net *net); > > +void mesh_net_attach_gatt(struct gatt_proxy_service *gatt_proxy); > > +void mesh_net_detach_gatt(struct gatt_proxy_service *gatt_proxy); > > struct l_queue *mesh_net_get_app_keys(struct mesh_net *net); > > > > void mesh_net_transport_send(struct mesh_net *net, uint32_t net_key_id, > > diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c > > index f483c330953b..1d30f3593d3a 100644 > > --- a/mesh/prov-acceptor.c > > +++ b/mesh/prov-acceptor.c > > @@ -21,6 +21,8 @@ > > #include "mesh/mesh-defs.h" > > #include "mesh/util.h" > > #include "mesh/crypto.h" > > +#include "mesh/mesh-io.h" > > +#include "mesh/gatt-proxy-svc.h" > > #include "mesh/net.h" > > #include "mesh/prov.h" > > #include "mesh/provision.h" > > @@ -88,6 +90,11 @@ struct mesh_prov_acceptor { > > > > static struct mesh_prov_acceptor *prov = NULL; > > > > +static void gatt_unreg_finished(void *user_data) > > +{ > > + gatt_proxy_service_create(); > > +} > > + > > static void acceptor_free(void) > > { > > if (!prov) > > @@ -100,7 +107,7 @@ static void acceptor_free(void) > > mesh_send_cancel(&pkt_filter, sizeof(pkt_filter)); > > > > pb_adv_unreg(prov); > > - pb_gatt_unreg(prov, NULL, NULL); > > + pb_gatt_unreg(prov, gatt_unreg_finished, NULL); > > > > l_free(prov); > > prov = NULL; > > @@ -704,8 +711,13 @@ failure: > > cleanup: > > l_timeout_remove(prov->timeout); > > > > - /* Give PB Link 5 seconds to end session */ > > - prov->timeout = l_timeout_create(5, prov_to, prov, NULL); > > + if (prov->transport == PB_ADV) { > > + /* Give PB Link 5 seconds to end session */ > > + prov->timeout = l_timeout_create(5, prov_to, prov, NULL); > > + } else { > > + prov->timeout = NULL; > > + prov_to(NULL, prov); > > + } > > } > > > > static void acp_prov_ack(void *user_data, uint8_t msg_num) > > @@ -804,6 +816,14 @@ bool acceptor_start(uint8_t num_ele, uint8_t *uuid, > > result = pb_adv_reg(false, acp_prov_open, acp_prov_close, > > acp_prov_rx, acp_prov_ack, uuid, > > prov); > > > > + /* > > + * MeshPRT_v1.1, chapter 7: "A device may support the Mesh > > + * Provisioning Service or the Mesh Proxy Service or both. > > If > > + * both are supported, only one of these services shall be > > + * exposed in the GATT database at a time." > > + */ > > + gatt_proxy_service_destroy(); > > + > > result = pb_gatt_reg(acp_prov_open, acp_prov_close, > > acp_prov_rx, acp_prov_ack, uuid, > > caps->oob_info, prov); > > -- > > 2.43.0 > > > > >