Re: [PATCH BlueZ] shared/bap: wait for GATT client ready before ASCS/PACS discovery

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Luiz,

su, 2023-02-12 kello 12:45 -0800, Luiz Augusto von Dentz kirjoitti:
> Hi Pauli,
> 
> On Sun, Feb 12, 2023 at 10:41 AM Pauli Virtanen <pav@xxxxxx> wrote:
> > 
> > BAP client fails to find endpoints if GATT services are not resolved
> > when the GATT client is attached to the session.  This condition
> > almost always occurs on the first BAP connection to a device between
> > bluetoothd restarts, and may occur also otherwise.
> 
> Hmm, this shouldn't happen if you have caching enabled, did you
> disable it for some reason?

Caching has not been disabled. The files in /var/lib/bluetooth/*/cache
also get updated so presumably it is working.

> > The BAP client code discovers ASCS/PACS services and characteristics at
> > client attach time.
> > 
> > Fix the connection issue by postponing PAC/ASE discovery until the
> > GATT client is ready, if it was not ready at attach time.
> 
> This should probably be done by the core, it should check if the
> services are cached then it can call accept, otherwise it needs to
> wait for the client to be ready, perhaps there is something not quite
> right with the way to probe services as afaik if we don't have any
> cache the driver shouldn't have been called to begin with.

bap_accept gets called from

#0  bap_accept (service=0x604000005f50) at profiles/audio/bap.c:1304
#1  0x0000000000631755 in service_accept (service=0x604000005f50, initiator=true) at src/service.c:203
#2  0x0000000000668561 in device_accept_gatt_profiles (device=0x617000000080) at src/device.c:3739
#3  0x0000000000676128 in gatt_client_init (device=0x617000000080) at src/device.c:5161
#4  0x00000000006782e5 in device_attach_att (dev=0x617000000080, io=0x60c00000b2c0) at src/device.c:5331
#5  0x00000000006788e5 in att_connect_cb (io=0x60c00000b2c0, gerr=0x0, user_data=0x617000000080) at src/device.c:5378
#6  0x000000000053de23 in connect_cb (io=0x60c00000b2c0, cond=G_IO_OUT, user_data=0x60300001f8d0) at btio/btio.c:229
#7  0x00007f4955d16cbf in g_main_context_dispatch () from target:/lib64/libglib-2.0.so.0
#8  0x00007f4955d6c598 in g_main_context_iterate.constprop () from target:/lib64/libglib-2.0.so.0
#9  0x00007f4955d1628f in g_main_loop_run () from target:/lib64/libglib-2.0.so.0
#10 0x00000000007df9ca in mainloop_run () at src/shared/mainloop-glib.c:66
#11 0x00000000007e075a in mainloop_run_with_signal (func=0x558597 <signal_callback>, user_data=0x0) at src/shared/mainloop-notify.c:188
#12 0x0000000000558e97 in main (argc=1, argv=0x7ffd399f7788) at src/main.c:1304

which does not wait for GATT client ready. The comment above that

5157│         /*
5158│          * Notify notify existing service about the new connection so they can
5159│          * react to notifications while discovering services
5160│          */

looks like this is intentional. If it's like this, then services would
need to explicitly wait.

Didn't look yet how come it knows the gatt service is there then,
however I guess it only looks for the PACS service uuid, as I think
nothing tells device.c also ASCS would be needed.

Best,
Pauli

