mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-16 08:56:45 -05:00
bluez5: Manage BAP linked transports
Multiple transport from the same device may share the same stream (CIS) and group (CIG) but for different direction, e.g. a speaker and a microphone. In this case they are linked. In this case: - On acquire, if another transport has already been acquired, the new transport should not call Acquire or TryAcquire but re-use values from the previously acquired transport, - on release, the closing of transport fd and call to Release should be done only for the last transport.
This commit is contained in:
parent
81f70aa1ec
commit
28b4fbecfb
2 changed files with 72 additions and 2 deletions
|
|
@ -2016,6 +2016,7 @@ struct spa_bt_transport *spa_bt_transport_create(struct spa_bt_monitor *monitor,
|
||||||
t->bap_initiator = monitor->bap_initiator;
|
t->bap_initiator = monitor->bap_initiator;
|
||||||
t->user_data = SPA_PTROFF(t, sizeof(struct spa_bt_transport), void);
|
t->user_data = SPA_PTROFF(t, sizeof(struct spa_bt_transport), void);
|
||||||
spa_hook_list_init(&t->listener_list);
|
spa_hook_list_init(&t->listener_list);
|
||||||
|
spa_list_init(&t->bap_transport_linked);
|
||||||
|
|
||||||
spa_list_append(&monitor->transport_list, &t->link);
|
spa_list_append(&monitor->transport_list, &t->link);
|
||||||
|
|
||||||
|
|
@ -2095,6 +2096,8 @@ void spa_bt_transport_free(struct spa_bt_transport *transport)
|
||||||
if (device && device->connected_profiles != prev_connected)
|
if (device && device->connected_profiles != prev_connected)
|
||||||
spa_bt_device_emit_profiles_changed(device, device->profiles, prev_connected);
|
spa_bt_device_emit_profiles_changed(device, device->profiles, prev_connected);
|
||||||
|
|
||||||
|
spa_list_remove(&transport->bap_transport_linked);
|
||||||
|
|
||||||
free(transport->endpoint_path);
|
free(transport->endpoint_path);
|
||||||
free(transport->path);
|
free(transport->path);
|
||||||
free(transport);
|
free(transport);
|
||||||
|
|
@ -2524,6 +2527,35 @@ static int transport_update_props(struct spa_bt_transport *transport,
|
||||||
transport->delay = value / 100;
|
transport->delay = value / 100;
|
||||||
spa_bt_transport_emit_delay_changed(transport);
|
spa_bt_transport_emit_delay_changed(transport);
|
||||||
}
|
}
|
||||||
|
else if (spa_streq(key, "Links")) {
|
||||||
|
DBusMessageIter iter;
|
||||||
|
|
||||||
|
if (!check_iter_signature(&it[1], "ao"))
|
||||||
|
goto next;
|
||||||
|
|
||||||
|
dbus_message_iter_recurse(&it[1], &iter);
|
||||||
|
while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
|
||||||
|
const char *transport_path;
|
||||||
|
struct spa_bt_transport *t;
|
||||||
|
|
||||||
|
dbus_message_iter_get_basic(&iter, &transport_path);
|
||||||
|
|
||||||
|
spa_log_debug(monitor->log, "transport %p: Linked with=%s", transport, transport_path);
|
||||||
|
t = spa_bt_transport_find(monitor, transport_path);
|
||||||
|
if (!t) {
|
||||||
|
spa_log_warn(monitor->log, "Unable to find linked transport");
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spa_list_is_empty(&t->bap_transport_linked))
|
||||||
|
spa_list_append(&transport->bap_transport_linked, &t->bap_transport_linked);
|
||||||
|
else if (spa_list_is_empty(&transport->bap_transport_linked))
|
||||||
|
spa_list_append(&t->bap_transport_linked, &transport->bap_transport_linked);
|
||||||
|
|
||||||
|
dbus_message_iter_next(&iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
next:
|
next:
|
||||||
dbus_message_iter_next(props_iter);
|
dbus_message_iter_next(props_iter);
|
||||||
}
|
}
|
||||||
|
|
@ -2607,10 +2639,27 @@ static int transport_acquire(void *data, bool optional)
|
||||||
{
|
{
|
||||||
struct spa_bt_transport *transport = data;
|
struct spa_bt_transport *transport = data;
|
||||||
struct spa_bt_monitor *monitor = transport->monitor;
|
struct spa_bt_monitor *monitor = transport->monitor;
|
||||||
DBusMessage *m, *r;
|
DBusMessage *m, *r = NULL;
|
||||||
DBusError err;
|
DBusError err;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
const char *method = optional ? "TryAcquire" : "Acquire";
|
const char *method = optional ? "TryAcquire" : "Acquire";
|
||||||
|
struct spa_bt_transport *t_linked;
|
||||||
|
|
||||||
|
/* For LE Audio, multiple transport from the same device may share the same
|
||||||
|
* stream (CIS) and group (CIG) but for different direction, e.g. a speaker and
|
||||||
|
* a microphone. In this case they are linked.
|
||||||
|
* If one of them has already been acquired this function should not call Acquire
|
||||||
|
* or TryAcquire but re-use values from the previously acquired transport.
|
||||||
|
*/
|
||||||
|
spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
|
||||||
|
if (t_linked->acquired && t_linked->device == transport->device) {
|
||||||
|
transport->fd = t_linked->fd;
|
||||||
|
transport->read_mtu = t_linked->read_mtu;
|
||||||
|
transport->write_mtu = t_linked->write_mtu;
|
||||||
|
spa_log_debug(monitor->log, "transport %p: linked transport %s", transport, t_linked->path);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m = dbus_message_new_method_call(BLUEZ_SERVICE,
|
m = dbus_message_new_method_call(BLUEZ_SERVICE,
|
||||||
transport->path,
|
transport->path,
|
||||||
|
|
@ -2654,6 +2703,7 @@ static int transport_acquire(void *data, bool optional)
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
spa_log_debug(monitor->log, "transport %p: %s %s, fd %d MTU %d:%d", transport, method,
|
spa_log_debug(monitor->log, "transport %p: %s %s, fd %d MTU %d:%d", transport, method,
|
||||||
transport->path, transport->fd, transport->read_mtu, transport->write_mtu);
|
transport->path, transport->fd, transport->read_mtu, transport->write_mtu);
|
||||||
|
|
||||||
|
|
@ -2662,7 +2712,8 @@ static int transport_acquire(void *data, bool optional)
|
||||||
transport_sync_volume(transport);
|
transport_sync_volume(transport);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
dbus_message_unref(r);
|
if (r)
|
||||||
|
dbus_message_unref(r);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2673,12 +2724,30 @@ static int transport_release(void *data)
|
||||||
DBusMessage *m, *r;
|
DBusMessage *m, *r;
|
||||||
DBusError err;
|
DBusError err;
|
||||||
bool is_idle = (transport->state == SPA_BT_TRANSPORT_STATE_IDLE);
|
bool is_idle = (transport->state == SPA_BT_TRANSPORT_STATE_IDLE);
|
||||||
|
struct spa_bt_transport *t_linked;
|
||||||
|
bool linked = false;
|
||||||
|
|
||||||
spa_log_debug(monitor->log, "transport %p: Release %s",
|
spa_log_debug(monitor->log, "transport %p: Release %s",
|
||||||
transport, transport->path);
|
transport, transport->path);
|
||||||
|
|
||||||
spa_bt_player_set_state(transport->device->adapter->dummy_player, SPA_BT_PLAYER_STOPPED);
|
spa_bt_player_set_state(transport->device->adapter->dummy_player, SPA_BT_PLAYER_STOPPED);
|
||||||
|
|
||||||
|
/* For LE Audio, multiple transport stream (CIS) can be linked together (CIG).
|
||||||
|
* If they are part of the same device they re-use the same fd, and call to
|
||||||
|
* release should be done for the last one only.
|
||||||
|
*/
|
||||||
|
spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
|
||||||
|
if (t_linked->acquired && t_linked->device == transport->device) {
|
||||||
|
linked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (linked) {
|
||||||
|
spa_log_info(monitor->log, "Linked transport %s released", transport->path);
|
||||||
|
transport->fd = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
close(transport->fd);
|
close(transport->fd);
|
||||||
transport->fd = -1;
|
transport->fd = -1;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -603,6 +603,7 @@ struct spa_bt_transport {
|
||||||
int configuration_len;
|
int configuration_len;
|
||||||
char *endpoint_path;
|
char *endpoint_path;
|
||||||
bool bap_initiator;
|
bool bap_initiator;
|
||||||
|
struct spa_list bap_transport_linked;
|
||||||
|
|
||||||
uint32_t n_channels;
|
uint32_t n_channels;
|
||||||
uint32_t channels[64];
|
uint32_t channels[64];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue