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