示例#1
0
static void device_sink_cb(struct audio_device *dev,
				sink_state_t old_state,
				sink_state_t new_state,
				void *user_data)
{
	struct dev_priv *priv = dev->priv;

	if (!dev->sink)
		return;

	priv->sink_state = new_state;

	switch (new_state) {
	case SINK_STATE_DISCONNECTED:
		if (dev->control) {
			device_remove_control_timer(dev);
			avrcp_disconnect(dev);
		}

		device_set_state(dev, AUDIO_STATE_DISCONNECTED);
		break;
	case SINK_STATE_CONNECTING:
		device_remove_avdtp_timer(dev);
		device_set_state(dev, AUDIO_STATE_CONNECTING);
		break;
	case SINK_STATE_CONNECTED:
		if (old_state == SINK_STATE_PLAYING)
			break;
		device_set_state(dev, AUDIO_STATE_CONNECTED);
		break;
	case SINK_STATE_PLAYING:
		break;
	}
}
static DBusMessage *dev_disconnect(DBusConnection *conn, DBusMessage *msg,
								void *data)
{
	struct audio_device *dev = data;
	struct dev_priv *priv = dev->priv;

	if (priv->state == AUDIO_STATE_DISCONNECTED)
		return g_dbus_create_error(msg, ERROR_INTERFACE ".NotConnected",
						"Not connected");

	if (priv->dc_req)
		return dbus_message_new_method_return(msg);

	priv->dc_req = dbus_message_ref(msg);

	if (dev->control) {
		device_remove_control_timer(dev);
		avrcp_disconnect(dev);
	}

	if (dev->sink && priv->sink_state != SINK_STATE_DISCONNECTED)
		sink_shutdown(dev->sink);
	else if (priv->hs_state != HEADSET_STATE_DISCONNECTED)
		headset_shutdown(dev);
	else {
		dbus_message_unref(priv->dc_req);
		priv->dc_req = NULL;
		return dbus_message_new_method_return(msg);
	}

	return NULL;
}
示例#3
0
static void disconnect_cb(struct btd_device *btd_dev, gboolean removal,
				void *user_data)
{
	struct audio_device *dev = user_data;
	struct dev_priv *priv = dev->priv;

	if (priv->state == AUDIO_STATE_DISCONNECTED)
		return;

	if (priv->disconnecting)
		return;

	priv->disconnecting = TRUE;

	device_remove_control_timer(dev);
	device_remove_avdtp_timer(dev);

	if (dev->control)
		avrcp_disconnect(dev);

	if (dev->sink && priv->sink_state != SINK_STATE_DISCONNECTED)
		sink_disconnect(dev, TRUE);
	else
		priv->disconnecting = FALSE;
}
示例#4
0
gboolean avrcp_connect(struct audio_device *dev)
{
	struct control *control = dev->control;
	struct avctp *session;
	int err;

	if (control->session)
		return TRUE;

	session = avctp_get(&dev->src, &dev->dst);
	if (!session) {
		error("Unable to create new AVCTP session");
		return FALSE;
	}

	device_remove_control_timer(dev);

	session->dev = dev;
	session->state = AVCTP_STATE_CONNECTING;

	err = bt_l2cap_connect(&dev->src, &dev->dst, AVCTP_PSM, 0,
				avctp_connect_cb, session);
	if (err < 0) {
		avctp_unref(session);
		error("Connect failed. %s(%d)", strerror(-err), -err);
		return FALSE;
	}

	control->session = session;

	return TRUE;
}
示例#5
0
static void device_sink_cb(struct audio_device *dev,
				sink_state_t old_state,
				sink_state_t new_state,
				void *user_data)
{
	struct dev_priv *priv = dev->priv;

	if (!dev->sink)
		return;

	priv->sink_state = new_state;

	switch (new_state) {
	case SINK_STATE_DISCONNECTED:
		if (dev->control) {
			device_remove_control_timer(dev);
			avrcp_disconnect(dev);
		}
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_DISCONNECTED);
		else if (old_state == SINK_STATE_CONNECTING) {
			switch (priv->hs_state) {
			case HEADSET_STATE_CONNECTED:
			case HEADSET_STATE_PLAY_IN_PROGRESS:
			case HEADSET_STATE_PLAYING:
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			default:
				break;
			}
		}
		break;
	case SINK_STATE_CONNECTING:
		device_remove_avdtp_timer(dev);
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_CONNECTING);
		break;
	case SINK_STATE_CONNECTED:
		if (old_state == SINK_STATE_PLAYING)
			break;
