Re: [PATCH v3 3/3] a2dp: Fix not calling SelectConfiguration on other available endpoints

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

 



On Monday 29 April 2019 19:35:24 Luiz Augusto von Dentz wrote:
> Hi Pali,
> 
> On Mon, Apr 29, 2019 at 3:03 PM Luiz Augusto von Dentz
> <luiz.dentz@xxxxxxxxx> wrote:
> >
> > From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
> >
> > Endpoint may not be able to select a valid configuration but there could
> > be other endpoints available that could be used, so instead of just
> > using the first match this collects all the matching endpoints and put
> > them into a queue (ordered by priority) then proceed to next endpoint
> > only failing if none of the available endpoits can select a valid
> > configuration.
> > ---
> >  profiles/audio/a2dp.c | 77 ++++++++++++++++++++++++++++---------------
> >  1 file changed, 50 insertions(+), 27 deletions(-)
> >
> > diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
> > index a23abdd97..4d378a91a 100644
> > --- a/profiles/audio/a2dp.c
> > +++ b/profiles/audio/a2dp.c
> > @@ -105,6 +105,7 @@ struct a2dp_setup_cb {
> >  struct a2dp_setup {
> >         struct a2dp_channel *chan;
> >         struct avdtp *session;
> > +       struct queue *eps;
> >         struct a2dp_sep *sep;
> >         struct a2dp_remote_sep *rsep;
> >         struct avdtp_stream *stream;
> > @@ -2406,23 +2407,44 @@ void a2dp_remove_sep(struct a2dp_sep *sep)
> >
> >  static void select_cb(struct a2dp_setup *setup, void *ret, int size)
> >  {
> > -       if (size < 0) {
> > -               DBG("Endpoint replied an invalid configuration");
> > +       struct avdtp_service_capability *service;
> > +       struct avdtp_media_codec_capability *codec;
> > +       int err;
> > +
> > +       if (size) {
> > +               caps_add_codec(&setup->caps, setup->sep->codec, ret, size);
> >                 goto done;
> >         }
> >
> > -       caps_add_codec(&setup->caps, setup->sep->codec, ret, size);
> > +       setup->sep = queue_pop_head(setup->eps);
> > +       if (!setup->sep) {
> > +               error("Unable to select a valid configuration");
> > +               queue_destroy(setup->eps, NULL);
> > +               goto done;
> > +       }
> > +
> > +       setup->rsep = find_remote_sep(setup->chan, setup->sep);
> > +       service = avdtp_get_codec(setup->rsep->sep);
> > +       codec = (struct avdtp_media_codec_capability *) service->data;
> > +
> > +       err = setup->sep->endpoint->select_configuration(setup->sep,
> > +                                       codec->data,
> > +                                       service->length - sizeof(*codec),
> > +                                       setup_ref(setup),
> > +                                       select_cb, setup->sep->user_data);
> > +       if (err == 0)
> > +               return;
> >
> >  done:
> >         finalize_select(setup);
> >         setup_unref(setup);
> >  }
> >
> > -static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
> > +static struct queue *a2dp_find_eps(struct avdtp *session, GSList *list,
> >                                         const char *sender)
> >  {
> > -       struct a2dp_sep *first = NULL;
> >         struct a2dp_channel *chan = find_channel(session);
> > +       struct queue *seps = NULL;
> >
> >         for (; list; list = list->next) {
> >                 struct a2dp_sep *sep = list->data;
> > @@ -2444,26 +2466,25 @@ static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
> >                 if (!rsep)
> >                         continue;
> >
> > -               /* Locate last used if set */
> > -               if (chan->last_used) {
> > -                       if (chan->last_used->sep == rsep)
> > -                               return sep;
> > -                       first = sep;
> > -                       continue;
> > -               }
> > +               if (!seps)
> > +                       seps = queue_new();
> >
> > -               return sep;
> > +               /* Prepend last used so it is preferred over others */
> > +               if (chan->last_used && chan->last_used->sep == rsep)
> > +                       queue_push_head(seps, sep);
> > +               else
> > +                       queue_push_tail(seps, sep);
> >
> >         }
> >
> > -       return first;
> > +       return seps;
> >  }
> >
> > -static struct a2dp_sep *a2dp_select_sep(struct avdtp *session, uint8_t type,
> > +static struct queue *a2dp_select_eps(struct avdtp *session, uint8_t type,
> >                                         const char *sender)
> >  {
> >         struct a2dp_server *server;
> > -       struct a2dp_sep *sep;
> > +       struct queue *seps;
> >         GSList *l;
> >
> >         server = find_server(servers, avdtp_get_adapter(session));
> > @@ -2473,11 +2494,11 @@ static struct a2dp_sep *a2dp_select_sep(struct avdtp *session, uint8_t type,
> >         l = type == AVDTP_SEP_TYPE_SINK ? server->sources : server->sinks;
> >
> >         /* Check sender's seps first */
> > -       sep = a2dp_find_sep(session, l, sender);
> > -       if (sep != NULL)
> > -               return sep;
> > +       seps = a2dp_find_eps(session, l, sender);
> > +       if (seps != NULL)
> > +               return seps;
> >
> > -       return a2dp_find_sep(session, l, NULL);
> > +       return a2dp_find_eps(session, l, NULL);
> >  }
> >
> >  static void store_remote_sep(void *data, void *user_data)
> > @@ -2580,13 +2601,13 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
> >  {
> >         struct a2dp_setup *setup;
> >         struct a2dp_setup_cb *cb_data;
> > -       struct a2dp_sep *sep;
> > +       struct queue *eps;
> >         struct avdtp_service_capability *service;
> >         struct avdtp_media_codec_capability *codec;
> >         int err;
> >
> > -       sep = a2dp_select_sep(session, type, sender);
> > -       if (!sep) {
> > +       eps = a2dp_select_eps(session, type, sender);
> > +       if (!eps) {
> >                 error("Unable to select SEP");
> >                 return 0;
> >         }
> > @@ -2599,8 +2620,9 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
> >         cb_data->select_cb = cb;
> >         cb_data->user_data = user_data;
> >
> > -       setup->sep = sep;
> > -       setup->rsep = find_remote_sep(setup->chan, sep);
> > +       setup->eps = eps;
> > +       setup->sep = queue_pop_head(eps);
> > +       setup->rsep = find_remote_sep(setup->chan, setup->sep);
> >
> >         if (setup->rsep == NULL) {
> >                 error("Could not find remote sep");
> > @@ -2610,10 +2632,11 @@ unsigned int a2dp_select_capabilities(struct avdtp *session,
> >         service = avdtp_get_codec(setup->rsep->sep);
> >         codec = (struct avdtp_media_codec_capability *) service->data;
> >
> > -       err = sep->endpoint->select_configuration(sep, codec->data,
> > +       err = setup->sep->endpoint->select_configuration(setup->sep,
> > +                                       codec->data,
> >                                         service->length - sizeof(*codec),
> >                                         setup_ref(setup),
> > -                                       select_cb, sep->user_data);
> > +                                       select_cb, setup->sep->user_data);
> >         if (err == 0)
> >                 return cb_data->id;
> >
> > --
> > 2.20.1
> 
> Le me know if you find any problem with this change, my headsets seems
> to always succeed the first try so I cannot really reproduce the
> problem.

Ok, I will try it in next days. I can register PA endpoints which always
"fails" so I can test if this is working correctly as expected.

Btw, for future patches please directly CC them to me as I'm not
subscribed to list and either extracting them from '> ' quotes or
finding them in web archive is quite impractical.

-- 
Pali Rohár
pali.rohar@xxxxxxxxx

Attachment: signature.asc
Description: PGP signature


[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