All of lore.kernel.org
 help / color / mirror / Atom feed
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
> >
> >
> 





  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.