Esempio n. 1
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct avctp *session;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;
	uint16_t psm;
	struct btd_device *device;

	bt_io_get(chan, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	DBG("AVCTP: incoming connect from %s", address);

	device = btd_adapter_find_device(adapter_find(&src), &dst,
								BDADDR_BREDR);
	if (!device)
		return;

	session = avctp_get_internal(device);
	if (session == NULL)
		return;

	if (btd_device_get_service(device, AVRCP_REMOTE_UUID) == NULL)
		btd_device_add_uuid(device, AVRCP_REMOTE_UUID);

	if (btd_device_get_service(device, AVRCP_TARGET_UUID) == NULL)
		btd_device_add_uuid(device, AVRCP_TARGET_UUID);

	switch (psm) {
	case AVCTP_CONTROL_PSM:
		avctp_control_confirm(session, chan, device);
		break;
	case AVCTP_BROWSING_PSM:
		avctp_browsing_confirm(session, chan, device);
		break;
	}

	return;
}
Esempio n. 2
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct avctp *session;
	struct audio_device *dev;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;
	uint16_t psm;
	struct btd_device *device;

	bt_io_get(chan, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_PSM, &psm,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	DBG("AVCTP: incoming connect from %s", address);

	device = adapter_find_device(adapter_find(&src), &dst);
	if (!device)
		return;

	session = avctp_get_internal(device);
	if (session == NULL)
		return;

	dev = manager_get_audio_device(device, TRUE);
	if (!dev) {
		error("Unable to get audio device object for %s", address);
		goto drop;
	}

	if (dev->control == NULL) {
		btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID);
		if (dev->control == NULL)
			goto drop;
	}

	switch (psm) {
	case AVCTP_CONTROL_PSM:
		avctp_control_confirm(session, chan, dev);
		break;
	case AVCTP_BROWSING_PSM:
		avctp_browsing_confirm(session, chan, dev);
		break;
	}

	return;

drop:
	if (psm == AVCTP_CONTROL_PSM)
		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
}
Esempio n. 3
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct control *control = NULL;
	struct audio_device *dev;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;

	bt_io_get(chan, BT_IO_L2CAP, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	dev = manager_get_device(&src, &dst, TRUE);
	if (!dev) {
		error("Unable to get audio device object for %s", address);
		goto drop;
	}

	if (!dev->control) {
		btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID);
		if (!dev->control)
			goto drop;
	}

	control = dev->control;

	if (control->io) {
		error("Refusing unexpected connect from %s", address);
		goto drop;
	}

	avctp_set_state(control, AVCTP_STATE_CONNECTING);
	control->io = g_io_channel_ref(chan);

	if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
						auth_cb, dev->control) < 0)
		goto drop;

	control->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
							control_cb, control);
	return;

drop:
	if (!control || !control->io)
		g_io_channel_shutdown(chan, TRUE, NULL);
	if (control)
		avctp_set_state(control, AVCTP_STATE_DISCONNECTED);
}
Esempio n. 4
0
static void hf_io_cb(GIOChannel *chan, gpointer data)
{
	bdaddr_t src, dst;
	GError *err = NULL;
	uint8_t ch;
	const char *server_uuid, *remote_uuid;
	struct audio_device *device;
	int perr;

	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);
		return;
	}

	server_uuid = HFP_AG_UUID;
	remote_uuid = HFP_HS_UUID;

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

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

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

	if (gateway_connect_rfcomm(device, chan) < 0) {
		error("Allocating new GIOChannel failed!");
		goto drop;
	}

	perr = audio_device_request_authorization(device, server_uuid,
						gateway_auth_cb, device);
	if (perr < 0) {
		DBG("Authorization denied!");
		goto drop;
	}

	return;

drop:
	g_io_channel_shutdown(chan, TRUE, NULL);
}
Esempio n. 5
0
static void avctp_confirm_cb(GIOChannel *chan, gpointer data)
{
	struct avctp *session;
	struct audio_device *dev;
	char address[18];
	bdaddr_t src, dst;
	GError *err = NULL;

	bt_io_get(chan, BT_IO_L2CAP, &err,
			BT_IO_OPT_SOURCE_BDADDR, &src,
			BT_IO_OPT_DEST_BDADDR, &dst,
			BT_IO_OPT_DEST, address,
			BT_IO_OPT_INVALID);
	if (err) {
		error("%s", err->message);
		g_error_free(err);
		g_io_channel_shutdown(chan, TRUE, NULL);
		return;
	}

	DBG("AVCTP: incoming connect from %s", address);

	session = avctp_get_internal(&src, &dst);
	if (!session)
		goto drop;

	dev = manager_get_device(&src, &dst, FALSE);
	if (!dev) {
		dev = manager_get_device(&src, &dst, TRUE);
		if (!dev) {
			error("Unable to get audio device object for %s",
					address);
			goto drop;
		}
	}

	if (dev->control == NULL) {
		btd_device_add_uuid(dev->btd_dev, AVRCP_REMOTE_UUID);
		if (dev->control == NULL)
			goto drop;
	}

	if (session->io) {
		/* AVCTP collision fix. (Collision was found with Sony headset DR-BT30Q). */
		DBG("Canceling outgoing and accepting incoming connection from %s", address);
		avctp_disconnected(session);
	       session = avctp_get_internal(&src, &dst);
	       if (!session)
			goto drop;
	}

	avctp_set_state(session, AVCTP_STATE_CONNECTING);
	session->io = g_io_channel_ref(chan);

	if (audio_device_request_authorization(dev, AVRCP_TARGET_UUID,
						auth_cb, session) < 0)
		goto drop;

	session->io_id = g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
							session_cb, session);
	return;

drop:
	if (!session || !session->io)
		g_io_channel_shutdown(chan, TRUE, NULL);
	if (session)
		avctp_set_state(session, AVCTP_STATE_DISCONNECTED);
}
Esempio n. 6
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);
}