> 
> > ---
> > 
> > Notes:
> >     Typical bluetoothctl output in the failing case, without this patch:
> > 
> >     $ sudo systemctl restart bluetooth
> >     $ bluetoothctl
> >     ...
> >     [bluetooth]# connect XX:XX:XX:XX:XX:XX
> >     Attempting to connect to XX:XX:XX:XX:XX:XX
> >     [CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 0000184e-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001850-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 03b80e5a-ede8-4b33-a751-6ce34ec4c700
> >     Connection successful
> >     [NEW] Primary Service (Handle 0x0000)
> >             /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0008
> >             00001801-0000-1000-8000-00805f9b34fb
> >             Generic Attribute Profile
> >     ...
> >     [NEW] Descriptor (Handle 0x0000)
> >             /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0065/char0066/desc0069
> >             00002901-0000-1000-8000-00805f9b34fb
> >             Characteristic User Description
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001800-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001801-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 0000180a-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001844-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 0000184e-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001850-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 03b80e5a-ede8-4b33-a751-6ce34ec4c700
> >     [CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: yes
> >     [CHG] Device XX:XX:XX:XX:XX:XX Paired: yes
> >     [xxx]# endpoint.list
> >     [xxx]# disconnect
> >     Attempting to disconnect from XX:XX:XX:XX:XX:XX
> >     [CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: no
> >     Successful disconnected
> >     [CHG] Device XX:XX:XX:XX:XX:XX Connected: no
> >     [bluetooth]# connect XX:XX:XX:XX:XX:XX
> >     Attempting to connect to XX:XX:XX:XX:XX:XX
> >     [CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
> >     Connection successful
> >     [NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0
> >     [NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0
> >     [NEW] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0
> >     [NEW] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1
> >     [CHG] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0 Links: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1
> >     [CHG] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1 Links: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0
> >     [CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: yes
> >     [xxx]# endpoint.list
> >     Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0
> >     Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0
> >     [xxx]#
> > 
> >     Endpoints and transports failed to appear on the first connect to the
> >     BAP server, since GATT discovery was not yet completed when the BAP code
> >     tried to discover the endpoints. Second connection succeeded.
> >     Occasionally, it also happens that endpoints appear but transports do
> >     not, but this is hard to reproduce.
> > 
> >     With this patch:
> > 
> >     $ sudo systemctl restart bluetooth
> >     $ bluetoothctl
> >     ...
> >     [bluetooth]# connect XX:XX:XX:XX:XX:XX
> >     Attempting to connect to XX:XX:XX:XX:XX:XX
> >     [CHG] Device XX:XX:XX:XX:XX:XX Connected: yes
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 0000184e-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 00001850-0000-1000-8000-00805f9b34fb
> >     [CHG] Device XX:XX:XX:XX:XX:XX UUIDs: 03b80e5a-ede8-4b33-a751-6ce34ec4c700
> >     Connection successful
> >     [NEW] Primary Service (Handle 0x0000)
> >             /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0008
> >             00001801-0000-1000-8000-00805f9b34fb
> >             Generic Attribute Profile
> >     ...
> >     [NEW] Descriptor (Handle 0x0000)
> >             /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/service0065/char0066/desc0069
> >             00002901-0000-1000-8000-00805f9b34fb
> >             Characteristic User Description
> >     [CHG] Device XX:XX:XX:XX:XX:XX ServicesResolved: yes
> >     [CHG] Device XX:XX:XX:XX:XX:XX Paired: yes
> >     [NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0
> >     [NEW] Endpoint /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0
> >     [NEW] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0
> >     [NEW] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1
> >     [CHG] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0 Links: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1
> >     [CHG] Transport /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_sink0/fd1 Links: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX/pac_source0/fd0
> >     [xxx]#
> > 
> >     Now the first connection works properly.
> > 
> >     On first reading, the spec does not seem to clearly comment if ASEs and
> >     PACs could be removed/added by the server while client is connected. If
> >     that's allowed, then we'd need some bigger changes here. Regardless,
> >     waiting for GATT client ready before first scan seems good also in this
> >     case.
> > 
> >  src/shared/bap.c | 93 +++++++++++++++++++++++++++++++-----------------
> >  1 file changed, 60 insertions(+), 33 deletions(-)
> > 
> > diff --git a/src/shared/bap.c b/src/shared/bap.c
> > index 22f2e6714..2d676d96f 100644
> > --- a/src/shared/bap.c
> > +++ b/src/shared/bap.c
> > @@ -158,6 +158,7 @@ struct bt_bap {
> >         struct bt_att *att;
> >         struct bt_bap_req *req;
> >         unsigned int cp_id;
> > +       unsigned int client_ready_id;
> > 
> >         unsigned int process_id;
> >         unsigned int disconn_id;
> > @@ -3733,41 +3734,10 @@ static void bap_attach_att(struct bt_bap *bap, struct bt_att *att)
> >                                                         bap, NULL);
> >  }
> > 
> > -bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
> > +static void bap_attach_finish(struct bt_bap *bap)
> >  {
> >         bt_uuid_t uuid;
> > 
> > -       if (queue_find(sessions, NULL, bap)) {
> > -               /* If instance already been set but there is no client proceed
> > -                * to clone it otherwise considered it already attached.
> > -                */
> > -               if (client && !bap->client)
> > -                       goto clone;
> > -               return true;
> > -       }
> > -
> > -       if (!sessions)
> > -               sessions = queue_new();
> > -
> > -       queue_push_tail(sessions, bap);
> > -
> > -       queue_foreach(bap_cbs, bap_attached, bap);
> > -
> > -       if (!client) {
> > -               bap_attach_att(bap, bap->att);
> > -               return true;
> > -       }
> > -
> > -       if (bap->client)
> > -               return false;
> > -
> > -clone:
> > -       bap->client = bt_gatt_client_clone(client);
> > -       if (!bap->client)
> > -               return false;
> > -
> > -       bap_attach_att(bap, bt_gatt_client_get_att(client));
> > -
> >         if (bap->rdb->pacs) {
> >                 uint16_t value_handle;
> >                 struct bt_pacs *pacs = bap->rdb->pacs;
> > @@ -3798,7 +3768,7 @@ clone:
> > 
> >                 bap_notify_ready(bap);
> > 
> > -               return true;
> > +               return;
> >         }
> > 
> >         bt_uuid16_create(&uuid, PACS_UUID);
> > @@ -3806,6 +3776,57 @@ clone:
> > 
> >         bt_uuid16_create(&uuid, ASCS_UUID);
> >         gatt_db_foreach_service(bap->rdb->db, &uuid, foreach_ascs_service, bap);
> > +}
> > +
> > +static void bap_attach_ready_cb(bool success, uint8_t att_ecode,
> > +                                                               void *user_data)
> > +{
> > +       struct bt_bap *bap = user_data;
> > +
> > +       bap->client_ready_id = 0;
> > +
> > +       bap_attach_finish(bap);
> > +}
> > +
> > +bool bt_bap_attach(struct bt_bap *bap, struct bt_gatt_client *client)
> > +{
> > +       if (queue_find(sessions, NULL, bap)) {
> > +               /* If instance already been set but there is no client proceed
> > +                * to clone it otherwise considered it already attached.
> > +                */
> > +               if (client && !bap->client)
> > +                       goto clone;
> > +               return true;
> > +       }
> > +
> > +       if (!sessions)
> > +               sessions = queue_new();
> > +
> > +       queue_push_tail(sessions, bap);
> > +
> > +       queue_foreach(bap_cbs, bap_attached, bap);
> > +
> > +       if (!client) {
> > +               bap_attach_att(bap, bap->att);
> > +               return true;
> > +       }
> > +
> > +       if (bap->client)
> > +               return false;
> > +
> > +clone:
> > +       bap->client = bt_gatt_client_clone(client);
> > +       if (!bap->client)
> > +               return false;
> > +
> > +       bap_attach_att(bap, bt_gatt_client_get_att(bap->client));
> > +
> > +       if (bt_gatt_client_is_ready(bap->client)) {
> > +               bap_attach_finish(bap);
> > +       } else {
> > +               bap->client_ready_id = bt_gatt_client_ready_register(
> > +                               bap->client, bap_attach_ready_cb, bap, NULL);
> > +       }
> > 
> >         return true;
> >  }
> > @@ -3824,6 +3845,12 @@ void bt_bap_detach(struct bt_bap *bap)
> >         if (!queue_remove(sessions, bap))
> >                 return;
> > 
> > +       if (bap->client_ready_id) {
> > +               bt_gatt_client_ready_unregister(bap->client,
> > +                                               bap->client_ready_id);
> > +               bap->client_ready_id = 0;
> > +       }
> > +
> >         bt_gatt_client_unref(bap->client);
> >         bap->client = NULL;
> > 
> > --
> > 2.39.1
> > 
> 
> 





[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux