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. Now I run 'sudo grep LastUsed -r /var/lib/bluetooth/' and see that this properly is stored only for one device. So seems that bluetoothd does not always stores LastUsed information. E.g. when I called and successfully connected device via command $ qdbus --system org.bluez /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX org.bluez.Device1.ConnectProfile 0000110a-0000-1000-8000-00805f9b34fb and later disconnected, I have not found anything via above grep. -- Pali Rohár pali.rohar@xxxxxxxxx
Attachment:
signature.asc
Description: PGP signature