Re: [PATCH v3 1/1] Bluetooth: ISO: Use defer setup to separate PA sync and BIG sync

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

 



Hi Luiz, Pauli

> -----Original Message-----
> From: Luiz Augusto von Dentz <luiz.dentz@xxxxxxxxx>
> Sent: Friday, August 18, 2023 12:39 AM
> To: Pauli Virtanen <pav@xxxxxx>
> Cc: Iulia Tanasescu <iulia.tanasescu@xxxxxxx>; linux-
> bluetooth@xxxxxxxxxxxxxxx
> Subject: Re: [PATCH v3 1/1] Bluetooth: ISO: Use defer setup to
> separate PA sync and BIG sync
> 
> Hi Pauli,
> 
> On Thu, Aug 17, 2023 at 1:26 PM Pauli Virtanen <pav@xxxxxx> wrote:
> >
> > Hi,
> >
> > to, 2023-08-17 kello 09:44 +0300, Iulia Tanasescu kirjoitti:
> > > This commit implements defer setup support for the Broadcast Sink
> > > scenario: By setting defer setup on a broadcast socket before
> > > calling listen, the user is able to trigger the PA sync and BIG sync
> > > procedures separately.
> > >
> > > This is useful if the user first wants to synchronize to the
> > > periodic advertising transmitted by a Broadcast Source, and trigger
> > > the BIG sync procedure later on.
> > >
> > > If defer setup is set, once a PA sync established event arrives, a
> > > new hcon is created and notified to the ISO layer. A child socket
> > > associated with the PA sync connection will be added to the accept
> > > queue of the listening socket.
> > >
> > > Once the accept call returns the fd for the PA sync child socket,
> > > the user should call read on that fd. This will trigger the BIG
> > > create sync procedure, and the PA sync socket will become a listening
> socket itself.
> > >
> > > When the BIG sync established event is notified to the ISO layer,
> > > the bis connections will be added to the accept queue of the PA sync
> parent.
> > > The user should call accept on the PA sync socket to get the final
> > > bis connections.
> > >
> > > Signed-off-by: Iulia Tanasescu <iulia.tanasescu@xxxxxxx>
> > > ---
> > >  include/net/bluetooth/hci_core.h |  30 +++++-
> > >  net/bluetooth/hci_conn.c         |  13 ++-
> > >  net/bluetooth/hci_event.c        |  41 +++++++-
> > >  net/bluetooth/hci_sync.c         |  15 +++
> > >  net/bluetooth/iso.c              | 160 ++++++++++++++++++++++++-------
> > >  5 files changed, 218 insertions(+), 41 deletions(-)
> > >
> > > diff --git a/include/net/bluetooth/hci_core.h
> > > b/include/net/bluetooth/hci_core.h
> > > index c53d74236e3a..6fb055e3c595 100644
> > > --- a/include/net/bluetooth/hci_core.h
> > > +++ b/include/net/bluetooth/hci_core.h
> > > @@ -978,6 +978,8 @@ enum {
> > >       HCI_CONN_CREATE_CIS,
> > >       HCI_CONN_BIG_SYNC,
> > >       HCI_CONN_BIG_SYNC_FAILED,
> > > +     HCI_CONN_PA_SYNC,
> > > +     HCI_CONN_PA_SYNC_FAILED,
> > >  };
> > >
> > >  static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) @@
> > > -1300,7 +1302,7 @@ static inline struct hci_conn
> *hci_conn_hash_lookup_big_any_dst(struct hci_dev *
> > >               if (c->type != ISO_LINK)
> > >                       continue;
> > >
> > > -             if (handle == c->iso_qos.bcast.big) {
> > > +             if (handle != BT_ISO_QOS_BIG_UNSET && handle ==
> > > + c->iso_qos.bcast.big) {
> > >                       rcu_read_unlock();
> > >                       return c;
> > >               }
> > > @@ -1311,6 +1313,29 @@ static inline struct hci_conn
> *hci_conn_hash_lookup_big_any_dst(struct hci_dev *
> > >       return NULL;
> > >  }
> > >
> > > +static inline struct hci_conn *
> > > +hci_conn_hash_lookup_pa_sync(struct hci_dev *hdev, __u8 big) {
> > > +     struct hci_conn_hash *h = &hdev->conn_hash;
> > > +     struct hci_conn  *c;
> > > +
> > > +     rcu_read_lock();
> > > +
> > > +     list_for_each_entry_rcu(c, &h->list, list) {
> > > +             if (c->type != ISO_LINK ||
> > > +                     !test_bit(HCI_CONN_PA_SYNC, &c->flags))
> > > +                     continue;
> > > +
> > > +             if (c->iso_qos.bcast.big == big) {
> > > +                     rcu_read_unlock();
> > > +                     return c;
> > > +             }
> > > +     }
> > > +     rcu_read_unlock();
> > > +
> > > +     return NULL;
> > > +}
> > > +
> > >  static inline struct hci_conn *hci_conn_hash_lookup_state(struct
> hci_dev *hdev,
> > >                                                       __u8 type,
> > > __u16 state)  { @@ -1435,7 +1460,8 @@ struct hci_conn
> > > *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst,
> > >                                __u8 data_len, __u8 *data);  int
> > > hci_pa_create_sync(struct hci_dev *hdev, bdaddr_t *dst, __u8 dst_type,
> > >                      __u8 sid, struct bt_iso_qos *qos); -int
> > > hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos *qos,
> > > +int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
> > > +                        struct bt_iso_qos *qos,
> > >                          __u16 sync_handle, __u8 num_bis, __u8
> > > bis[]);  int hci_conn_check_link_mode(struct hci_conn *conn);  int
> > > hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); diff
> > > --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index
> > > 95339623883c..8b0c8e631324 100644
> > > --- a/net/bluetooth/hci_conn.c
> > > +++ b/net/bluetooth/hci_conn.c
> > > @@ -734,6 +734,7 @@ struct iso_list_data {
> > >       };
> > >       int count;
> > >       bool big_term;
> > > +     bool pa_sync_term;
> > >       bool big_sync_term;
> > >  };
> > >
> > > @@ -807,7 +808,10 @@ static int big_terminate_sync(struct hci_dev
> *hdev, void *data)
> > >       if (d->big_sync_term)
> > >               hci_le_big_terminate_sync(hdev, d->big);
> > >
> > > -     return hci_le_pa_terminate_sync(hdev, d->sync_handle);
> > > +     if (d->pa_sync_term)
> > > +             return hci_le_pa_terminate_sync(hdev, d->sync_handle);
> > > +
> > > +     return 0;
> > >  }
> > >
> > >  static int hci_le_big_terminate(struct hci_dev *hdev, u8 big,
> > > struct hci_conn *conn) @@ -823,6 +827,7 @@ static int
> > > hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn
> > > *c
> > >
> > >       d->big = big;
> > >       d->sync_handle = conn->sync_handle;
> > > +     d->pa_sync_term = test_and_clear_bit(HCI_CONN_PA_SYNC,
> > > + &conn->flags);
> > >       d->big_sync_term = test_and_clear_bit(HCI_CONN_BIG_SYNC,
> > > &conn->flags);
> > >
> > >       ret = hci_cmd_sync_queue(hdev, big_terminate_sync, d, @@
> > > -2099,7 +2104,8 @@ int hci_pa_create_sync(struct hci_dev *hdev,
> bdaddr_t *dst, __u8 dst_type,
> > >       return hci_cmd_sync_queue(hdev, create_pa_sync, cp,
> > > create_pa_complete);  }
> > >
> > > -int hci_le_big_create_sync(struct hci_dev *hdev, struct bt_iso_qos
> > > *qos,
> > > +int hci_le_big_create_sync(struct hci_dev *hdev, struct hci_conn *hcon,
> > > +                        struct bt_iso_qos *qos,
> > >                          __u16 sync_handle, __u8 num_bis, __u8
> > > bis[])  {
> > >       struct _packed {
> > > @@ -2115,6 +2121,9 @@ int hci_le_big_create_sync(struct hci_dev
> *hdev, struct bt_iso_qos *qos,
> > >       if (err)
> > >               return err;
> > >
> > > +     if (hcon)
> > > +             hcon->iso_qos.bcast.big = qos->bcast.big;
> > > +
> > >       memset(&pdu, 0, sizeof(pdu));
> > >       pdu.cp.handle = qos->bcast.big;
> > >       pdu.cp.sync_handle = cpu_to_le16(sync_handle); diff --git
> > > a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index
> > > 559b6080706c..b4b72070f5f6 100644
> > > --- a/net/bluetooth/hci_event.c
> > > +++ b/net/bluetooth/hci_event.c
> > > @@ -6581,20 +6581,39 @@ static void
> hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data,
> > >       struct hci_ev_le_pa_sync_established *ev = data;
> > >       int mask = hdev->link_mode;
> > >       __u8 flags = 0;
> > > +     struct hci_conn *bis;
> > >
> > >       bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
> > >
> > > -     if (ev->status)
> > > -             return;
> > > -
> > >       hci_dev_lock(hdev);
> > >
> > >       hci_dev_clear_flag(hdev, HCI_PA_SYNC);
> > >
> > >       mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ISO_LINK,
> &flags);
> > > -     if (!(mask & HCI_LM_ACCEPT))
> > > +     if (!(mask & HCI_LM_ACCEPT)) {
> > >               hci_le_pa_term_sync(hdev, ev->handle);
> > > +             goto unlock;
> > > +     }
> > > +
> > > +     if (!(flags & HCI_PROTO_DEFER))
> > > +             goto unlock;
> > > +
> > > +     /* Add connection to indicate the PA sync event */
> > > +     bis = hci_conn_add(hdev, ISO_LINK, BDADDR_ANY,
> > > +                        HCI_ROLE_SLAVE);
> > >
> > > +     if (!bis)
> > > +             goto unlock;
> > > +
> > > +     if (ev->status)
> > > +             set_bit(HCI_CONN_PA_SYNC_FAILED, &bis->flags);
> > > +     else
> > > +             set_bit(HCI_CONN_PA_SYNC, &bis->flags);
> > > +
> > > +     /* Notify connection to iso layer */
> > > +     hci_connect_cfm(bis, ev->status);
> > > +
> > > +unlock:
> > >       hci_dev_unlock(hdev);
> > >  }
> > >
> > > @@ -7045,6 +7064,7 @@ static void
> > > hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,  {
> > >       struct hci_evt_le_big_sync_estabilished *ev = data;
> > >       struct hci_conn *bis;
> > > +     struct hci_conn *pa_sync;
> > >       int i;
> > >
> > >       bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); @@ -7055,6
> > > +7075,15 @@ static void hci_le_big_sync_established_evt(struct
> > > hci_dev *hdev, void *data,
> > >
> > >       hci_dev_lock(hdev);
> > >
> > > +     if (!ev->status) {
> > > +             pa_sync = hci_conn_hash_lookup_pa_sync(hdev, ev->handle);
> > > +             if (pa_sync)
> > > +                     /* Also mark the BIG sync established event on the
> > > +                      * associated PA sync hcon
> > > +                      */
> > > +                     set_bit(HCI_CONN_BIG_SYNC, &pa_sync->flags);
> > > +     }
> > > +
> > >       for (i = 0; i < ev->num_bis; i++) {
> > >               u16 handle = le16_to_cpu(ev->bis[i]);
> > >               __le32 interval;
> > > @@ -7068,6 +7097,10 @@ static void
> hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data,
> > >                       bis->handle = handle;
> > >               }
> > >
> > > +             if (ev->status != 0x42)
> > > +                     /* Mark PA sync as established */
> > > +                     set_bit(HCI_CONN_PA_SYNC, &bis->flags);
> > > +
> > >               bis->iso_qos.bcast.big = ev->handle;
> > >               memset(&interval, 0, sizeof(interval));
> > >               memcpy(&interval, ev->latency, sizeof(ev->latency));
> > > diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
> > > index d10a0f36b947..0cb780817198 100644
> > > --- a/net/bluetooth/hci_sync.c
> > > +++ b/net/bluetooth/hci_sync.c
> > > @@ -5384,6 +5384,21 @@ int hci_abort_conn_sync(struct hci_dev *hdev,
> struct hci_conn *conn, u8 reason)
> > >               err = hci_reject_conn_sync(hdev, conn, reason);
> > >               break;
> > >       case BT_OPEN:
> > > +             hci_dev_lock(hdev);
> > > +
> > > +             /* Cleanup bis or pa sync connections */
> > > +             if (test_and_clear_bit(HCI_CONN_BIG_SYNC_FAILED, &conn-
> >flags) ||
> > > +                 test_and_clear_bit(HCI_CONN_PA_SYNC_FAILED, &conn-
> >flags)) {
> > > +                     hci_conn_failed(conn, reason);
> > > +             } else if (test_bit(HCI_CONN_PA_SYNC, &conn->flags) ||
> > > +                        test_bit(HCI_CONN_BIG_SYNC, &conn->flags)) {
> > > +                     conn->state = BT_CLOSED;
> > > +                     hci_disconn_cfm(conn, reason);
> > > +                     hci_conn_del(conn);
> > > +             }
> > > +
> > > +             hci_dev_unlock(hdev);
> > > +             return 0;
> >
> > Note the hci_disconnect_all_sync changes in 45c37c4e9c9aab5b now
> > require the conn is deleted in all cases, the above probably results
> > to busy loop if non-ISO broadcast conn is in BT_OPEN when controller
> > is supended.
> 
> Yep, I wonder if we could just keep doing hci_conn_failed, it seems the only
> difference seem that hci_disconn_cfm must be called in certain cases where
> PA or BIG is being setup over hci_connnect_cfm which is already handled by
> hci_conn_failed.
> 

I agree, we could just keep hci_conn_failed, since both hci_disconn_cfm
and hci_connect_cfm with error status will have the same effect on ISO
layer. I decided to use hci_disconn_cfm for the successful connections
just because I thought it might be confusing to use hci_conn_failed for
those cases. I can submit a new patch to only use hci_conn_failed like
before, if you agree.

> >
> > >       case BT_BOUND:
> > >               hci_dev_lock(hdev);
> > >               hci_conn_failed(conn, reason); diff --git
> > > a/net/bluetooth/iso.c b/net/bluetooth/iso.c index
> > > 6b66d6a88b9a..9879f2349d48 100644
> > > --- a/net/bluetooth/iso.c
> > > +++ b/net/bluetooth/iso.c
> > > @@ -51,6 +51,7 @@ static void iso_sock_kill(struct sock *sk);
> > >  /* iso_pinfo flags values */
> > >  enum {
> > >       BT_SK_BIG_SYNC,
> > > +     BT_SK_PA_SYNC,
> > >  };
> > >
> > >  struct iso_pinfo {
> > > @@ -75,6 +76,8 @@ static struct bt_iso_qos default_qos;
> > >
> > >  static bool check_ucast_qos(struct bt_iso_qos *qos);  static bool
> > > check_bcast_qos(struct bt_iso_qos *qos);
> > > +static bool iso_match_sid(struct sock *sk, void *data); static void
> > > +iso_sock_disconn(struct sock *sk);
> > >
> > >  /* ---- ISO timers ---- */
> > >  #define ISO_CONN_TIMEOUT     (HZ * 40)
> > > @@ -598,6 +601,15 @@ static void iso_sock_cleanup_listen(struct sock
> *parent)
> > >               iso_sock_kill(sk);
> > >       }
> > >
> > > +     /* If listening socket stands for a PA sync connection,
> > > +      * properly disconnect the hcon and socket.
> > > +      */
> > > +     if (iso_pi(parent)->conn && iso_pi(parent)->conn->hcon &&
> > > +         test_bit(HCI_CONN_PA_SYNC, &iso_pi(parent)->conn->hcon-
> >flags)) {
> > > +             iso_sock_disconn(parent);
> > > +             return;
> > > +     }
> > > +
> > >       parent->sk_state  = BT_CLOSED;
> > >       sock_set_flag(parent, SOCK_ZAPPED);  } @@ -619,6 +631,16 @@
> > > static void iso_sock_kill(struct sock *sk)
> > >       sock_put(sk);
> > >  }
> > >
> > > +static void iso_sock_disconn(struct sock *sk) {
> > > +     sk->sk_state = BT_DISCONN;
> > > +     iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
> > > +     iso_conn_lock(iso_pi(sk)->conn);
> > > +     hci_conn_drop(iso_pi(sk)->conn->hcon);
> > > +     iso_pi(sk)->conn->hcon = NULL;
> > > +     iso_conn_unlock(iso_pi(sk)->conn);
> > > +}
> > > +
> > >  static void __iso_sock_close(struct sock *sk)  {
> > >       BT_DBG("sk %p state %d socket %p", sk, sk->sk_state,
> > > sk->sk_socket); @@ -631,20 +653,19 @@ static void
> __iso_sock_close(struct sock *sk)
> > >       case BT_CONNECT:
> > >       case BT_CONNECTED:
> > >       case BT_CONFIG:
> > > -             if (iso_pi(sk)->conn->hcon) {
> > > -                     sk->sk_state = BT_DISCONN;
> > > -                     iso_sock_set_timer(sk, ISO_DISCONN_TIMEOUT);
> > > -                     iso_conn_lock(iso_pi(sk)->conn);
> > > -                     hci_conn_drop(iso_pi(sk)->conn->hcon);
> > > -                     iso_pi(sk)->conn->hcon = NULL;
> > > -                     iso_conn_unlock(iso_pi(sk)->conn);
> > > -             } else {
> > > +             if (iso_pi(sk)->conn->hcon)
> > > +                     iso_sock_disconn(sk);
> > > +             else
> > >                       iso_chan_del(sk, ECONNRESET);
> > > -             }
> > >               break;
> > >
> > >       case BT_CONNECT2:
> > > -             iso_chan_del(sk, ECONNRESET);
> > > +             if (iso_pi(sk)->conn->hcon &&
> > > +                 (test_bit(HCI_CONN_PA_SYNC, &iso_pi(sk)->conn->hcon-
> >flags) ||
> > > +                 test_bit(HCI_CONN_PA_SYNC_FAILED, &iso_pi(sk)->conn-
> >hcon->flags)))
> > > +                     iso_sock_disconn(sk);
> > > +             else
> > > +                     iso_chan_del(sk, ECONNRESET);
> > >               break;
> > >       case BT_DISCONN:
> > >               iso_chan_del(sk, ECONNRESET); @@ -1139,6 +1160,29 @@
> > > static void iso_conn_defer_accept(struct hci_conn *conn)
> > >       hci_send_cmd(hdev, HCI_OP_LE_ACCEPT_CIS, sizeof(cp), &cp);  }
> > >
> > > +static void iso_conn_big_sync(struct sock *sk) {
> > > +     int err;
> > > +     struct hci_dev *hdev;
> > > +
> > > +     hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
> > > +                          iso_pi(sk)->src_type);
> > > +
> > > +     if (!hdev)
> > > +             return;
> > > +
> > > +     if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
> > > +             err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
> > > +                                          &iso_pi(sk)->qos,
> > > +                                          iso_pi(sk)->sync_handle,
> > > +                                          iso_pi(sk)->bc_num_bis,
> > > +                                          iso_pi(sk)->bc_bis);
> > > +             if (err)
> > > +                     bt_dev_err(hdev, "hci_le_big_create_sync: %d",
> > > +                                err);
> > > +     }
> > > +}
> > > +
> > >  static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
> > >                           size_t len, int flags)  { @@ -1151,8
> > > +1195,15 @@ static int iso_sock_recvmsg(struct socket *sock, struct
> msghdr *msg,
> > >               lock_sock(sk);
> > >               switch (sk->sk_state) {
> > >               case BT_CONNECT2:
> > > -                     iso_conn_defer_accept(pi->conn->hcon);
> > > -                     sk->sk_state = BT_CONFIG;
> > > +                     if (pi->conn->hcon &&
> > > +                         test_bit(HCI_CONN_PA_SYNC, &pi->conn->hcon->flags)) {
> > > +                             iso_conn_big_sync(sk);
> > > +                             sk->sk_state = BT_LISTEN;
> > > +                             set_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags);
> > > +                     } else {
> > > +                             iso_conn_defer_accept(pi->conn->hcon);
> > > +                             sk->sk_state = BT_CONFIG;
> > > +                     }
> > >                       release_sock(sk);
> > >                       return 0;
> > >               case BT_CONNECT:
> > > @@ -1513,11 +1564,17 @@ static bool iso_match_big(struct sock *sk,
> void *data)
> > >       return ev->handle == iso_pi(sk)->qos.bcast.big;  }
> > >
> > > +static bool iso_match_pa_sync_flag(struct sock *sk, void *data) {
> > > +     return test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags); }
> > > +
> > >  static void iso_conn_ready(struct iso_conn *conn)  {
> > > -     struct sock *parent;
> > > +     struct sock *parent = NULL;
> > >       struct sock *sk = conn->sk;
> > > -     struct hci_ev_le_big_sync_estabilished *ev;
> > > +     struct hci_ev_le_big_sync_estabilished *ev = NULL;
> > > +     struct hci_ev_le_pa_sync_established *ev2 = NULL;
> > >       struct hci_conn *hcon;
> > >
> > >       BT_DBG("conn %p", conn);
> > > @@ -1529,15 +1586,32 @@ static void iso_conn_ready(struct iso_conn
> *conn)
> > >               if (!hcon)
> > >                       return;
> > >
> > > -             ev = hci_recv_event_data(hcon->hdev,
> > > -                                      HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
> > > -             if (ev)
> > > +             if (test_bit(HCI_CONN_BIG_SYNC, &hcon->flags) ||
> > > +                 test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
> > > +                     ev = hci_recv_event_data(hcon->hdev,
> > > +
> > > + HCI_EVT_LE_BIG_SYNC_ESTABILISHED);
> > > +
> > > +                     /* Get reference to PA sync parent socket, if
> > > + it exists */
> > >                       parent = iso_get_sock_listen(&hcon->src,
> > >                                                    &hcon->dst,
> > > -                                                  iso_match_big, ev);
> > > -             else
> > > +                                                  iso_match_pa_sync_flag, NULL);
> > > +                     if (!parent && ev)
> > > +                             parent = iso_get_sock_listen(&hcon->src,
> > > +                                                          &hcon->dst,
> > > +                                                          iso_match_big, ev);
> > > +             } else if (test_bit(HCI_CONN_PA_SYNC, &hcon->flags) ||
> > > +                             test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
> > > +                     ev2 = hci_recv_event_data(hcon->hdev,
> > > +                                               HCI_EV_LE_PA_SYNC_ESTABLISHED);
> > > +                     if (ev2)
> > > +                             parent = iso_get_sock_listen(&hcon->src,
> > > +                                                          &hcon->dst,
> > > +                                                          iso_match_sid, ev2);
> > > +             }
> > > +
> > > +             if (!parent)
> > >                       parent = iso_get_sock_listen(&hcon->src,
> > > -                                                  BDADDR_ANY, NULL, NULL);
> > > +                                                     BDADDR_ANY,
> > > + NULL, NULL);
> > >
> > >               if (!parent)
> > >                       return;
> > > @@ -1554,11 +1628,17 @@ static void iso_conn_ready(struct iso_conn
> *conn)
> > >               iso_sock_init(sk, parent);
> > >
> > >               bacpy(&iso_pi(sk)->src, &hcon->src);
> > > -             iso_pi(sk)->src_type = hcon->src_type;
> > > +
> > > +             /* Convert from HCI to three-value type */
> > > +             if (hcon->src_type == ADDR_LE_DEV_PUBLIC)
> > > +                     iso_pi(sk)->src_type = BDADDR_LE_PUBLIC;
> > > +             else
> > > +                     iso_pi(sk)->src_type = BDADDR_LE_RANDOM;
> > >
> > >               /* If hcon has no destination address (BDADDR_ANY) it means it
> > > -              * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED so we
> need to
> > > -              * initialize using the parent socket destination address.
> > > +              * was created by HCI_EV_LE_BIG_SYNC_ESTABILISHED or
> > > +              * HCI_EV_LE_PA_SYNC_ESTABLISHED so we need to initialize
> using
> > > +              * the parent socket destination address.
> > >                */
> > >               if (!bacmp(&hcon->dst, BDADDR_ANY)) {
> > >                       bacpy(&hcon->dst, &iso_pi(parent)->dst); @@
> > > -1566,13 +1646,21 @@ static void iso_conn_ready(struct iso_conn *conn)
> > >                       hcon->sync_handle = iso_pi(parent)->sync_handle;
> > >               }
> > >
> > > +             if (ev2 && !ev2->status) {
> > > +                     iso_pi(sk)->sync_handle = iso_pi(parent)->sync_handle;
> > > +                     iso_pi(sk)->qos = iso_pi(parent)->qos;
> > > +                     iso_pi(sk)->bc_num_bis = iso_pi(parent)->bc_num_bis;
> > > +                     memcpy(iso_pi(sk)->bc_bis, iso_pi(parent)->bc_bis,
> ISO_MAX_NUM_BIS);
> > > +             }
> > > +
> > >               bacpy(&iso_pi(sk)->dst, &hcon->dst);
> > >               iso_pi(sk)->dst_type = hcon->dst_type;
> > >
> > >               hci_conn_hold(hcon);
> > >               iso_chan_add(conn, sk, parent);
> > >
> > > -             if (ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status)
> {
> > > +             if ((ev && ((struct hci_evt_le_big_sync_estabilished *)ev)-
> >status) ||
> > > +                 (ev2 && ev2->status)) {
> > >                       /* Trigger error signal on child socket */
> > >                       sk->sk_err = ECONNREFUSED;
> > >                       sk->sk_error_report(sk); @@ -1630,7 +1718,7 @@
> > > int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8
> *flags)
> > >       if (ev1) {
> > >               sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr, iso_match_sid,
> > >                                        ev1);
> > > -             if (sk)
> > > +             if (sk && !ev1->status)
> > >                       iso_pi(sk)->sync_handle =
> > > le16_to_cpu(ev1->handle);
> > >
> > >               goto done;
> > > @@ -1638,16 +1726,21 @@ int iso_connect_ind(struct hci_dev *hdev,
> > > bdaddr_t *bdaddr, __u8 *flags)
> > >
> > >       ev2 = hci_recv_event_data(hdev,
> HCI_EVT_LE_BIG_INFO_ADV_REPORT);
> > >       if (ev2) {
> > > +             /* Try to get PA sync listening socket, if it exists
> > > + */
> > >               sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
> > > -                                      iso_match_sync_handle, ev2);
> > > +                                             iso_match_pa_sync_flag, NULL);
> > > +             if (!sk)
> > > +                     sk = iso_get_sock_listen(&hdev->bdaddr, bdaddr,
> > > +
> > > + iso_match_sync_handle, ev2);
> > >               if (sk) {
> > >                       int err;
> > >
> > >                       if (ev2->num_bis < iso_pi(sk)->bc_num_bis)
> > >                               iso_pi(sk)->bc_num_bis = ev2->num_bis;
> > >
> > > -                     if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
> > > -                             err = hci_le_big_create_sync(hdev,
> > > +                     if (!test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags) &&
> > > +                         !test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
> > > +                             err = hci_le_big_create_sync(hdev,
> > > + NULL,
> > >                                                            &iso_pi(sk)->qos,
> > >                                                            iso_pi(sk)->sync_handle,
> > >
> > > iso_pi(sk)->bc_num_bis, @@ -1699,12 +1792,13 @@ static void
> > > iso_connect_cfm(struct hci_conn *hcon, __u8 status)
> > >
> > >       BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst,
> > > status);
> > >
> > > -     /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED is set,
> > > -      * queue the failed bis connection into the accept queue of the
> > > -      * listening socket and wake up userspace, to inform the user about
> > > -      * the BIG sync failed event.
> > > +     /* Similar to the success case, if HCI_CONN_BIG_SYNC_FAILED or
> > > +      * HCI_CONN_PA_SYNC_FAILED is set, queue the failed connection
> > > +      * into the accept queue of the listening socket and wake up
> > > +      * userspace, to inform the user about the event.
> > >        */
> > > -     if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)) {
> > > +     if (!status || test_bit(HCI_CONN_BIG_SYNC_FAILED, &hcon->flags)
> ||
> > > +         test_bit(HCI_CONN_PA_SYNC_FAILED, &hcon->flags)) {
> > >               struct iso_conn *conn;
> > >
> > >               conn = iso_conn_add(hcon);
> >
> > --
> > Pauli Virtanen
> 
> 
> 
> --
> Luiz Augusto von Dentz


Regards,
Iulia



[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