#ifdef ANDROID
/* google code, Broadcom Bluetooth Feature
		android_set_high_priority(&dev->dst);
*/
#endif
		if (dev->auto_connect) {
			if (!dev->headset)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
				device_set_headset_timer(dev);
			else if (priv->hs_state == HEADSET_STATE_CONNECTED)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
		} else if (priv->hs_state != HEADSET_STATE_CONNECTED)
			device_set_state(dev, AUDIO_STATE_CONNECTED);
		break;
	case SINK_STATE_PLAYING:
		break;
	}
}
示例#6
0
static void device_sink_cb(struct audio_device *dev,
				sink_state_t old_state,
				sink_state_t new_state,
				void *user_data)
{
	struct dev_priv *priv = dev->priv;

	if (!dev->sink)
		return;

	priv->sink_state = new_state;

	switch (new_state) {
	case SINK_STATE_DISCONNECTED:
		if (dev->control) {
			device_remove_control_timer(dev);
			avrcp_disconnect(dev);
		}
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_DISCONNECTED);
		else if (old_state == SINK_STATE_CONNECTING) {
			switch (priv->hs_state) {
			case HEADSET_STATE_CONNECTED:
			case HEADSET_STATE_PLAY_IN_PROGRESS:
			case HEADSET_STATE_PLAYING:
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			default:
				break;
			}
		}
		break;
	case SINK_STATE_CONNECTING:
		device_remove_avdtp_timer(dev);
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_CONNECTING);
		break;
	case SINK_STATE_CONNECTED:
		if (old_state == SINK_STATE_PLAYING)
			break;
		if (dev->auto_connect) {
			if (!dev->headset)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			else if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
				device_set_headset_timer(dev);
			else if (priv->hs_state == HEADSET_STATE_CONNECTED ||
					priv->hs_state == HEADSET_STATE_PLAY_IN_PROGRESS ||
					priv->hs_state == HEADSET_STATE_PLAYING)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
		} else if (priv->hs_state == HEADSET_STATE_DISCONNECTED ||
				priv->hs_state == HEADSET_STATE_CONNECTING)
			device_set_state(dev, AUDIO_STATE_CONNECTED);
		break;
	case SINK_STATE_PLAYING:
		break;
	}
}
static void device_avctp_cb(struct audio_device *dev,
				avctp_state_t old_state,
				avctp_state_t new_state,
				void *user_data)
{
	if (!dev->control)
		return;

	dev->priv->avctp_state = new_state;

	switch (new_state) {
	case AVCTP_STATE_DISCONNECTED:
		break;
	case AVCTP_STATE_CONNECTING:
		device_remove_control_timer(dev);
		break;
	case AVCTP_STATE_CONNECTED:
		break;
	}
}
static void device_sink_cb(struct audio_device *dev,
				sink_state_t old_state,
				sink_state_t new_state,
				void *user_data)
{
	struct dev_priv *priv = dev->priv;

	if (!dev->sink)
		return;

	priv->sink_state = new_state;

	switch (new_state) {
	case SINK_STATE_DISCONNECTED:
		if (dev->control) {
			device_remove_control_timer(dev);
			avrcp_disconnect(dev);
		}
		if (priv->hs_state != HEADSET_STATE_DISCONNECTED &&
								priv->dc_req) {
			headset_shutdown(dev);
			break;
		}
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_DISCONNECTED);
		else if (old_state == SINK_STATE_CONNECTING) {
			switch (priv->hs_state) {
			case HEADSET_STATE_CONNECTED:
			case HEADSET_STATE_PLAY_IN_PROGRESS:
			case HEADSET_STATE_PLAYING:
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			default:
				break;
			}
		}
		break;
	case SINK_STATE_CONNECTING:
		device_remove_avdtp_timer(dev);
		if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
			device_set_state(dev, AUDIO_STATE_CONNECTING);
		break;
	case SINK_STATE_CONNECTED:
		if (old_state == SINK_STATE_PLAYING)
			break;
#ifdef ANDROID
		android_set_high_priority(&dev->dst);
#endif
		if (dev->auto_connect) {
			if (!dev->headset)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
			else if (priv->hs_state == HEADSET_STATE_DISCONNECTED)
				device_set_headset_timer(dev);
			else if (priv->hs_state == HEADSET_STATE_CONNECTED ||
					priv->hs_state == HEADSET_STATE_PLAY_IN_PROGRESS ||
					priv->hs_state == HEADSET_STATE_PLAYING)
				device_set_state(dev, AUDIO_STATE_CONNECTED);
		} else if (priv->hs_state == HEADSET_STATE_DISCONNECTED ||
				priv->hs_state == HEADSET_STATE_CONNECTING)
			device_set_state(dev, AUDIO_STATE_CONNECTED);
		break;
	case SINK_STATE_PLAYING:
//Terry Cheng, 20101222, force to send high priority when playing +
#ifdef ANDROID
		//Re-send high priority when playing A2DP. It may not work when only connecting A2DP profile
		android_set_high_priority(&dev->dst);
#endif		
//Terry Cheng, 20101222, force to send high priority when playing -
		break;
	}
}
示例#9
0
static void avctp_server_cb(GIOChannel *chan, int err, const bdaddr_t *src,
				const bdaddr_t *dst, gpointer data)
{
	socklen_t size;
	struct l2cap_options l2o;
	struct avctp *session;
	GIOCondition flags = G_IO_ERR | G_IO_HUP | G_IO_NVAL;
	struct audio_device *dev;
	char address[18];

	if (err < 0) {
		error("AVCTP server socket: %s (%d)", strerror(-err), -err);
		return;
	}

	session = avctp_get(src, dst);

	if (!session) {
		error("Unable to create new AVCTP session");
		goto drop;
	}

	if (session->sock >= 0) {
		error("Refusing unexpected connect from %s", address);
		goto drop;
	}

	dev = manager_find_device(&session->dst, AUDIO_CONTROL_INTERFACE, FALSE);

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

	if (!dev->control)
		dev->control = control_init(dev);

	device_remove_control_timer(dev);

	session->state = AVCTP_STATE_CONNECTING;
	session->sock = g_io_channel_unix_get_fd(chan);

	memset(&l2o, 0, sizeof(l2o));
	size = sizeof(l2o);
	if (getsockopt(session->sock, SOL_L2CAP, L2CAP_OPTIONS, &l2o, &size) < 0) {
		err = errno;
		error("getsockopt(L2CAP_OPTIONS): %s (%d)", strerror(err),
				err);
		avctp_unref(session);
		goto drop;
	}

	session->mtu = l2o.imtu;

	if (session->io)
		g_source_remove(session->io);
	session->io = g_io_add_watch(chan, flags, (GIOFunc) session_cb,
				session);
	g_io_channel_unref(chan);

	if (avdtp_is_connected(src, dst))
		goto proceed;

	if (service_req_auth(src, dst, AVRCP_TARGET_UUID, auth_cb, session) < 0)
		goto drop;

	return;

proceed:
	avctp_connect_session(session);

	return;

drop:
	close(session->sock);
}