pcm_bluetooth.c revision afc2f9e31b18b2572e90902c86d6b75368e1e9c6
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/*
2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  BlueZ - Bluetooth protocol stack for Linux
4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
5e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
6e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
7e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
8e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  This library is free software; you can redistribute it and/or
9e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  modify it under the terms of the GNU Lesser General Public
10e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  License as published by the Free Software Foundation; either
11e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  version 2.1 of the License, or (at your option) any later version.
12e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
13e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  This library is distributed in the hope that it will be useful,
14e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Lesser General Public License for more details.
17e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
18e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  You should have received a copy of the GNU Lesser General Public
19e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  License along with this library; if not, write to the Free Software
20e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann *
22e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann */
23e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann
24e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#ifdef HAVE_CONFIG_H
25e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#include <config.h>
26e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#endif
275ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
28b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/socket.h>
29b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/un.h>
306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <sys/time.h>
316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h>
33b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
345ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h>
355ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h>
365ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/bluetooth.h>
388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/sco.h>
398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
40b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h"
416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h"
426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
436e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann//#define ENABLE_DEBUG
446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#define BUFFER_SIZE 1024
46b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
47f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG
48b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...)  printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg)
49f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else
50f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...)
51f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif
52b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS
548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03
558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS
588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04
598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif
608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct rtp_header {
626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t cc:4;
636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t x:1;
646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t p:1;
656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t v:2;
666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t pt:7;
686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t m:1;
696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t sequence_number;
716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint32_t timestamp;
726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint32_t ssrc;
736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint32_t csrc[0];
746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} __attribute__ ((packed));
756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct rtp_payload {
776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t frame_count:4;
786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t rfa0:1;
796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t is_last_fragment:1;
806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t is_first_fragment:1;
816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t is_fragmented:1;
826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} __attribute__ ((packed));
836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp {
856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_t sbc;			/* Codec data */
866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int samples;			/* Number of encoded samples */
876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	time_t timestamp;		/* Codec samples timestamp */
886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t buffer[BUFFER_SIZE];	/* Codec transfer buffer */
896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int count;			/* Codec transfer buffer counter */
906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int nsamples;			/* Cumulative number of codec samples */
926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct timeval ntimestamp;	/* Cumulative timeval */
936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t seq_num;		/* */
946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int frame_count;		/* */
956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int bandwithcount;
976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct timeval bandwithtimestamp;
986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
100b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data {
101b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_ioplug_t io;
102b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_sframes_t hw_ptr;
1038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct ipc_data_cfg cfg;	/* Bluetooth device config */
1049494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	int stream_fd;			/* Audio stream filedescriptor */
1058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int sock;			/* Daemon unix socket */
1066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t buffer[BUFFER_SIZE];	/* Encoded transfer buffer */
1076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int count;			/* Transfer buffer counter */
1086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp a2dp;	/* a2dp data */
109b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
110b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergvoid memcpy_changeendian(void *dst, const void *src, int size)
1126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
1136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int i;
1146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	const uint16_t *ptrsrc = src;
1156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint16_t *ptrdst = dst;
1166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	for (i = 0; i < size / 2; i++) {
1176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		*ptrdst++ = htons(*ptrsrc++);
1186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
1196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
1206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
121b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io)
122b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1239217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_start %p", io);
124b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
125b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
126b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io)
129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
1309217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	DBG("bluetooth_stop %p", io);
131b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
132b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
133b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
134b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
135b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io)
136b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
137b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
138b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#if 0
1406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("bluetooth_pointer %p, hw_ptr=%lu", io, data->hw_ptr);
1416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
142b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
143b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return data->hw_ptr;
144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1465ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data)
1475ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{
1485ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	if (data->sock >= 0)
1495ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz		close(data->sock);
1505ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
1519494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	if (data->stream_fd >= 0)
1529494c146cec1df466c2f331957748beeac8d745aJohan Hedberg		close(data->stream_fd);
1532a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz
1545ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	free(data);
1555ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz}
1565ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz
157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io)
158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	struct bluetooth_data *data = io->private_data;
160b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("%p", io);
162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1635ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
164b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
165b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
166b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
167b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
1688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io)
1698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
17200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Preparing with io->period_size = %lu, io->buffer_size = %lu",
17300c71248e732de0230c12df4240087a6b2747179Johan Hedberg			io->period_size, io->buffer_size);
1748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1759217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	if (io->stream == SND_PCM_STREAM_PLAYBACK)
17600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* If not null for playback, xmms doesn't display time
17700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * correctly */
1788742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = 0;
1799217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg	else
18000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* ALSA library is really picky on the fact hw_ptr is not null.
18100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		 * If it is, capture won't start */
1828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		data->hw_ptr = io->period_size;
1839217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
1848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return 0;
1858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
1868742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
187afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io,
188afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
1898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
1908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
1918742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
192c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	int opt_name, err;
1939217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
1946e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann	DBG("fd = %d, period_count = %d", data->stream_fd, period_count);
195ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
19600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
19700c71248e732de0230c12df4240087a6b2747179Johan Hedberg			SCO_TXBUFS : SCO_RXBUFS;
1988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
1999494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count,
2009217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg			sizeof(period_count)) == 0)
2018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		return 0;
2029217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg
20300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
2046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			SO_SNDBUF : SO_RCVBUF;
20500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
2069494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count,
20700c71248e732de0230c12df4240087a6b2747179Johan Hedberg			sizeof(period_count)) == 0)
2089217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg		return 0;
20900c71248e732de0230c12df4240087a6b2747179Johan Hedberg
210c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = errno;
211c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	SNDERR("%s (%d)", strerror(err), err);
2126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	bluetooth_close(io);
21300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
214c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	return -err;
2158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
2168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
217afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io,
218afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz					snd_pcm_hw_params_t *params)
219afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{
220afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
221afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	uint32_t period_count = io->buffer_size / io->period_size;
222afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	int opt_name, err;
223afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	struct timeval t = { 0, period_count };
224afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
225afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	DBG("fd = %d, period_count = %d", data->stream_fd, period_count);
226afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
227afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ?
228afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz			SO_SNDTIMEO : SO_RCVTIMEO;
229afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
230afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	if (setsockopt(data->stream_fd, SOL_SOCKET, opt_name, &t,
231afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz			sizeof(t)) == 0)
232afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz		return 0;
233afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
234afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	err = errno;
235afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	SNDERR("%s (%d)", strerror(err), err);
236afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	bluetooth_close(io);
237afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
238afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	return -err;
239afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz}
240afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz
2416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io,
2426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						const snd_pcm_channel_area_t *areas,
2436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t offset,
2446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t size)
2458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
2468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
2478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct ipc_data_cfg cfg = data->cfg;
24800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	snd_pcm_uframes_t frames_to_write, ret;
24900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	unsigned char *buff;
250f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int nrecv, frame_size = 0;
2518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
2526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu,"
2536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		"io->nonblock=%u", areas->step, areas->first, offset, size,
2546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		io->nonblock);
2558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
25600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (data->count > 0)
25700c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto proceed;
25800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
259f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
260f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz
2619494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	nrecv = recv(data->stream_fd, data->buffer, cfg.pkt_len,
26200c71248e732de0230c12df4240087a6b2747179Johan Hedberg			MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0));
26300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
26400c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv < 0) {
26500c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
26600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
2678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
26800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
26900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (nrecv != cfg.pkt_len) {
27000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
27100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR(strerror(-ret));
27200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
2738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
2748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
27500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Increment hardware transmition pointer */
2766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) %
2776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			io->buffer_size;
27800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
27900c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed:
2806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (unsigned char *) areas->addr +
2816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
28200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
2832a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	if ((data->count + size * frame_size) <= cfg.pkt_len)
28400c71248e732de0230c12df4240087a6b2747179Johan Hedberg		frames_to_write = size;
28500c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
286f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz		frames_to_write = (cfg.pkt_len - data->count) / frame_size;
28700c71248e732de0230c12df4240087a6b2747179Johan Hedberg
288f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(buff, data->buffer + data->count, frame_size * frames_to_write);
289f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	data->count += (frame_size * frames_to_write);
29000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->count %= cfg.pkt_len;
29100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
29200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	/* Return written frames count */
29300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	ret = frames_to_write;
29400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
29500c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
29600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("returning %lu", ret);
2978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
2988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
2998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
3006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io,
3016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						const snd_pcm_channel_area_t *areas,
3026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t offset,
3036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t size)
3048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
3058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
3068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	struct ipc_data_cfg cfg = data->cfg;
3078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_sframes_t ret = 0;
3088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	snd_pcm_uframes_t frames_to_read;
309c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	uint8_t *buff;
310f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	int rsend, frame_size;
3118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
31200c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu,"
31300c71248e732de0230c12df4240087a6b2747179Johan Hedberg			"io->nonblock=%u", areas->step, areas->first,
31400c71248e732de0230c12df4240087a6b2747179Johan Hedberg			offset, size, io->nonblock);
3158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
316f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	frame_size = areas->step / 8;
317f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	if ((data->count + size * frame_size) <= cfg.pkt_len)
3188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		frames_to_read = size;
3198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	else
320f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz		frames_to_read = (cfg.pkt_len - data->count) / frame_size;
3218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
322c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	DBG("count = %d, frames_to_read = %lu", data->count, frames_to_read);
323c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
3248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	/* Ready for more data */
3256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
3266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			(areas->first + areas->step * offset) / 8;
327f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz	memcpy(data->buffer + data->count, buff, frame_size * frames_to_read);
3288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
3296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
3302a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	data->count += frames_to_read * frame_size;
3312a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz	if (data->count != cfg.pkt_len) {
3328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		ret = frames_to_read;
33300c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto done;
3348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
3358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
3369494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	rsend = send(data->stream_fd, data->buffer, cfg.pkt_len,
337c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz			io->nonblock ? MSG_DONTWAIT : 0);
33800c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (rsend > 0) {
33900c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Reset count pointer */
34000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		data->count = 0;
34100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
34200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		/* Increment hardware transmition pointer */
343f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz		data->hw_ptr = (data->hw_ptr + cfg.pkt_len / frame_size)
344c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz				% io->buffer_size;
34500c71248e732de0230c12df4240087a6b2747179Johan Hedberg
34600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = frames_to_read;
34700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	} else if (rsend < 0)
34800c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = (errno == EPIPE) ? -EIO : -errno;
34900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	else
35000c71248e732de0230c12df4240087a6b2747179Johan Hedberg		ret = -EIO;
35100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
35200c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone:
3536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("returning %lu", ret);
3546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
3556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io,
3586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						const snd_pcm_channel_area_t *areas,
3596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t offset,
3606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t size)
3616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
3626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t ret = 0;
3636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return ret;
3646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
3656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3669494c146cec1df466c2f331957748beeac8d745aJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data, unsigned int nonblock)
3676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
3686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int count = 0;
3696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int written;
3706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_header *header;
3716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct rtp_payload *payload;
3729494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
3736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#ifdef ENABLE_DEBUG
3746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	static struct timeval send_date = { 0, 0 };
3756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	static struct timeval prev_date = { 0, 0 };
3766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct timeval send_delay = { 0, 0 };
3776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct timeval sendz_delay = { 0, 0 };
3786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
3796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header = (void *) a2dp->buffer;
3816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload = (void *) (a2dp->buffer + sizeof(*header));
3826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload));
3846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	payload->frame_count = a2dp->frame_count;
3866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->v = 2;
3876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->pt = 1;
3886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->sequence_number = htons(a2dp->seq_num);
3896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->timestamp = htonl(a2dp->nsamples);
3906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	header->ssrc = htonl(1);
3916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
392afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	while (count++ < 10) {
3936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#ifdef ENABLE_DEBUG
3946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		gettimeofday(&send_date, NULL);
3956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
3969494c146cec1df466c2f331957748beeac8d745aJohan Hedberg		written = send(data->stream_fd, a2dp->buffer, a2dp->count,
3976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				nonblock ? MSG_DONTWAIT : 0);
3986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
3996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#ifdef ENABLE_DEBUG
4006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if ((written >= 0 || errno == EAGAIN) && prev_date.tv_sec != 0) {
4016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			long delay, real, theo, delta;
4026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			delay = (long) (send_delay.tv_sec * 1000 +
4046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						send_delay.tv_usec / 1000),
4056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			real = (long) (sendz_delay.tv_sec * 1000 +
4066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sendz_delay.tv_usec / 1000);
4076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			theo = (long) (((float) a2dp->nsamples) /
4086e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann						data->cfg.rate * 1000.0);
4096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			delta = (long) (sendz_delay.tv_sec * 1000 +
4106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						sendz_delay.tv_usec / 1000) -
4116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					(long) (((float) a2dp->nsamples) /
4126e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann							data->cfg.rate * 1000.0);
4136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			timersub(&send_date, &prev_date, &send_delay);
4156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			timersub(&send_date, &a2dp->ntimestamp, &sendz_delay);
4166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
417afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz			printf("send %d (cumul=%d) samples (delay=%ld ms,"
4186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					" real=%ld ms, theo=%ld ms,"
419afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz					" delta=%ld ms).\n", a2dp->samples,
4206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					a2dp->nsamples, delay, real, theo,
4216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg					delta);
4226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		}
4236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
424afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz		if (written == a2dp->count)
4256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			break;
4266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
427afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz		a2dp->count -= written;
4286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		DBG("send (retry).");
4306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		usleep(150000);
4316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
4326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#ifdef ENABLE_DEBUG
4346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	prev_date = send_date;
4356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
4366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Send our data */
4386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (written != a2dp->count)
439afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz		printf("Wrote %d not %d bytes\n", written, a2dp->count);
440afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz#ifdef ENABLE_DEBUG
4416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else {
4426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		/* Measure bandwith usage */
4436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		struct timeval now = { 0, 0 };
4446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		struct timeval interval = { 0, 0 };
4456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if(a2dp->bandwithtimestamp.tv_sec == 0)
4476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			gettimeofday(&a2dp->bandwithtimestamp, NULL);
4486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		/* See if we must wait again */
4506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		gettimeofday(&now, NULL);
4516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		timersub(&now, &a2dp->bandwithtimestamp, &interval);
4526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if(interval.tv_sec > 0)
453afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz			printf("Bandwith: %d (%d kbps)\n", a2dp->bandwithcount,
454afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz				a2dp->bandwithcount / 128);
4556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		a2dp->bandwithtimestamp = now;
4566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		a2dp->bandwithcount = 0;
4576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
4586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->bandwithcount += written;
4606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif
4626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Reset buffer of data to send */
4636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload);
4646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count = 0;
4656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples = 0;
4666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->seq_num++;
4676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return written;
4696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
4706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io,
4726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						const snd_pcm_channel_area_t *areas,
4736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t offset,
4746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg						snd_pcm_uframes_t size)
4756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
4766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_data *data = io->private_data;
4776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
4786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_sframes_t ret = 0;
4796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	snd_pcm_uframes_t frames_to_read;
4806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int frame_size, encoded;
4816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	uint8_t *buff;
4826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	static int codesize = 0;
4836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu,"
4856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			"io->nonblock=%u", areas->step, areas->first,
4866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			offset, size, io->nonblock);
4876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (codesize == 0) {
4896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		/* How much data can be encoded by sbc at a time? */
4906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		codesize = a2dp->sbc.subbands * a2dp->sbc.blocks *
4916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				a2dp->sbc.channels * 2;
4926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		/* Reserv header space in outgoing buffer */
4936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		a2dp->count = sizeof(struct rtp_header) +
4946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				sizeof(struct rtp_payload);
4956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		gettimeofday(&a2dp->ntimestamp, NULL);
4966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
4976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
4986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	frame_size = areas->step / 8;
4996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if ((data->count + size * frame_size) <= codesize)
5006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		frames_to_read = size;
5016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
5026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		frames_to_read = (codesize - data->count) / frame_size;
5036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("count = %d, frames_to_read = %lu", data->count, frames_to_read);
5056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("a2dp.count = %d cfg.pkt_len = %d", a2dp->count,
5066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			data->cfg.pkt_len);
5076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* FIXME: If state is not streaming then return */
5096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Ready for more data */
5116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	buff = (uint8_t *) areas->addr +
5126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		(areas->first + areas->step * offset) / 8;
5136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memcpy_changeendian(data->buffer + data->count, buff,
5146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				frame_size * frames_to_read);
5156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Remember we have some frames in the pipe now */
5176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	data->count += frames_to_read * frame_size;
5186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (data->count != codesize) {
5196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = frames_to_read;
5206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		goto done;
5216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Enough data to encode (sbc wants 1k blocks) */
5246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	encoded = sbc_encode(&(a2dp->sbc), data->buffer, codesize);
5256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (encoded <= 0) {
5266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		DBG("Encoding error %d", encoded);
5276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		goto done;
5286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
5296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	data->count -= encoded;
5316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("encoded = %d  a2dp.sbc.len= %d", encoded, a2dp->sbc.len);
5336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (a2dp->count + a2dp->sbc.len >= data->cfg.pkt_len)
5359494c146cec1df466c2f331957748beeac8d745aJohan Hedberg		avdtp_write(data, io->nonblock);
5366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memcpy(a2dp->buffer + a2dp->count, a2dp->sbc.data, a2dp->sbc.len);
5386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->count += a2dp->sbc.len;
5396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->frame_count++;
5406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->samples += encoded / frame_size;
5416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->nsamples += encoded / frame_size;
5426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* Increment hardware transmition pointer */
5436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	data->hw_ptr = (data->hw_ptr + codesize / frame_size)
5446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			% io->buffer_size;
5456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	ret = frames_to_read;
5476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
5496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("returning %lu", ret);
5508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	return ret;
5518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
5528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
5536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = {
5546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start		= bluetooth_start,
5556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.stop		= bluetooth_stop,
5566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.pointer	= bluetooth_pointer,
5576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close		= bluetooth_close,
558afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	.hw_params	= bluetooth_hsp_hw_params,
5596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.prepare	= bluetooth_prepare,
5606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.transfer	= bluetooth_hsp_write,
5616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
5626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = {
564b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.start		= bluetooth_start,
565b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.stop		= bluetooth_stop,
566b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.pointer	= bluetooth_pointer,
567b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.close		= bluetooth_close,
568afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	.hw_params	= bluetooth_hsp_hw_params,
569b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.prepare	= bluetooth_prepare,
5706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.transfer	= bluetooth_hsp_read,
571b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
572b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
5736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = {
574b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.start		= bluetooth_start,
575b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.stop		= bluetooth_stop,
576b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.pointer	= bluetooth_pointer,
577b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.close		= bluetooth_close,
578afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	.hw_params	= bluetooth_a2dp_hw_params,
579b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	.prepare	= bluetooth_prepare,
5806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.transfer	= bluetooth_a2dp_write,
5816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg};
5826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
5836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = {
5846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.start		= bluetooth_start,
5856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.stop		= bluetooth_stop,
5866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.pointer	= bluetooth_pointer,
5876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.close		= bluetooth_close,
588afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz	.hw_params	= bluetooth_a2dp_hw_params,
5896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.prepare	= bluetooth_prepare,
5906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	.transfer	= bluetooth_a2dp_read,
591b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann};
592b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
593b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0]))
594b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
595b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_hw_constraint(snd_pcm_ioplug_t *io)
596b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{
597c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct bluetooth_data *data = io->private_data;
598c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	struct ipc_data_cfg cfg = data->cfg;
599b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	snd_pcm_access_t access_list[] = {
600b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_RW_INTERLEAVED,
601b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		/* Mmap access is really useless fo this driver, but we
602b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * support it because some pieces of software out there
603b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		 * insist on using it */
604b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_ACCESS_MMAP_INTERLEAVED
605b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
606b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	unsigned int format_list[] = {
607b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		SND_PCM_FORMAT_S16_LE
608b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	};
609b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	int err;
610b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
611c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* access type */
612b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
613b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(access_list), access_list);
614b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
615b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
616b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
617c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported formats */
618b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
619b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann					ARRAY_NELEMS(format_list), format_list);
620b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
621b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
622b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
623c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	/* supported channels */
624c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
625c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz					cfg.channels, cfg.channels);
626b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
627b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
628b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
62935b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported rate */
630c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
631c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz					cfg.rate, cfg.rate);
632b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
633b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
634b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
63535b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz	/* supported block size */
636c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES,
637c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz					cfg.pkt_len, cfg.pkt_len);
638b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
639b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
640b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
641c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
642c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz					2, 200);
643b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
644b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		return err;
645b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
646b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
647b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}
648b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
649ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentzstatic int bluetooth_recvmsg_fd(struct bluetooth_data *data)
650ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz{
651ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	char cmsg_b[CMSG_SPACE(sizeof(int))];
652ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	struct ipc_packet pkt;
653ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	int err, ret;
654ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	struct iovec iov = {
655ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.iov_base = &pkt,
656ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.iov_len  = sizeof(pkt)
657ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz        };
658ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	struct msghdr msgh = {
659ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_name       = 0,
660ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_namelen    = 0,
661ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_iov        = &iov,
662ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_iovlen     = 1,
663ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_control    = &cmsg_b,
664ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_controllen = CMSG_LEN(sizeof(int)),
665ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		.msg_flags      = 0
666ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	};
667ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
668ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	ret = recvmsg(data->sock, &msgh, 0);
669ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	if (ret < 0) {
670ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		err = errno;
671ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		SNDERR("Unable to receive fd: %s (%d)", strerror(err), err);
672ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		return -err;
673ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	}
674ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
675e703434f83af5a41cb2f27604aedc8b2d15024e2Johan Hedberg	if (pkt.type == PKT_TYPE_CFG_RSP) {
676ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		struct cmsghdr *cmsg;
677ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		/* Receive auxiliary data in msgh */
678ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
679e703434f83af5a41cb2f27604aedc8b2d15024e2Johan Hedberg				cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
680ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz			if (cmsg->cmsg_level == SOL_SOCKET
681ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz				&& cmsg->cmsg_type == SCM_RIGHTS)
6829494c146cec1df466c2f331957748beeac8d745aJohan Hedberg				data->stream_fd = (*(int *) CMSG_DATA(cmsg));
6839494c146cec1df466c2f331957748beeac8d745aJohan Hedberg				DBG("stream_fd = %d", data->stream_fd);
684ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz				return 0;
685ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		}
686ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	}
687ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	else
688ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		SNDERR("Unexpected packet type received: type = %d", pkt.type);
689ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
690ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	return -EINVAL;
691ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz}
692ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz
6936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_a2dp_init(struct bluetooth_data *data,
6946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				struct ipc_codec_sbc *sbc)
6955ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann{
6966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct bluetooth_a2dp *a2dp = &data->a2dp;
6976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_data_cfg *cfg = &data->cfg;
6988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
6996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (cfg == NULL) {
7006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		SNDERR("Error getting codec parameters");
7016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -1;
7026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
70300c71248e732de0230c12df4240087a6b2747179Johan Hedberg
7046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (cfg->codec != CFG_CODEC_SBC)
7056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -1;
7066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	/* FIXME: init using flags? */
7086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sbc_init(&a2dp->sbc, 0);
7096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.rate = cfg->rate;
7106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.channels = cfg->channels;
7116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (cfg->channel_mode == CFG_CHANNEL_MODE_MONO ||
7126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			cfg->channel_mode == CFG_CHANNEL_MODE_JOINT_STEREO)
7136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		a2dp->sbc.joint = 1;
7146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.allocation = sbc->allocation;
7156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.subbands = sbc->subbands;
7166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.blocks = sbc->blocks;
7176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	a2dp->sbc.bitpool = sbc->bitpool;
71800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
7196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
7206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}
7216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_cfg(struct bluetooth_data *data, snd_config_t *conf)
7236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{
7246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int ret, total;
7256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	char buf[IPC_MTU];
7266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_packet *pkt = (void *) buf;
7276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_data_cfg *cfg = (void *) pkt->data;
7286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	struct ipc_codec_sbc *sbc = (void *) cfg->data;
7296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("Sending PKT_TYPE_CFG_REQ...");
7316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(buf, 0, sizeof(buf));
733f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	pkt->type = PKT_TYPE_CFG_REQ;
734f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	pkt->role = PKT_ROLE_NONE;
735f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	pkt->error = PKT_ERROR_NONE;
73600c71248e732de0230c12df4240087a6b2747179Johan Hedberg
7376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	ret = send(data->sock, pkt, sizeof(struct ipc_packet), 0);
7386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (ret < 0)
7396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -errno;
7406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (ret == 0)
7416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EIO;
74200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
7436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("OK - %d bytes sent. Waiting for response...", ret);
7448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
7456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memset(buf, 0, sizeof(buf));
7468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
7476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	ret = recv(data->sock, buf, sizeof(*pkt) + sizeof(*cfg), 0);
7486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (ret < 0)
7496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -errno;
7506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (ret == 0)
7516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EIO;
75200c71248e732de0230c12df4240087a6b2747179Johan Hedberg
7536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	total = ret;
754b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
755f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	if (pkt->type != PKT_TYPE_CFG_RSP) {
75600c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR("Unexpected packet type received: type = %d",
75700c71248e732de0230c12df4240087a6b2747179Johan Hedberg				pkt->type);
7586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EINVAL;
7598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
760b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
761f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	if (pkt->error != PKT_ERROR_NONE) {
76200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		SNDERR("Error while configuring device: error = %d",
76300c71248e732de0230c12df4240087a6b2747179Johan Hedberg				pkt->error);
7646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return pkt->error;
7658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
766b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
7676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (cfg->codec != CFG_CODEC_SBC)
7686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		goto done;
7696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	ret = recv(data->sock, sbc, sizeof(*sbc), 0);
7716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (ret < 0)
7726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -errno;
7736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else if (ret == 0)
7746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EIO;
7756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	total += ret;
7776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone:
7796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("OK - %d bytes received", total);
7806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (pkt->length != (total - sizeof(struct ipc_packet))) {
782019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley		SNDERR("Error while configuring device: packet size doesn't "
78300c71248e732de0230c12df4240087a6b2747179Johan Hedberg				"match");
7846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EINVAL;
7858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	}
786b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
7876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	memcpy(&data->cfg, cfg, sizeof(*cfg));
788b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
7898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	DBG("Device configuration:");
790f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
7916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	DBG("\n\tfd=%d\n\tfd_opt=%u\n\tchannels=%u\n\tpkt_len=%u\n"
7926e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann		"\tsample_size=%u\n\trate=%u", data->stream_fd,
7936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->cfg.fd_opt, data->cfg.channels, data->cfg.pkt_len,
7946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->cfg.sample_size, data->cfg.rate);
7956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
7966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (data->cfg.codec == CFG_CODEC_SBC) {
7976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		struct bluetooth_a2dp *a2dp = &data->a2dp;
7986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		ret = bluetooth_a2dp_init(data, sbc);
7996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		if (ret < 0)
8006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			return ret;
8016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		printf("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\t"
8026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				"bitpool=%u\n", a2dp->sbc.allocation,
8036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				a2dp->sbc.subbands, a2dp->sbc.blocks,
8046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				a2dp->sbc.bitpool);
8056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	}
8068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8079494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	if (data->stream_fd == -1) {
808019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley		SNDERR("Error while configuring device: could not acquire "
80900c71248e732de0230c12df4240087a6b2747179Johan Hedberg				"audio socket");
8106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -EINVAL;
811f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	}
812f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
8136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	ret = bluetooth_recvmsg_fd(data);
8146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (ret < 0)
8156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return ret;
816c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
817ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	/* It is possible there is some outstanding
818ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	data in the pipe - we have to empty it */
8199494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	while (recv(data->stream_fd, data->buffer, data->cfg.pkt_len,
8206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg				MSG_DONTWAIT) > 0);
82100c71248e732de0230c12df4240087a6b2747179Johan Hedberg
822c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz	memset(data->buffer, 0, data->cfg.pkt_len);
823c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz
8246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return 0;
8258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
8268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_config_t *conf)
8288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
8296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	int sk, err;
830ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	struct sockaddr_un addr = {
831ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz		AF_UNIX, IPC_SOCKET_NAME
832ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz	};
8338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
834f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	if (!data)
835f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		return -EINVAL;
836f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz
83700c71248e732de0230c12df4240087a6b2747179Johan Hedberg	memset(data, 0, sizeof(struct bluetooth_data));
83800c71248e732de0230c12df4240087a6b2747179Johan Hedberg
83900c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->sock = -1;
84000c71248e732de0230c12df4240087a6b2747179Johan Hedberg
8416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	sk = socket(PF_LOCAL, SOCK_STREAM, 0);
8426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (sk < 0) {
8436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		err = errno;
8446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		SNDERR("Cannot open socket: %s (%d)", strerror(err), err);
8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -err;
846b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
847b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
8488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	DBG("Connecting to address: %s", addr.sun_path + 1);
849b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
8506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		err = errno;
8516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		SNDERR("Connection fail", strerror(err), err);
852b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		close(sk);
8536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		return -err;
854b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
855b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
856b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	data->sock = sk;
857b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
8586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	return bluetooth_cfg(data, conf);
8598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz}
8608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
8618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth)
8628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{
863f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	struct bluetooth_data *data;
8648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	int err;
8658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg	DBG("Bluetooth PCM plugin (%s)",
8678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture");
8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
869f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data = malloc(sizeof(struct bluetooth_data));
87000c71248e732de0230c12df4240087a6b2747179Johan Hedberg	if (!data) {
87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg		err = -ENOMEM;
87200c71248e732de0230c12df4240087a6b2747179Johan Hedberg		goto error;
87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg	}
87400c71248e732de0230c12df4240087a6b2747179Johan Hedberg
8756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	err = bluetooth_init(data, conf);
8768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz	if (err < 0)
8778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
8788742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz
879f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.version = SND_PCM_IOPLUG_VERSION;
880f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.name = "Bluetooth Audio Device";
88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg	data->io.mmap_rw = 0; /* No direct mmap communication */
8829494c146cec1df466c2f331957748beeac8d745aJohan Hedberg	data->io.poll_fd = data->stream_fd;
883f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.poll_events = stream == SND_PCM_STREAM_PLAYBACK ?
88400c71248e732de0230c12df4240087a6b2747179Johan Hedberg					POLLOUT : POLLIN;
885f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	data->io.private_data = data;
886b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
8876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	if (data->cfg.codec == CFG_CODEC_SBC)
8886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
8896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_playback :
8906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_a2dp_capture;
8916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg	else
8926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg		data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
8936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_playback :
8946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg			&bluetooth_hsp_capture;
8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg
896f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = snd_pcm_ioplug_create(&data->io, name, stream, mode);
897b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0)
898b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann		goto error;
899b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
900f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	err = bluetooth_hw_constraint(&data->io);
901b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	if (err < 0) {
902f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz		snd_pcm_ioplug_delete(&data->io);
9038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz		goto error;
904b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	}
905b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
906f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz	*pcmp = data->io.pcm;
907b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
908b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return 0;
909b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann
910b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror:
9115ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz	bluetooth_exit(data);
9125ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
913b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann	return err;
9145ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann}
9155ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann
9165ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth);
917