static gint gst_avdtp_sink_bluetooth_recvmsg_fd(GstAvdtpSink *sink)
{
	int err, ret;

	ret = bt_audio_service_get_data_fd(
			g_io_channel_unix_get_fd(sink->server));

	if (ret < 0) {
		err = errno;
		GST_ERROR_OBJECT(sink, "Unable to receive fd: %s (%d)",
				strerror(err), err);
		return -err;
	}

	sink->stream = g_io_channel_unix_new(ret);
	GST_DEBUG_OBJECT(sink, "stream_fd=%d", ret);

	return 0;
}
Example #2
0
static int bluetooth_start(struct bluetooth_data *data)
{
	char c = 'w';
	char buf[BT_SUGGESTED_BUFFER_SIZE];
	struct bt_start_stream_req *start_req = (void*) buf;
	struct bt_start_stream_rsp *start_rsp = (void*) buf;
	struct bt_new_stream_ind *streamfd_ind = (void*) buf;
	int opt_name, err, bytes;

	DBG("bluetooth_start");
	data->state = A2DP_STATE_STARTING;
	/* send start */
	memset(start_req, 0, BT_SUGGESTED_BUFFER_SIZE);
	start_req->h.type = BT_REQUEST;
	start_req->h.name = BT_START_STREAM;
	start_req->h.length = sizeof(*start_req);


	err = audioservice_send(data, &start_req->h);
	if (err < 0)
		goto error;

	start_rsp->h.length = sizeof(*start_rsp);
	err = audioservice_expect(data, &start_rsp->h, BT_START_STREAM);
	if (err < 0)
		goto error;

	streamfd_ind->h.length = sizeof(*streamfd_ind);
	err = audioservice_expect(data, &streamfd_ind->h, BT_NEW_STREAM);
	if (err < 0)
		goto error;

	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
	if (data->stream.fd < 0) {
		ERR("bt_audio_service_get_data_fd failed, errno: %d", errno);
		err = -errno;
		goto error;
	}
	l2cap_set_flushable(data->stream.fd, 1);
	data->stream.events = POLLOUT;

	/* set our socket buffer to the size of PACKET_BUFFER_COUNT packets */
	bytes = data->link_mtu * PACKET_BUFFER_COUNT;
	setsockopt(data->stream.fd, SOL_SOCKET, SO_SNDBUF, &bytes,
			sizeof(bytes));

#ifdef TN_JPN_NTT_BT_SCMS-T
	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload) + data->sizeof_scms_t;
#else
	data->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
#endif
	data->frame_count = 0;
	data->samples = 0;
	data->nsamples = 0;
	data->seq_num = 0;
	data->frame_count = 0;
	data->next_write = 0;

	set_state(data, A2DP_STATE_STARTED);
	return 0;

error:
	/* close bluetooth connection to force reinit and reconfiguration */
	if (data->state == A2DP_STATE_STARTING) {
		bluetooth_close(data);
		/* notify client that thread is ready for next command */
		pthread_cond_signal(&data->client_wait);
        }
	return err;
}
static int bluetooth_prepare(snd_pcm_ioplug_t *io)
{
	struct bluetooth_data *data = io->private_data;
	char c = 'w';
	char buf[BT_SUGGESTED_BUFFER_SIZE];
	struct bt_start_stream_req *req = (void *) buf;
	struct bt_start_stream_rsp *rsp = (void *) buf;
	struct bt_new_stream_ind *ind = (void *) buf;
	uint32_t period_count = io->buffer_size / io->period_size;
	int opt_name, err;
	struct timeval t = { 0, period_count };

	DBG("Preparing with io->period_size=%lu io->buffer_size=%lu",
					io->period_size, io->buffer_size);

	data->reset = 0;

	/* As we're gonna receive messages on the server socket, we have to stop the
	   hw thread that is polling on it, if any */
	if (data->hw_thread) {
		pthread_cancel(data->hw_thread);
		pthread_join(data->hw_thread, 0);
		data->hw_thread = 0;
	}

	if (io->stream == SND_PCM_STREAM_PLAYBACK)
		/* If not null for playback, xmms doesn't display time
		 * correctly */
		data->hw_ptr = 0;
	else
		/* ALSA library is really picky on the fact hw_ptr is not null.
		 * If it is, capture won't start */
		data->hw_ptr = io->period_size;

	/* send start */
	memset(req, 0, BT_SUGGESTED_BUFFER_SIZE);
	req->h.type = BT_REQUEST;
	req->h.name = BT_START_STREAM;
	req->h.length = sizeof(*req);

	err = audioservice_send(data->server.fd, &req->h);
	if (err < 0)
		return err;

	rsp->h.length = sizeof(*rsp);
	err = audioservice_expect(data->server.fd, &rsp->h,
					BT_START_STREAM);
	if (err < 0)
		return err;

	ind->h.length = sizeof(*ind);
	err = audioservice_expect(data->server.fd, &ind->h,
					BT_NEW_STREAM);
	if (err < 0)
		return err;

	if (data->stream.fd >= 0)
		close(data->stream.fd);

	data->stream.fd = bt_audio_service_get_data_fd(data->server.fd);
	if (data->stream.fd < 0) {
		return -errno;
	}

	if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) {
		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
						SO_SNDTIMEO : SO_RCVTIMEO;

		if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t,
							sizeof(t)) < 0)
			return -errno;
	} else {
		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
						SCO_TXBUFS : SCO_RXBUFS;

		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
						sizeof(period_count)) == 0)
			return 0;

		opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
						SO_SNDBUF : SO_RCVBUF;

		if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count,
						sizeof(period_count)) == 0)
			return 0;

		/* FIXME : handle error codes */
	}

	/* wake up any client polling at us */
	if (write(data->pipefd[1], &c, 1) < 0) {
		err = -errno;
		return err;
	}

	return 0;
}