Re: [PATCH BlueZ 1/2] a2dp: Store last used endpoint

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

 



On Wednesday 24 April 2019 18:57:21 Pali Rohár wrote:
> On Wednesday 24 April 2019 12:42:22 Luiz Augusto von Dentz wrote:
> > Hi Pali,
> > 
> > On Wed, Apr 24, 2019 at 11:39 AM Luiz Augusto von Dentz
> > <luiz.dentz@xxxxxxxxx> wrote:
> > >
> > > From: Luiz Augusto von Dentz <luiz.von.dentz@xxxxxxxxx>
> > >
> > > This stores the last used endpoint whenever it is considered open and
> > > then prefer to use it when attempting to reconnect.
> > > ---
> > >  profiles/audio/a2dp.c | 104 ++++++++++++++++++++++++++++++++++++------
> > >  1 file changed, 91 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c
> > > index 8f141739c..78b02dc84 100644
> > > --- a/profiles/audio/a2dp.c
> > > +++ b/profiles/audio/a2dp.c
> > > @@ -147,6 +147,7 @@ struct a2dp_channel {
> > >         unsigned int auth_id;
> > >         struct avdtp *session;
> > >         struct queue *seps;
> > > +       struct a2dp_remote_sep *last_used;
> > >  };
> > >
> > >  static GSList *servers = NULL;
> > > @@ -860,6 +861,60 @@ static gboolean open_ind(struct avdtp *session, struct avdtp_local_sep *sep,
> > >         return TRUE;
> > >  }
> > >
> > > +static bool match_remote_sep(const void *data, const void *user_data)
> > > +{
> > > +       const struct a2dp_remote_sep *sep = data;
> > > +       const struct avdtp_remote_sep *rsep = user_data;
> > > +
> > > +       return sep->sep == rsep;
> > > +}
> > > +
> > > +static void store_last_used(struct a2dp_channel *chan,
> > > +                                       struct avdtp_remote_sep *rsep)
> > > +{
> > > +       GKeyFile *key_file;
> > > +       char filename[PATH_MAX];
> > > +       char dst_addr[18];
> > > +       char value[4];
> > > +       char *data;
> > > +       size_t len = 0;
> > > +
> > > +       ba2str(device_get_address(chan->device), dst_addr);
> > > +
> > > +       snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
> > > +               btd_adapter_get_storage_dir(device_get_adapter(chan->device)),
> > > +               dst_addr);
> > > +       key_file = g_key_file_new();
> > > +       g_key_file_load_from_file(key_file, filename, 0, NULL);
> > > +
> > > +       sprintf(value, "%02hhx", avdtp_get_seid(rsep));
> > > +
> > > +       g_key_file_set_string(key_file, "Endpoints", "LastUsed", value);
> > > +
> > > +       data = g_key_file_to_data(key_file, &len, NULL);
> > > +       g_file_set_contents(filename, data, len, NULL);
> > > +
> > > +       g_free(data);
> > > +       g_key_file_free(key_file);
> > > +}
> > > +
> > > +static void update_last_used(struct a2dp_channel *chan,
> > > +                                               struct avdtp_stream *stream)
> > > +{
> > > +       struct avdtp_remote_sep *rsep;
> > > +       struct a2dp_remote_sep *sep;
> > > +
> > > +       rsep = avdtp_stream_get_remote_sep(stream);
> > > +
> > > +       /* Update last used */
> > > +       sep = queue_find(chan->seps, match_remote_sep, rsep);
> > > +       if (chan->last_used == sep)
> > > +               return;
> > > +
> > > +       chan->last_used = sep;
> > > +       store_last_used(chan, rsep);
> > > +}
> > > +
> > >  static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
> > >                         struct avdtp_stream *stream, struct avdtp_error *err,
> > >                         void *user_data)
> > > @@ -884,7 +939,8 @@ static void open_cfm(struct avdtp *session, struct avdtp_local_sep *sep,
> > >                 setup->err = err;
> > >                 if (setup->start)
> > >                         finalize_resume(setup);
> > > -       }
> > > +       } else if (setup->chan)
> > > +               update_last_used(setup->chan, stream);
> > >
> > >         finalize_config(setup);
> > >
> > > @@ -1077,14 +1133,6 @@ static gboolean close_ind(struct avdtp *session, struct avdtp_local_sep *sep,
> > >         return TRUE;
> > >  }
> > >
> > > -static bool match_remote_sep(const void *data, const void *user_data)
> > > -{
> > > -       const struct a2dp_remote_sep *sep = data;
> > > -       const struct avdtp_remote_sep *rsep = user_data;
> > > -
> > > -       return sep->sep == rsep;
> > > -}
> > > -
> > >  static struct a2dp_remote_sep *find_remote_sep(struct a2dp_channel *chan,
> > >                                                 struct a2dp_sep *sep)
> > >  {
> > > @@ -1791,19 +1839,28 @@ done:
> > >         queue_push_tail(chan->seps, sep);
> > >  }
> > >
> > > +static bool match_seid(const void *data, const void *user_data)
> > > +{
> > > +       const struct a2dp_remote_sep *sep = data;
> > > +       const uint8_t *seid = user_data;
> > > +
> > > +       return avdtp_get_seid(sep->sep) == *seid;
> > > +}
> > > +
> > >  static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
> > >                                                                 char **seids)
> > >  {
> > >         struct avdtp_remote_sep *sep;
> > > +       uint8_t seid;
> > > +       char *value;
> > >
> > >         if (!seids)
> > >                 return;
> > >
> > >         for (; *seids; seids++) {
> > > -               uint8_t seid;
> > >                 uint8_t type;
> > >                 uint8_t codec;
> > > -               char *value, caps[256];
> > > +               char caps[256];
> > >                 uint8_t data[128];
> > >                 int i, size;
> > >                 GSList *l = NULL;
> > > @@ -1847,6 +1904,15 @@ static void load_remote_sep(struct a2dp_channel *chan, GKeyFile *key_file,
> > >
> > >                 register_remote_sep(sep, chan);
> > >         }
> > > +
> > > +       value = g_key_file_get_string(key_file, "Endpoints", "LastUsed", NULL);
> > > +       if (!value)
> > > +               return;
> > > +
> > > +       if (sscanf(value, "%02hhx", &seid) != 1)
> > > +               return;
> > > +
> > > +       chan->last_used = queue_find(chan->seps, match_seid, &seid);
> > >  }
> > >
> > >  static void load_remote_seps(struct a2dp_channel *chan)
> > > @@ -2355,8 +2421,12 @@ done:
> > >  static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
> > >                                         const char *sender)
> > >  {
> > > +       struct a2dp_sep *first = NULL;
> > > +       struct a2dp_channel *chan = find_channel(session);
> > > +
> > >         for (; list; list = list->next) {
> > >                 struct a2dp_sep *sep = list->data;
> > > +               struct avdtp_remote_sep *rsep;
> > >
> > >                 /* Use sender's endpoint if available */
> > >                 if (sender) {
> > > @@ -2370,14 +2440,22 @@ static struct a2dp_sep *a2dp_find_sep(struct avdtp *session, GSList *list,
> > >                                 continue;
> > >                 }
> > >
> > > -               if (avdtp_find_remote_sep(session, sep->lsep) == NULL)
> > > +               rsep = avdtp_find_remote_sep(session, sep->lsep);
> > > +               if (!rsep)
> > >                         continue;
> > >
> > > +               /* Locate last used if set */
> > > +               if (chan->last_used) {
> > > +                       if (chan->last_used->sep == rsep)
> > > +                               return sep;
> > > +                       first = sep;
> > > +               }
> > > +
> > >                 return sep;
> > >
> > >         }
> > >
> > > -       return NULL;
> > > +       return first;
> > >  }
> > >
> > >  static struct a2dp_sep *a2dp_select_sep(struct avdtp *session, uint8_t type,
> > > --
> > > 2.20.1
> > 
> > Can you give this a try, it should make the daemon remember what was
> > the last endpoint used (locally the remote selection we cannot really
> > control).
> 
> Great, I will try it.

Seems that it does not work as expected when there are more SEPs for one
codec.

Before bluez chose first registered endpoint which matched codec. Now in
git master is bluez choosing last registered endpoint which matched
codec. So before it was SBC at highest quality, now it is SBC at lowest
quality.

-- 
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