Пример #1
0
static void get_incoming_record_cb(sdp_list_t *recs, int err,
					gpointer user_data)
{
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	GError *gerr = NULL;

	if (err < 0) {
		error("Unable to get service record: %s (%d)", strerror(-err),
					-err);
		goto fail;
	}

	if (!recs || !recs->data) {
		error("No records found");
		goto fail;
	}

	gw->version = get_remote_profile_version(recs->data);
	if (gw->version == 0)
		goto fail;

	rfcomm_connect_cb(gw->incoming, gerr, dev);
	return;

fail:
	gateway_close(dev);
}
Пример #2
0
static void newconnection_reply(DBusPendingCall *call, void *data)
{
	struct audio_device *dev = data;
	struct gateway *gw = dev->gateway;
	struct hf_agent *agent = gw->agent;
	DBusMessage *reply = dbus_pending_call_steal_reply(call);
	DBusError derr;

	dbus_pending_call_unref(agent->call);
	agent->call = NULL;

	dbus_error_init(&derr);
	if (!dbus_set_error_from_message(&derr, reply)) {
		DBG("Agent reply: file descriptor passed successfully");
		gw->rfcomm_id = g_io_add_watch(gw->rfcomm,
						G_IO_ERR | G_IO_HUP | G_IO_NVAL,
						(GIOFunc) rfcomm_disconnect_cb,
						dev);
		change_state(dev, GATEWAY_STATE_CONNECTED);
		goto done;
	}

	DBG("Agent reply: %s", derr.message);

	dbus_error_free(&derr);
	gateway_close(dev);

done:
	dbus_message_unref(reply);
}
Пример #3
0
static void newconnection_reply(DBusPendingCall *call, void *data)
{
	struct audio_device *dev = data;
	DBusMessage *reply = dbus_pending_call_steal_reply(call);
	DBusError derr;

	if (!dev->gateway->rfcomm) {
		DBG("RFCOMM disconnected from server before agent reply");
		goto done;
	}

	dbus_error_init(&derr);
	if (!dbus_set_error_from_message(&derr, reply)) {
		DBG("Agent reply: file descriptor passed successfully");
		change_state(dev, GATEWAY_STATE_CONNECTED);
		goto done;
	}

	DBG("Agent reply: %s", derr.message);

	dbus_error_free(&derr);
	gateway_close(dev);

done:
	dbus_message_unref(reply);
}
Пример #4
0
static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
			struct audio_device *dev)
{
	if (cond & G_IO_NVAL)
		return FALSE;

	gateway_close(dev);

