mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	bluez: backend-ofono: advertise transport state for incoming connections
This commit is contained in:
		
							parent
							
								
									f9b39191c4
								
							
						
					
					
						commit
						343be7503a
					
				
					 1 changed files with 65 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -54,6 +54,10 @@ struct spa_bt_backend {
 | 
			
		|||
	unsigned int msbc_supported:1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct transport_data {
 | 
			
		||||
	struct spa_source sco;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define OFONO_HF_AUDIO_MANAGER_INTERFACE OFONO_SERVICE ".HandsfreeAudioManager"
 | 
			
		||||
#define OFONO_HF_AUDIO_CARD_INTERFACE OFONO_SERVICE ".HandsfreeAudioCard"
 | 
			
		||||
#define OFONO_HF_AUDIO_AGENT_INTERFACE OFONO_SERVICE ".HandsfreeAudioAgent"
 | 
			
		||||
| 
						 | 
				
			
			@ -80,6 +84,7 @@ struct spa_bt_backend {
 | 
			
		|||
	"</node>"
 | 
			
		||||
 | 
			
		||||
#define OFONO_ERROR_INVALID_ARGUMENTS "org.ofono.Error.InvalidArguments"
 | 
			
		||||
#define OFONO_ERROR_NOT_IMPLEMENTED "org.ofono.Error.NotImplemented"
 | 
			
		||||
#define OFONO_ERROR_IN_USE "org.ofono.Error.InUse"
 | 
			
		||||
 | 
			
		||||
static void ofono_transport_get_mtu(struct spa_bt_backend *backend, struct spa_bt_transport *t)
 | 
			
		||||
| 
						 | 
				
			
			@ -113,7 +118,7 @@ static struct spa_bt_transport *_transport_create(struct spa_bt_backend *backend
 | 
			
		|||
	struct spa_bt_transport *t = NULL;
 | 
			
		||||
	char *t_path = strdup(path);
 | 
			
		||||
 | 
			
		||||
	t = spa_bt_transport_create(backend->monitor, t_path, 0);
 | 
			
		||||
	t = spa_bt_transport_create(backend->monitor, t_path, sizeof(struct transport_data));
 | 
			
		||||
	if (t == NULL) {
 | 
			
		||||
		spa_log_warn(backend->log, NAME": can't create transport: %m");
 | 
			
		||||
		free(t_path);
 | 
			
		||||
| 
						 | 
				
			
			@ -186,6 +191,9 @@ static int ofono_audio_acquire(void *data, bool optional)
 | 
			
		|||
	uint8_t codec;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
 | 
			
		||||
	if (transport->fd)
 | 
			
		||||
		goto finish;
 | 
			
		||||
 | 
			
		||||
	ret = _audio_acquire(backend, transport->path, &codec);
 | 
			
		||||
	if (ret < 0)
 | 
			
		||||
		goto finish;
 | 
			
		||||
| 
						 | 
				
			
			@ -283,8 +291,7 @@ static DBusHandlerResult ofono_audio_card_found(struct spa_bt_backend *backend,
 | 
			
		|||
	struct spa_bt_device *d;
 | 
			
		||||
	struct spa_bt_transport *t;
 | 
			
		||||
	enum spa_bt_profile profile = SPA_BT_PROFILE_HFP_AG;
 | 
			
		||||
	int fd;
 | 
			
		||||
	uint8_t codec;
 | 
			
		||||
	uint8_t codec = HFP_AUDIO_CODEC_CVSD;
 | 
			
		||||
 | 
			
		||||
	spa_assert(backend);
 | 
			
		||||
	spa_assert(path);
 | 
			
		||||
| 
						 | 
				
			
			@ -324,14 +331,23 @@ static DBusHandlerResult ofono_audio_card_found(struct spa_bt_backend *backend,
 | 
			
		|||
		dbus_message_iter_next(props_i);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd = _audio_acquire(backend, path, &codec);
 | 
			
		||||
	if (fd < 0) {
 | 
			
		||||
		spa_log_error(backend->log, NAME": Failed to retrieve codec for %s", path);
 | 
			
		||||
		return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 | 
			
		||||
	/*
 | 
			
		||||
	 * Acquire and close immediately to figure out the codec.
 | 
			
		||||
	 * This is necessary if we are in HF mode, because we need to emit
 | 
			
		||||
	 * nodes and the advertised sample rate of the node depends on the codec.
 | 
			
		||||
	 * For AG mode, we delay the emission of the nodes, so it is not necessary
 | 
			
		||||
	 * to know the codec in advance
 | 
			
		||||
	 */
 | 
			
		||||
	if (profile == SPA_BT_PROFILE_HFP_HF) {
 | 
			
		||||
		int fd = _audio_acquire(backend, path, &codec);
 | 
			
		||||
		if (fd < 0) {
 | 
			
		||||
			spa_log_error(backend->log, NAME": Failed to retrieve codec for %s", path);
 | 
			
		||||
			return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 | 
			
		||||
		}
 | 
			
		||||
		/* shutdown to make sure connection is dropped immediately */
 | 
			
		||||
		shutdown(fd, SHUT_RDWR);
 | 
			
		||||
		close(fd);
 | 
			
		||||
	}
 | 
			
		||||
	/* shutdown to make sure connection is dropped immediately */
 | 
			
		||||
	shutdown(fd, SHUT_RDWR);
 | 
			
		||||
	close(fd);
 | 
			
		||||
 | 
			
		||||
	d = spa_bt_device_find_by_address(backend->monitor, remote_address, local_address);
 | 
			
		||||
	if (!d) {
 | 
			
		||||
| 
						 | 
				
			
			@ -366,6 +382,24 @@ static DBusHandlerResult ofono_release(DBusConnection *conn, DBusMessage *m, voi
 | 
			
		|||
	return DBUS_HANDLER_RESULT_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sco_event(struct spa_source *source)
 | 
			
		||||
{
 | 
			
		||||
	struct spa_bt_transport *t = source->data;
 | 
			
		||||
	struct spa_bt_backend *backend = t->backend;
 | 
			
		||||
 | 
			
		||||
	if (source->rmask & (SPA_IO_HUP | SPA_IO_ERR)) {
 | 
			
		||||
		spa_log_debug(backend->log, NAME": transport %p: error on SCO socket: %s", t, strerror(errno));
 | 
			
		||||
		if (t->fd >= 0) {
 | 
			
		||||
			if (source->loop)
 | 
			
		||||
				spa_loop_remove_source(source->loop, source);
 | 
			
		||||
			shutdown(t->fd, SHUT_RDWR);
 | 
			
		||||
			close (t->fd);
 | 
			
		||||
			t->fd = -1;
 | 
			
		||||
			spa_bt_transport_set_state(t, SPA_BT_TRANSPORT_STATE_IDLE);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMessage *m, void *userdata)
 | 
			
		||||
{
 | 
			
		||||
	struct spa_bt_backend *backend = userdata;
 | 
			
		||||
| 
						 | 
				
			
			@ -373,6 +407,7 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
 | 
			
		|||
	int fd;
 | 
			
		||||
	uint8_t codec;
 | 
			
		||||
	struct spa_bt_transport *t;
 | 
			
		||||
	struct transport_data *td;
 | 
			
		||||
	DBusMessage *r = NULL;
 | 
			
		||||
 | 
			
		||||
	if (dbus_message_get_args(m, NULL,
 | 
			
		||||
| 
						 | 
				
			
			@ -385,34 +420,30 @@ static DBusHandlerResult ofono_new_audio_connection(DBusConnection *conn, DBusMe
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	t = spa_bt_transport_find(backend->monitor, path);
 | 
			
		||||
	if (t && (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY)) {
 | 
			
		||||
		t->fd = fd;
 | 
			
		||||
		t->codec = codec;
 | 
			
		||||
 | 
			
		||||
	if (!t || t->codec != codec || t->fd >= 0) {
 | 
			
		||||
			spa_log_warn(backend->log, NAME": New audio connection invalid "
 | 
			
		||||
					"arguments (path=%s fd=%d, codec=%d)", path, fd, codec);
 | 
			
		||||
			r = dbus_message_new_error(m, "org.ofono.Error.InvalidArguments", "Invalid arguments in method call");
 | 
			
		||||
			shutdown(fd, SHUT_RDWR);
 | 
			
		||||
			close(fd);
 | 
			
		||||
		spa_log_debug(backend->log, NAME": transport %p: NewConnection %s, fd %d codec %d",
 | 
			
		||||
						t, t->path, t->fd, t->codec);
 | 
			
		||||
 | 
			
		||||
			if (t->codec != codec) {
 | 
			
		||||
				struct spa_bt_transport *transport = NULL;
 | 
			
		||||
		td = t->user_data;
 | 
			
		||||
		td->sco.func = sco_event;
 | 
			
		||||
		td->sco.data = t;
 | 
			
		||||
		td->sco.fd = fd;
 | 
			
		||||
		td->sco.mask = SPA_IO_HUP | SPA_IO_ERR;
 | 
			
		||||
		td->sco.rmask = 0;
 | 
			
		||||
		spa_loop_add_source(backend->main_loop, &td->sco);
 | 
			
		||||
 | 
			
		||||
				spa_log_warn(backend->log, NAME": Acquired codec (%d) differs from transport one (%d)",
 | 
			
		||||
				             codec, t->codec);
 | 
			
		||||
 | 
			
		||||
				/* Create a new transport which differs only for codec */
 | 
			
		||||
				transport = _transport_create(backend, t->path, t->device, t->profile, codec, &t->impl);
 | 
			
		||||
				spa_bt_transport_free(t);
 | 
			
		||||
				spa_bt_device_connect_profile(transport->device, transport->profile);
 | 
			
		||||
			}
 | 
			
		||||
			goto fail;
 | 
			
		||||
		ofono_transport_get_mtu(backend, t);
 | 
			
		||||
		spa_bt_transport_set_state (t, SPA_BT_TRANSPORT_STATE_PENDING);
 | 
			
		||||
	}
 | 
			
		||||
	else if (fd) {
 | 
			
		||||
		spa_log_debug(backend->log, NAME": ignoring NewConnection");
 | 
			
		||||
		r = dbus_message_new_error(m, OFONO_ERROR_NOT_IMPLEMENTED, "Method not implemented");
 | 
			
		||||
		shutdown(fd, SHUT_RDWR);
 | 
			
		||||
		close(fd);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t->fd = fd;
 | 
			
		||||
	ofono_transport_get_mtu(backend, t);
 | 
			
		||||
 | 
			
		||||
	spa_log_debug(backend->log, NAME": transport %p: NewConnection %s, fd %d codec %d", t, t->path, t->fd, t->codec);
 | 
			
		||||
 | 
			
		||||
	/* TODO: pass fd to SCO nodes */
 | 
			
		||||
 | 
			
		||||
fail:
 | 
			
		||||
	if (r) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue