mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez5: Add support for Broadcast links
This adds support for BAP Broadcast transport links. Unlike unicast, broadcast links are used by a BAP Broadcast Sink device to link together multiple transports in the same BIG that the user wants to start receiving audio from. Each transport is associated with a different BIS, so each one has a different fd. Thus, each link needs to be acquired and released separately.
This commit is contained in:
		
							parent
							
								
									7f885a2e94
								
							
						
					
					
						commit
						b2a70f5933
					
				
					 1 changed files with 37 additions and 7 deletions
				
			
		| 
						 | 
					@ -3455,6 +3455,9 @@ static int transport_update_props(struct spa_bt_transport *transport,
 | 
				
			||||||
			if (!check_iter_signature(&it[1], "ao"))
 | 
								if (!check_iter_signature(&it[1], "ao"))
 | 
				
			||||||
				goto next;
 | 
									goto next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								spa_list_remove(&transport->bap_transport_linked);
 | 
				
			||||||
 | 
								spa_list_init(&transport->bap_transport_linked);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			dbus_message_iter_recurse(&it[1], &iter);
 | 
								dbus_message_iter_recurse(&it[1], &iter);
 | 
				
			||||||
			while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
 | 
								while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
 | 
				
			||||||
				const char *transport_path;
 | 
									const char *transport_path;
 | 
				
			||||||
| 
						 | 
					@ -3684,22 +3687,33 @@ static void transport_acquire_reply(DBusPendingCall *pending, void *user_data)
 | 
				
			||||||
	transport_sync_volume(transport);
 | 
						transport_sync_volume(transport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
finish:
 | 
					finish:
 | 
				
			||||||
	if (ret < 0)
 | 
						if (ret < 0) {
 | 
				
			||||||
		spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ERROR);
 | 
							spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ERROR);
 | 
				
			||||||
	else {
 | 
					
 | 
				
			||||||
 | 
							/* For broadcast, skip handling links. Each link acquire
 | 
				
			||||||
 | 
							 * is handled separately.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
 | 
				
			||||||
 | 
								(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		if (transport_create_iso_io(transport) < 0)
 | 
							if (transport_create_iso_io(transport) < 0)
 | 
				
			||||||
			spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed",
 | 
								spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed",
 | 
				
			||||||
					transport);
 | 
										transport);
 | 
				
			||||||
		/* For broadcast the initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */
 | 
							/* For broadcast, each transport has a different fd, so it needs to be
 | 
				
			||||||
 | 
							 * acquired independently from others. Each transport moves to
 | 
				
			||||||
 | 
							 * SPA_BT_TRANSPORT_STATE_ACTIVE after acquire is completed.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
		/* TODO: handling multiple BIGs support */
 | 
							/* TODO: handling multiple BIGs support */
 | 
				
			||||||
		if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
 | 
							if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
 | 
				
			||||||
			(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))	{
 | 
								(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))	{
 | 
				
			||||||
			spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
 | 
								spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
 | 
				
			||||||
		} else {
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!transport->bap_initiator)
 | 
							if (!transport->bap_initiator)
 | 
				
			||||||
			spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
 | 
								spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* For LE Audio, multiple transport from the same device may share the same
 | 
						/* 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
 | 
						 * stream (CIS) and group (CIG) but for different direction, e.g. a speaker and
 | 
				
			||||||
| 
						 | 
					@ -3758,6 +3772,13 @@ static int do_transport_acquire(struct spa_bt_transport *transport)
 | 
				
			||||||
	spa_autoptr(DBusMessage) m = NULL;
 | 
						spa_autoptr(DBusMessage) m = NULL;
 | 
				
			||||||
	struct spa_bt_transport *t_linked;
 | 
						struct spa_bt_transport *t_linked;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
 | 
				
			||||||
 | 
							(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))
 | 
				
			||||||
 | 
							/* For Broadcast, all linked transports need to be
 | 
				
			||||||
 | 
							 * acquired independently, since they have different fds.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							goto acquire;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
 | 
						spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
 | 
				
			||||||
		/* If a linked transport has been acquired, it will do all the work */
 | 
							/* If a linked transport has been acquired, it will do all the work */
 | 
				
			||||||
		if (t_linked->acquire_call || t_linked->acquired) {
 | 
							if (t_linked->acquire_call || t_linked->acquired) {
 | 
				
			||||||
| 
						 | 
					@ -3768,6 +3789,7 @@ static int do_transport_acquire(struct spa_bt_transport *transport)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					acquire:
 | 
				
			||||||
	if (transport->acquire_call)
 | 
						if (transport->acquire_call)
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3862,10 +3884,17 @@ static int do_transport_release(struct spa_bt_transport *transport)
 | 
				
			||||||
		transport->iso_io = NULL;
 | 
							transport->iso_io = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* For LE Audio, multiple transport stream (CIS) can be linked together (CIG).
 | 
						/* For Unicast LE Audio, multiple transport stream (CIS) can be linked together (CIG).
 | 
				
			||||||
	 * If they are part of the same device they reuse the same fd, and call to
 | 
						 * If they are part of the same device they reuse the same fd, and call to
 | 
				
			||||||
	 * release should be done for the last one only.
 | 
						 * release should be done for the last one only.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * For Broadcast LE Audio, since linked transports have different fds, they
 | 
				
			||||||
 | 
						 * should be released independently.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
						if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) ||
 | 
				
			||||||
 | 
							(transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))
 | 
				
			||||||
 | 
							goto release;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
 | 
						spa_list_for_each(t_linked, &transport->bap_transport_linked, bap_transport_linked) {
 | 
				
			||||||
		if (t_linked->acquire_call || t_linked->acquired) {
 | 
							if (t_linked->acquire_call || t_linked->acquired) {
 | 
				
			||||||
			linked = true;
 | 
								linked = true;
 | 
				
			||||||
| 
						 | 
					@ -3878,6 +3907,7 @@ static int do_transport_release(struct spa_bt_transport *transport)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					release:
 | 
				
			||||||
	if (transport->fd >= 0) {
 | 
						if (transport->fd >= 0) {
 | 
				
			||||||
		close(transport->fd);
 | 
							close(transport->fd);
 | 
				
			||||||
		transport->fd = -1;
 | 
							transport->fd = -1;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue