From: Christian Eggers <ceggers@arri.de>
To: Brian Gix <brian.gix@gmail.com>
Cc: <linux-bluetooth@vger.kernel.org>,
Inga Stotland <inga.stotland@gmail.com>
Subject: Re: [RFC PATCH BlueZ 3/4] mesh: add GATT proxy service
Date: Tue, 1 Jul 2025 21:28:33 +0200 [thread overview]
Message-ID: <22176325.4csPzL39Zc@n9w6sw14> (raw)
In-Reply-To: <CABUQxGwt8MjoYmx_8jF=A9qug24Dnx+rEX=5vDWP7+SGOERcMw@mail.gmail.com>
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@arri.de> 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
> >
> >
>
next prev parent reply other threads:[~2025-07-01 19:28 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-01 14:22 [RFC PATCH BlueZ 0/4] Initial support for GATT Proxy Service Christian Eggers
2025-07-01 14:22 ` [RFC PATCH BlueZ 1/4] mesh: acceptor: increase interval for unprovisioned device beacon Christian Eggers
2025-07-01 16:02 ` Initial support for GATT Proxy Service bluez.test.bot
2025-07-01 14:22 ` [RFC PATCH BlueZ 2/4] mesh: add support for provisioning via GATT Christian Eggers
2025-07-01 14:22 ` [RFC PATCH BlueZ 3/4] mesh: add GATT proxy service Christian Eggers
[not found] ` <CABUQxGwt8MjoYmx_8jF=A9qug24Dnx+rEX=5vDWP7+SGOERcMw@mail.gmail.com>
2025-07-01 19:28 ` Christian Eggers [this message]
2025-07-01 14:22 ` [RFC PATCH BlueZ 4/4] mesh: initial support for proxy configuration messages via GATT Christian Eggers
2025-07-01 15:09 ` [RFC PATCH BlueZ 0/4] Initial support for GATT Proxy Service Christian Eggers
2025-07-01 16:07 ` Luiz Augusto von Dentz
2025-07-01 16:38 ` Christian Eggers
2025-07-01 19:11 ` Luiz Augusto von Dentz
2025-07-01 19:17 ` Brian Gix
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 0/7] " Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 1/7] mesh: acceptor: increase interval for unprovisioned device beacon Christian Eggers
2025-07-11 18:16 ` Initial support for GATT Proxy Service bluez.test.bot
2025-07-15 15:56 ` bluez.test.bot
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 2/7] mesh: add support for provisioning via GATT Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 3/7] mesh: add GATT proxy service Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 4/7] mesh: gatt-proxy: support for proxy configuration messages and filtering Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 5/7] mesh: main.conf/cfgmod-server: allow to enable proxy support Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 6/7] mesh: net: proxy relaying Christian Eggers
2025-07-11 17:56 ` [RFC PATCH BlueZ v2 7/7] mesh: gatt-proxy: propagate beacons Christian Eggers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=22176325.4csPzL39Zc@n9w6sw14 \
--to=ceggers@arri.de \
--cc=brian.gix@gmail.com \
--cc=inga.stotland@gmail.com \
--cc=linux-bluetooth@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox