Beispiel #1
0
static void device_set_state(struct audio_device *dev, audio_state_t new_state)
{
	struct dev_priv *priv = dev->priv;
	const char *state_str;

	state_str = state2str(new_state);
	if (!state_str)
		return;

	if (new_state == AUDIO_STATE_DISCONNECTED) {
		if (priv->dc_id) {
			device_remove_disconnect_watch(dev->btd_dev,
							priv->dc_id);
			priv->dc_id = 0;
		}
	} else if (new_state == AUDIO_STATE_CONNECTING)
		priv->dc_id = device_add_disconnect_watch(dev->btd_dev,
						disconnect_cb, dev, NULL);

	if (dev->priv->state == new_state) {
		DBG("state change attempted from %s to %s",
							state_str, state_str);
		return;
	}

	dev->priv->state = new_state;

	if (new_state == AUDIO_STATE_DISCONNECTED)
		priv->disconnecting = FALSE;
}
Beispiel #2
0
static int input_device_connected(struct input_device *idev,
						struct input_conn *iconn)
{
	dbus_bool_t connected;
	int err;

	if (iconn->intr_io == NULL || iconn->ctrl_io == NULL)
		return -ENOTCONN;

	err = hidp_add_connection(idev, iconn);
	if (err < 0)
		return err;

	iconn->intr_watch = g_io_add_watch(iconn->intr_io,
					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
					intr_watch_cb, iconn);
	iconn->ctrl_watch = g_io_add_watch(iconn->ctrl_io,
					G_IO_HUP | G_IO_ERR | G_IO_NVAL,
					ctrl_watch_cb, iconn);

	connected = TRUE;
	emit_property_changed(idev->conn, idev->path, INPUT_DEVICE_INTERFACE,
				"Connected", DBUS_TYPE_BOOLEAN, &connected);

	idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
							idev, NULL);

	return 0;
}
Beispiel #3
0
static void stream_state_changed(struct avdtp_stream *stream,
					avdtp_state_t old_state,
					avdtp_state_t new_state,
					struct avdtp_error *err,
					void *user_data)
{
	struct audio_device *dev = user_data;
	struct source *source = dev->source;

	if (err)
		return;

	switch (new_state) {
	case AVDTP_STATE_IDLE:
		if (source->disconnect) {
			DBusMessage *reply;
			struct pending_request *p;

			p = source->disconnect;
			source->disconnect = NULL;

			reply = dbus_message_new_method_return(p->msg);
			g_dbus_send_message(p->conn, reply);
			pending_request_free(dev, p);
		}

		if (source->dc_id) {
			device_remove_disconnect_watch(dev->btd_dev,
							source->dc_id);
			source->dc_id = 0;
		}

		if (source->session) {
			avdtp_unref(source->session);
			source->session = NULL;
		}
		source->stream = NULL;
		source->cb_id = 0;
		break;
	case AVDTP_STATE_OPEN:
		if (old_state == AVDTP_STATE_CONFIGURED &&
				source->state == SOURCE_STATE_CONNECTING) {
			source->dc_id = device_add_disconnect_watch(dev->btd_dev,
								disconnect_cb,
								dev, NULL);
		}
		source_set_state(dev, SOURCE_STATE_CONNECTED);
		break;
	case AVDTP_STATE_STREAMING:
		source_set_state(dev, SOURCE_STATE_PLAYING);
		break;
	case AVDTP_STATE_CONFIGURED:
	case AVDTP_STATE_CLOSING:
	case AVDTP_STATE_ABORTING:
	default:
		break;
	}

	source->stream_state = new_state;
}
static void device_set_state(struct audio_device *dev, audio_state_t new_state)
{
	struct dev_priv *priv = dev->priv;
	const char *state_str;
	DBusMessage *reply = NULL;

	state_str = state2str(new_state);
	if (!state_str)
		return;

	if (new_state == AUDIO_STATE_DISCONNECTED) {
		priv->authorized = FALSE;

		if (priv->dc_id) {
			device_remove_disconnect_watch(dev->btd_dev,
							priv->dc_id);
			priv->dc_id = 0;
		}
	} else if (new_state == AUDIO_STATE_CONNECTING)
		priv->dc_id = device_add_disconnect_watch(dev->btd_dev,
						disconnect_cb, dev, NULL);

	if (dev->priv->state == new_state) {
		DBG("state change attempted from %s to %s",
							state_str, state_str);
		return;
	}

	dev->priv->state = new_state;

	if (new_state == AUDIO_STATE_DISCONNECTED) {
		if (priv->dc_req) {
			reply = dbus_message_new_method_return(priv->dc_req);
			dbus_message_unref(priv->dc_req);
			priv->dc_req = NULL;
			g_dbus_send_message(dev->conn, reply);
		}
		priv->disconnecting = FALSE;
	}

	if (priv->conn_req && new_state != AUDIO_STATE_CONNECTING) {
		if (new_state == AUDIO_STATE_CONNECTED)
			reply = dbus_message_new_method_return(priv->conn_req);
		else
			reply = btd_error_failed(priv->conn_req,
							"Connect Failed");

		dbus_message_unref(priv->conn_req);
		priv->conn_req = NULL;
		g_dbus_send_message(dev->conn, reply);
	}

	emit_property_changed(dev->conn, dev->path,
				AUDIO_INTERFACE, "State",
				DBUS_TYPE_STRING, &state_str);
}
Beispiel #5
0
static int input_device_connected(struct input_device *idev)
{
    int err;

    if (idev->intr_io == NULL || idev->ctrl_io == NULL)
        return -ENOTCONN;

    err = hidp_add_connection(idev);
    if (err < 0)
        return err;

    idev->dc_id = device_add_disconnect_watch(idev->device, disconnect_cb,
                  idev, NULL);

    btd_service_connecting_complete(idev->service, 0);

    return 0;
}
Beispiel #6
0
static void bnep_conn_cb(GIOChannel *chan, char *iface, int err, void *data)
{
	struct network_conn *nc = data;
	const char *path;
	DBusConnection *conn;

	DBG("");

	if (err < 0) {
		error("connect failed %s", strerror(-err));
		goto failed;
	}

	info("%s connected", nc->dev);

	memcpy(nc->dev, iface, sizeof(nc->dev));
	btd_service_connecting_complete(nc->service, 0);

	if (nc->connect)
		local_connect_cb(nc, 0);

	conn = btd_get_dbus_connection();
	path = device_get_path(nc->peer->device);

	g_dbus_emit_property_changed(conn, path,
					NETWORK_PEER_INTERFACE, "Connected");
	g_dbus_emit_property_changed(conn, path,
					NETWORK_PEER_INTERFACE, "Interface");
	g_dbus_emit_property_changed(conn, path,
					NETWORK_PEER_INTERFACE, "UUID");

	nc->state = CONNECTED;
	nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
								nc, NULL);
	g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
							bnep_watchdog_cb, nc);
	g_io_channel_unref(nc->io);
	nc->io = NULL;

	return;

failed:
	cancel_connection(nc, -EIO);
}
Beispiel #7
0
static void stream_state_changed(struct avdtp_stream *stream,
					avdtp_state_t old_state,
					avdtp_state_t new_state,
					struct avdtp_error *err,
					void *user_data)
{
	struct audio_device *dev = user_data;
	struct sink *sink = dev->sink;
	gboolean value;

	if (err)
		return;

	switch (new_state) {
	case AVDTP_STATE_IDLE:
		if (sink->disconnect) {
			DBusMessage *reply;
			struct pending_request *p;

			p = sink->disconnect;
			sink->disconnect = NULL;

			reply = dbus_message_new_method_return(p->msg);
			g_dbus_send_message(p->conn, reply);
			pending_request_free(dev, p);
		}

		if (sink->dc_id) {
			device_remove_disconnect_watch(dev->btd_dev,
							sink->dc_id);
			sink->dc_id = 0;
		}

		if (sink->session) {
			avdtp_unref(sink->session);
			sink->session = NULL;
		}
		sink->stream = NULL;
		sink->cb_id = 0;
		break;
	case AVDTP_STATE_OPEN:
		if (old_state == AVDTP_STATE_CONFIGURED &&
				sink->state == SINK_STATE_CONNECTING) {
			value = TRUE;
			g_dbus_emit_signal(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Connected",
						DBUS_TYPE_INVALID);
			emit_property_changed(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Connected",
						DBUS_TYPE_BOOLEAN, &value);
			sink->dc_id = device_add_disconnect_watch(dev->btd_dev,
								disconnect_cb,
								dev, NULL);
		} else if (old_state == AVDTP_STATE_STREAMING) {
			value = FALSE;
			g_dbus_emit_signal(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Stopped",
						DBUS_TYPE_INVALID);
			emit_property_changed(dev->conn, dev->path,
						AUDIO_SINK_INTERFACE,
						"Playing",
						DBUS_TYPE_BOOLEAN, &value);
		}
		sink_set_state(dev, SINK_STATE_CONNECTED);
		break;
	case AVDTP_STATE_STREAMING:
		value = TRUE;
		g_dbus_emit_signal(dev->conn, dev->path, AUDIO_SINK_INTERFACE,
					"Playing", DBUS_TYPE_INVALID);
		emit_property_changed(dev->conn, dev->path,
					AUDIO_SINK_INTERFACE, "Playing",
					DBUS_TYPE_BOOLEAN, &value);
		sink_set_state(dev, SINK_STATE_PLAYING);
		break;
	case AVDTP_STATE_CONFIGURED:
	case AVDTP_STATE_CLOSING:
	case AVDTP_STATE_ABORTING:
	default:
		break;
	}

	sink->stream_state = new_state;
}
Beispiel #8
0
static gboolean bnep_setup_cb(GIOChannel *chan, GIOCondition cond,
							gpointer data)
{
	struct network_conn *nc = data;
	struct bnep_control_rsp *rsp;
	struct timeval timeo;
	char pkt[BNEP_MTU];
	ssize_t r;
	int sk;
	const char *pdev, *uuid;
	gboolean connected;

	if (cond & G_IO_NVAL)
		return FALSE;

	g_source_remove(nc->timeout_source);
	nc->timeout_source = 0;

	if (cond & (G_IO_HUP | G_IO_ERR)) {
		error("Hangup or error on l2cap server socket");
		goto failed;
	}

	sk = g_io_channel_unix_get_fd(chan);

	memset(pkt, 0, BNEP_MTU);
	r = read(sk, pkt, sizeof(pkt) -1);
	if (r < 0) {
		error("IO Channel read error");
		goto failed;
	}

	if (r == 0) {
		error("No packet received on l2cap socket");
		goto failed;
	}

	errno = EPROTO;

	if ((size_t) r < sizeof(*rsp)) {
		error("Packet received is not bnep type");
		goto failed;
	}

	rsp = (void *) pkt;
	if (rsp->type != BNEP_CONTROL) {
		error("Packet received is not bnep type");
		goto failed;
	}

	if (rsp->ctrl != BNEP_SETUP_CONN_RSP)
		return TRUE;

	r = ntohs(rsp->resp);

	if (r != BNEP_SUCCESS) {
		error("bnep failed");
		goto failed;
	}

	memset(&timeo, 0, sizeof(timeo));
	timeo.tv_sec = 0;

	setsockopt(sk, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo));

	if (bnep_connadd(sk, BNEP_SVC_PANU, nc->dev)) {
		error("%s could not be added", nc->dev);
		goto failed;
	}

	bnep_if_up(nc->dev);
	pdev = nc->dev;
	uuid = bnep_uuid(nc->id);

	g_dbus_send_reply(connection, nc->msg,
			DBUS_TYPE_STRING, &pdev,
			DBUS_TYPE_INVALID);

	connected = TRUE;
	emit_property_changed(connection, nc->peer->path,
				NETWORK_PEER_INTERFACE, "Connected",
				DBUS_TYPE_BOOLEAN, &connected);
	emit_property_changed(connection, nc->peer->path,
				NETWORK_PEER_INTERFACE, "Interface",
				DBUS_TYPE_STRING, &pdev);
	emit_property_changed(connection, nc->peer->path,
				NETWORK_PEER_INTERFACE, "UUID",
				DBUS_TYPE_STRING, &uuid);

	nc->state = CONNECTED;
	nc->dc_id = device_add_disconnect_watch(nc->peer->device, disconnect_cb,
						nc, NULL);

	info("%s connected", nc->dev);
	/* Start watchdog */
	g_io_add_watch(chan, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
			(GIOFunc) bnep_watchdog_cb, nc);
	g_io_channel_unref(nc->io);
	nc->io = NULL;

	return FALSE;

failed:
	cancel_connection(nc, "bnep setup failed");

	return FALSE;
}