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

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

 



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


-- 
Luiz Augusto von Dentz



[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