	return FALSE;
}
Пример #5
0
static void path_unregister(void *data)
{
	struct audio_device *dev = data;

	DBG("Unregistered interface %s on path %s",
		AUDIO_GATEWAY_INTERFACE, dev->path);

	gateway_close(dev);

	g_free(dev->gateway);
	dev->gateway = NULL;
}
Пример #6
0
void gateway_set_state(struct audio_device *dev, gateway_state_t new_state)
{
	switch (new_state) {
	case GATEWAY_STATE_DISCONNECTED:
		gateway_close(dev);
		break;
	case GATEWAY_STATE_CONNECTING:
	case GATEWAY_STATE_CONNECTED:
	case GATEWAY_STATE_PLAYING:
		break;
	}
}
Пример #7
0
void gateway_start_service(struct audio_device *dev)
{
	struct gateway *gw = dev->gateway;
	GError *err = NULL;

	if (gw->rfcomm == NULL)
		return;

	if (!bt_io_accept(gw->rfcomm, rfcomm_incoming_cb, dev, NULL, &err)) {
		error("bt_io_accept: %s", err->message);
		g_error_free(err);
		gateway_close(dev);
	}
}
Пример #8
0
static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
				gpointer user_data)
{
	DBusConnection *conn = btd_get_dbus_connection();
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	DBusMessage *reply;
	int sk, ret;

	if (err) {
		error("connect(): %s", err->message);
		goto fail;
	}

	if (!gw->agent) {
		error("Handsfree Agent not registered");
		goto fail;
	}

	sk = g_io_channel_unix_get_fd(chan);

	if (gw->rfcomm == NULL)
		gw->rfcomm = g_io_channel_ref(chan);

	ret = agent_sendfd(gw->agent, sk, newconnection_reply, dev);

	if (!gw->msg)
		return;

	if (ret)
		reply = dbus_message_new_method_return(gw->msg);
	else
		reply = btd_error_failed(gw->msg, "Can't pass file descriptor");

	g_dbus_send_message(conn, reply);

	return;

fail:
	if (gw->msg) {
		DBusMessage *reply;
		reply = btd_error_failed(gw->msg, "Connect failed");
		g_dbus_send_message(conn, reply);
	}

	gateway_close(dev);
}
Пример #9
0
static void rfcomm_incoming_cb(GIOChannel *chan, GError *err,
				gpointer user_data)
{
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	uuid_t uuid;

	gw->incoming = g_io_channel_ref(chan);

	sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
	if (bt_search_service(&dev->src, &dev->dst, &uuid,
						get_incoming_record_cb, dev,
						unregister_incoming) == 0)
		return;

	unregister_incoming(dev);
	gateway_close(dev);
}
Пример #10
0
static DBusMessage *ag_disconnect(DBusConnection *conn, DBusMessage *msg,
					void *data)
{
	struct audio_device *device = data;
	struct gateway *gw = device->gateway;
	DBusMessage *reply = NULL;
	char gw_addr[18];

	if (!gw->rfcomm)
		return btd_error_not_connected(msg);

	reply = dbus_message_new_method_return(msg);
	if (!reply)
		return NULL;

	gateway_close(device);
	ba2str(&device->dst, gw_addr);
	DBG("Disconnected from %s, %s", gw_addr, device->path);

	return reply;
}
Пример #11
0
static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
{
	struct audio_device *dev = (struct audio_device *) user_data;
	struct gateway *gw = dev->gateway;

	DBG("at the begin of sco_connect_cb() in gateway.c");

	gw->sco = g_io_channel_ref(chan);

	if (gw->sco_start_cb)
		gw->sco_start_cb(dev, err, gw->sco_start_cb_data);

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

	g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
				(GIOFunc) sco_io_cb, dev);
}
Пример #12
0
static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
{
	struct audio_device *dev = user_data;
	struct gateway *gw = dev->gateway;
	int ch;
	sdp_list_t *protos, *classes;
	uuid_t uuid;
	GIOChannel *io;
	GError *gerr = NULL;

	if (err < 0) {
		error("Unable to get service record: %s (%d)", strerror(-err),
					-err);
		goto fail;
	}

	if (!recs || !recs->data) {
		error("No records found");
		err = -EIO;
		goto fail;
	}

	if (sdp_get_service_classes(recs->data, &classes) < 0) {
		error("Unable to get service classes from record");
		err = -EINVAL;
		goto fail;
	}

	if (sdp_get_access_protos(recs->data, &protos) < 0) {
		error("Unable to get access protocols from record");
		err = -ENODATA;
		goto fail;
	}

	gw->version = get_remote_profile_version(recs->data);
	if (gw->version == 0) {
		error("Unable to get profile version from record");
		err = -EINVAL;
		goto fail;
	}

	memcpy(&uuid, classes->data, sizeof(uuid));
	sdp_list_free(classes, free);

	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
			uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
		sdp_list_free(protos, NULL);
		error("Invalid service record or not HFP");
		err = -EIO;
		goto fail;
	}

	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
	sdp_list_free(protos, NULL);
	if (ch <= 0) {
		error("Unable to extract RFCOMM channel from service record");
		err = -EIO;
		goto fail;
	}

	io = bt_io_connect(rfcomm_connect_cb, dev, NULL, &gerr,
				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
				BT_IO_OPT_DEST_BDADDR, &dev->dst,
				BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
				BT_IO_OPT_CHANNEL, ch,
				BT_IO_OPT_INVALID);
	if (!io) {
		error("Unable to connect: %s", gerr->message);
		goto fail;
	}

	g_io_channel_unref(io);
	return;

fail:
	if (gw->msg) {
		DBusMessage *reply = btd_error_failed(gw->msg,
					gerr ? gerr->message : strerror(-err));
		g_dbus_send_message(btd_get_dbus_connection(), reply);
	}

	gateway_close(dev);

	if (gerr)
		g_error_free(gerr);
}
Пример #13
0
gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
{
	gateway_close(dev);
	return TRUE;
}