Hi, 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> > > 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 | 105 ++++++++++++++++++++++++++++++++++++------ > 1 file changed, 92 insertions(+), 13 deletions(-) > > diff --git a/profiles/audio/a2dp.c b/profiles/audio/a2dp.c > index 8f141739c..a23abdd97 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,23 @@ 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; > + continue; > + } > + > return sep; > > } > > - return NULL; > + return first; > } > > static struct a2dp_sep *a2dp_select_sep(struct avdtp *session, uint8_t type, > -- > 2.20.1 Applied. -- Luiz Augusto von Dentz