Beispiel #1
0
static void headset_auth_cb(DBusError *derr, void *user_data)
{
	struct audio_device *device = user_data;
	GError *err = NULL;
	GIOChannel *io;

	if (device->hs_preauth_id) {
		g_source_remove(device->hs_preauth_id);
		device->hs_preauth_id = 0;
	}

	if (derr && dbus_error_is_set(derr)) {
		error("Access denied: %s", derr->message);
		headset_set_state(device, HEADSET_STATE_DISCONNECTED);
		return;
	}

	io = headset_get_rfcomm(device);

	if (!bt_io_accept(io, headset_connect_cb, device, NULL, &err)) {
		error("bt_io_accept: %s", err->message);
		g_error_free(err);
		headset_set_state(device, HEADSET_STATE_DISCONNECTED);
		return;
	}
}
Beispiel #2
0
static gboolean hs_preauth_cb(GIOChannel *chan, GIOCondition cond,
							gpointer user_data)
{
	struct audio_device *device = user_data;

	DBG("Headset disconnected during authorization");

	audio_device_cancel_authorization(device, headset_auth_cb, device);

	headset_set_state(device, HEADSET_STATE_DISCONNECTED);

	device->hs_preauth_id = 0;

	return FALSE;
}
Beispiel #3
0
static void sco_server_cb(GIOChannel *chan, GError *err, gpointer data)
{
	int sk;
	struct audio_device *device;
	char addr[18];
	bdaddr_t src, dst;

	if (err) {
		error("sco_server_cb: %s", err->message);
		return;
	}

	bt_io_get(chan, BT_IO_SCO, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, addr,
			BT_IO_OPT_INVALID);
	if (err) {
		error("bt_io_get: %s", err->message);
		goto drop;
	}

	device = manager_find_device(NULL, &src, &dst, AUDIO_HEADSET_INTERFACE,
					FALSE);
	if (!device)
		device = manager_find_device(NULL, &src, &dst,
						AUDIO_GATEWAY_INTERFACE,
						FALSE);

	if (!device)
		goto drop;

	if (device->headset) {
		if (headset_get_state(device) < HEADSET_STATE_CONNECTED) {
			DBG("Refusing SCO from non-connected headset");
			goto drop;
		}

		if (!get_hfp_active(device)) {
			error("Refusing non-HFP SCO connect attempt from %s",
									addr);
			goto drop;
		}

		if (headset_connect_sco(device, chan) < 0)
			goto drop;

		headset_set_state(device, HEADSET_STATE_PLAYING);
	} else if (device->gateway) {
		if (!gateway_is_connected(device)) {
			DBG("Refusing SCO from non-connected AG");
			goto drop;
		}

		if (gateway_connect_sco(device, chan) < 0)
			goto drop;
	} else
		goto drop;

	sk = g_io_channel_unix_get_fd(chan);
	fcntl(sk, F_SETFL, 0);

	DBG("Accepted SCO connection from %s", addr);

	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Beispiel #4
0
static void ag_confirm(GIOChannel *chan, gpointer data)
{
	const char *server_uuid, *remote_uuid;
	struct audio_device *device;
	gboolean hfp_active;
	bdaddr_t src, dst;
	int perr;
	GError *err = NULL;
	uint8_t ch;

	bt_io_get(chan, BT_IO_RFCOMM, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_CHANNEL, &ch,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		goto drop;
	}

	if (ch == DEFAULT_HS_AG_CHANNEL) {
		hfp_active = FALSE;
		server_uuid = HSP_AG_UUID;
		remote_uuid = HSP_HS_UUID;
	} else {
		hfp_active = TRUE;
		server_uuid = HFP_AG_UUID;
		remote_uuid = HFP_HS_UUID;
	}

	device = manager_get_device(&src, &dst, TRUE);
	if (!device)
		goto drop;

	if (!manager_allow_headset_connection(device)) {
		DBG("Refusing headset: too many existing connections");
		goto drop;
	}

	if (!device->headset) {
		btd_device_add_uuid(device->btd_dev, remote_uuid);
		if (!device->headset)
			goto drop;
	}

	if (headset_get_state(device) > HEADSET_STATE_DISCONNECTED) {
		DBG("Refusing new connection since one already exists");
		goto drop;
	}

	set_hfp_active(device, hfp_active);

	if (headset_connect_rfcomm(device, chan) < 0) {
		error("headset_connect_rfcomm failed");
		goto drop;
	}

	headset_set_state(device, HEADSET_STATE_CONNECTING);

	perr = audio_device_request_authorization(device, server_uuid,
						headset_auth_cb, device);
	if (perr < 0) {
		DBG("Authorization denied: %s", strerror(-perr));
		headset_set_state(device, HEADSET_STATE_DISCONNECTED);
		return;
	}

	device->hs_preauth_id = g_io_add_watch(chan,
					G_IO_NVAL | G_IO_HUP | G_IO_ERR,
					hs_preauth_cb, device);

	device->auto_connect = auto_connect;

	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}