pcm_bluetooth.c revision 3709666344736da68472f754ac52edc356039058
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/* 2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 53ff24ea225437af91db69a069caa65b00ed642d9Marcel Holtmann * Copyright (C) 2006-2007 Nokia Corporation 6e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org> 7e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 8e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 9e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * This library is free software; you can redistribute it and/or 10e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * modify it under the terms of the GNU Lesser General Public 11e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * License as published by the Free Software Foundation; either 12e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * version 2.1 of the License, or (at your option) any later version. 13e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 14e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * This library is distributed in the hope that it will be useful, 15e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 16e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Lesser General Public License for more details. 18e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 19e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * You should have received a copy of the GNU Lesser General Public 20e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * License along with this library; if not, write to the Free Software 21e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 23e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann */ 24e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann 25e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#ifdef HAVE_CONFIG_H 26e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#include <config.h> 27e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#endif 285ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 29714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#include <stdint.h> 30b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/socket.h> 31b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/un.h> 32344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg#include <time.h> 336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <sys/time.h> 34e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg#include <pthread.h> 35dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg#include <signal.h> 366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h> 38b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 395ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h> 405ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h> 415ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 42b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h" 436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h" 44347675ea994642c0ccd60f7af70f369f7a2d7a88Luiz Augusto von Dentz#include "rtp.h" 456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 4638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann//#define ENABLE_DEBUG 476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 48714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#define UINT_SECS_MAX (UINT_MAX / 1000000 - 1) 49714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg 50e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz#define MIN_PERIOD_TIME 1 51714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg 52f5befe8ab54b797a0a5357ceddf2f05ab0ff163cJohan Hedberg#define BUFFER_SIZE 2048 53b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 54f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG 55b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...) printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg) 56f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else 57f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...) 58f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif 59b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 6097c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#ifndef SOL_SCO 6197c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#define SOL_SCO 17 6297c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#endif 6397c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann 648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS 658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03 668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS 698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04 708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MIN 732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MIN(x, y) ((x) < (y) ? (x) : (y)) 742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif 752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MAX 772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MAX(x, y) ((x) > (y) ? (x) : (y)) 782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif 792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MAX_BITPOOL 64 812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MIN_BITPOOL 2 822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 83d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg/* adapted from glibc sys/time.h timersub() macro */ 84d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg#define priv_timespecsub(a, b, result) \ 85d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg do { \ 86d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 87d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \ 88d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg if ((result)->tv_nsec < 0) { \ 89d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg --(result)->tv_sec; \ 90d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_nsec += 1000000000; \ 91d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg } \ 92d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg } while (0) 93344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg 946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp { 95d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sbc_capabilities_t sbc_capabilities; 96d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sbc_t sbc; /* Codec data */ 97d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int sbc_initialized; /* Keep track if the encoder is initialized */ 98d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int codesize; /* SBC codesize */ 99d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int samples; /* Number of encoded samples */ 100d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t buffer[BUFFER_SIZE]; /* Codec transfer buffer */ 101d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int count; /* Codec transfer buffer counter */ 102d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 103d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int nsamples; /* Cumulative number of codec samples */ 104d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint16_t seq_num; /* Cumulative packet sequence */ 105d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int frame_count; /* Current frames in buffer*/ 106d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}; 107d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 108d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstruct bluetooth_alsa_config { 109d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz char device[18]; /* Address of the remote Device */ 110d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_device; 111d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t transport; /* Requested transport */ 112d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_transport; 113d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint16_t rate; 114d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_rate; 115d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t channel_mode; /* A2DP only */ 116d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_channel_mode; 117d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t allocation_method; /* A2DP only */ 118d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_allocation_method; 119d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t subbands; /* A2DP only */ 120d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_subbands; 121d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t block_length; /* A2DP only */ 122d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_block_length; 123d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t bitpool; /* A2DP only */ 124d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_bitpool; 1256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 1266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data { 128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_ioplug_t io; 129d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config alsa_config; /* ALSA resource file parameters */ 130e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg volatile snd_pcm_sframes_t hw_ptr; 131d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int transport; /* chosen transport SCO or AD2P */ 132d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int link_mtu; /* MTU for selected transport channel */ 133d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz volatile struct pollfd stream; /* Audio stream filedescriptor */ 134d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct pollfd server; /* Audio daemon filedescriptor */ 135d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t buffer[BUFFER_SIZE]; /* Encoded transfer buffer */ 136d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int count; /* Transfer buffer counter */ 137d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp a2dp; /* A2DP data */ 138d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 139d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_t hw_thread; /* Makes virtual hw pointer move */ 140d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int pipefd[2]; /* Inter thread communication */ 141892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz int stopped; 142dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg sig_atomic_t reset; /* Request XRUN handling */ 143b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 145d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg); 146d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg, 147d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int expected_type); 148d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 149b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io) 150b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1519217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_start %p", io); 152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 156b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io) 157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_stop %p", io); 159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 160b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 163892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic void *playback_hw_thread(void *param) 164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = param; 166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int prev_periods; 167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg double period_time; 168d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg struct timespec start; 169e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz struct pollfd fds[2]; 1703e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg int poll_timeout; 171e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz 172dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->server.events = POLLIN; 173dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* note: only errors for data->stream.events */ 174dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 175e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz fds[0] = data->server; 176e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz fds[1] = data->stream; 177e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg prev_periods = 0; 179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg period_time = 1000000.0 * data->io.period_size / data->io.rate; 1803e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg if (period_time > (int) (MIN_PERIOD_TIME * 1000)) 1813e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg poll_timeout = (int) (period_time / 1000.0f); 1823e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg else 1833e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg poll_timeout = MIN_PERIOD_TIME; 184e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 185d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg while (1) { 188714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg unsigned int dtime, periods; 189d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg struct timespec cur, delta; 190e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz int ret; 191e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 192892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->stopped) 193f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg goto iter_sleep; 194f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 195dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (data->reset) { 196dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Handle XRUN in hw-thread."); 197dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 0; 198d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 199dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg prev_periods = 0; 200dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 201dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 202d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &cur); 203e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 204d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg priv_timespecsub(&cur, &start, &delta); 205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 206d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000; 207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg periods = 1.0 * dtime / period_time; 208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (periods > prev_periods) { 210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 211dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg int frags = periods - prev_periods, n; 212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 213dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->hw_ptr += frags * data->io.period_size; 214e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data->hw_ptr %= data->io.buffer_size; 215e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 216dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg for (n = 0; n < frags; n++) { 217dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Notify user that hardware pointer 218dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg * has moved * */ 219dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (write(data->pipefd[1], &c, 1) < 0) 220dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg pthread_testcancel(); 221dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 222e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 223714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg /* Reset point of reference to avoid too big values 224714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg * that wont fit an unsigned int */ 2258dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg if (delta.tv_sec < UINT_SECS_MAX) 2268dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg prev_periods = periods; 2278dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg else { 228714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg prev_periods = 0; 229d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 2308dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg } 231de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 232e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 233f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedbergiter_sleep: 2343e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg /* sleep up to one period interval */ 2353e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg ret = poll(fds, 2, poll_timeout); 236dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 237e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (ret < 0) { 238e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz SNDERR("poll error: %s (%d)", strerror(errno), errno); 239e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (errno != EINTR) 240e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 241e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } else if (ret > 0) { 242e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz ret = (fds[0].revents) ? 0 : 1; 243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz SNDERR("poll fd %d revents %d", ret, fds[ret].revents); 244db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL)) 245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 246e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } 247e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 248e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Offer opportunity to be canceled by main thread */ 249de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz pthread_testcancel(); 250e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 251e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz 252e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->hw_thread = 0; 253e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pthread_exit(NULL); 254e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 25533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 256892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io) 257e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 259e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int err; 260e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 263892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 0; 264f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 265892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) 266f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg return 0; 267e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 268892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data); 269e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 270e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -err; 271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 273892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io) 274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 275e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 277e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 279892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 1; 280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 2817090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg return 0; 282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 283e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 284b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io) 285b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return data->hw_ptr; 289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2915ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data) 2925ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{ 293892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 294892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 295e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->server.fd >= 0) 296d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_service_close(data->server.fd); 2975ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 298e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->stream.fd >= 0) 299e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz close(data->stream.fd); 3002a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz 301892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) { 302892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 303892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 304892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 305f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 306d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 307f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg sbc_finish(&a2dp->sbc); 308d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz 309892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[0] > 0) 310892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[0]); 311de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 312892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[1] > 0) 313892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[1]); 314de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 3155ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz free(data); 3165ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz} 3175ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 318b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io) 319b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 321b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("%p", io); 323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3245ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 326b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 328b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 3308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 332e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 333d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz char buf[BT_AUDIO_IPC_PACKET_SIZE]; 334d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bt_streamstart_req *start_req = (void*) buf; 335d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; 336d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz struct bt_streamfd_ind *streamfd_ind = (void*) buf; 337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int opt_name, err; 339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct timeval t = { 0, period_count }; 3408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 34138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 34238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann io->period_size, io->buffer_size); 3438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 344dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 0; 345dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 346d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* As we're gonna receive messages on the server socket, we have to stop the 347d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz hw thread that is polling on it, if any */ 348d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->hw_thread) { 349d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_thread = 0; 352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3549217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg if (io->stream == SND_PCM_STREAM_PLAYBACK) 35500c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* If not null for playback, xmms doesn't display time 35600c71248e732de0230c12df4240087a6b2747179Johan Hedberg * correctly */ 3578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 3589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg else 35900c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* ALSA library is really picky on the fact hw_ptr is not null. 36000c71248e732de0230c12df4240087a6b2747179Johan Hedberg * If it is, capture won't start */ 3618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 3629217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 363d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* send start */ 364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(start_req, 0, BT_AUDIO_IPC_PACKET_SIZE); 365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz start_req->h.msg_type = BT_STREAMSTART_REQ; 3668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = audioservice_send(data->server.fd, &start_req->h); 368d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 369d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 370d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 371d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, 372d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz BT_STREAMSTART_RSP); 373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 376d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz if (rsp_hdr->posix_errno != 0) { 377d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("BT_START failed : %s(%d)", 378d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz strerror(rsp_hdr->posix_errno), 379d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz rsp_hdr->posix_errno); 380d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz return -rsp_hdr->posix_errno; 381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 383d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &streamfd_ind->h, 384d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz BT_STREAMFD_IND); 385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd >= 0) 389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz close(data->stream.fd); 390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->stream.fd = bt_audio_service_get_data_fd(data->server.fd); 392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd < 0) { 393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 3959217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SO_SNDTIMEO : SO_RCVTIMEO; 399ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 400d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t, 401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sizeof(t)) < 0) 402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 404d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 40538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SCO_TXBUFS : SCO_RXBUFS; 4068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 407d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 40838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 409d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4109217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 411d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 41238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SO_SNDBUF : SO_RCVBUF; 41300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 41538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 416d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4177090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg 418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* FIXME : handle error codes */ 419d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 42000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* wake up any client polling at us */ 422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return write(data->pipefd[1], &c, 1); 4238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 425721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, 426721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 427721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{ 428721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 429721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz char buf[BT_AUDIO_IPC_PACKET_SIZE]; 430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; 431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz struct bt_setconfiguration_req *setconf_req = (void*) buf; 432721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf; 433721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz int err; 434721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 435721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 436721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->period_size, io->buffer_size); 437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE); 439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; 440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz strncpy(setconf_req->device, data->alsa_config.device, 18); 441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz setconf_req->transport = BT_CAPABILITIES_TRANSPORT_SCO; 442721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? 443721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_WRITE : 444721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_READ); 445721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 446721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz err = audioservice_send(data->server.fd, &setconf_req->h); 447721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 448721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 449721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 450721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, 451721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz BT_SETCONFIGURATION_RSP); 452721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 453721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 454721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 455721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (rsp_hdr->posix_errno != 0) { 456721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz SNDERR("BT_SETCONFIGURATION failed : %s(%d)", 457721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz strerror(rsp_hdr->posix_errno), 458721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz rsp_hdr->posix_errno); 459721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return -rsp_hdr->posix_errno; 460721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz } 461721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 462721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz data->transport = setconf_rsp->transport; 463721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz data->link_mtu = setconf_rsp->link_mtu; 464721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 465721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return 0; 466721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz} 467721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 4682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) 4692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 4702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (freq) { 4712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_SAMPLING_FREQ_16000: 4722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_SAMPLING_FREQ_32000: 4732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 4742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_SAMPLING_FREQ_44100: 4752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 4782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 31; 4792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 4802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 4812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 4822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 4832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 4842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 4852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 4862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_SAMPLING_FREQ_48000: 4872934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 29; 4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 4942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid sampling freq %u", freq); 5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic int select_sbc_params(sbc_capabilities_t *cap, unsigned int rate, 5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz unsigned int channels) 5062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz unsigned int max_bitpool, min_bitpool; 5082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (rate) { 5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 48000: 5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->frequency = BT_A2DP_SAMPLING_FREQ_48000; 5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 44100: 5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->frequency = BT_A2DP_SAMPLING_FREQ_44100; 5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 32000: 5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->frequency = BT_A2DP_SAMPLING_FREQ_32000; 5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 16000: 5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->frequency = BT_A2DP_SAMPLING_FREQ_16000; 5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Rate %d not supported", rate); 5242934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (channels == 2) { 5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 5292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 5302934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 5312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 5322934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 5332934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 5342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } else { 5352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (!cap->channel_mode) { 5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported channel modes"); 5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) 5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_16; 5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) 5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_12; 5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) 5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_8; 5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) 5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_4; 5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5532934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported block lengths"); 5542934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5552934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->subbands & BT_A2DP_SUBBANDS_8) 5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_8; 5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->subbands & BT_A2DP_SUBBANDS_4) 5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_4; 5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported subbands"); 5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) 5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) 5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_SNR; 5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool); 5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz max_bitpool = MIN(default_bitpool(cap->frequency, cap->channel_mode), 5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->max_bitpool); 5742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->min_bitpool = min_bitpool; 5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->max_bitpool = max_bitpool; 5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 0; 5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 582afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, 583afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 584afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{ 585afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 586d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 587d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz char buf[BT_AUDIO_IPC_PACKET_SIZE]; 588d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; 589d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bt_setconfiguration_req *setconf_req = (void*) buf; 590d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bt_setconfiguration_rsp *setconf_rsp = (void*) buf; 5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz unsigned int rate, channels; 5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz int err, dir; 593d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sbc_capabilities_t active_capabilities; 594afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 595d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 596d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz io->period_size, io->buffer_size); 597afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 598d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* FIXME: this needs to be really implemented (take into account 599d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz real asoundrc settings + ALSA hw settings ) once server side sends us 600d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz more than one possible configuration */ 6012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz snd_pcm_hw_params_get_rate(params, &rate, &dir); 6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz snd_pcm_hw_params_get_channels(params, &channels); 6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz err = select_sbc_params(&a2dp->sbc_capabilities, rate, channels); 6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (err < 0) 6052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return err; 6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 607d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz active_capabilities = a2dp->sbc_capabilities; 608afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(setconf_req, 0, BT_AUDIO_IPC_PACKET_SIZE); 610d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz setconf_req->h.msg_type = BT_SETCONFIGURATION_REQ; 611721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz strncpy(setconf_req->device, data->alsa_config.device, 18); 612721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz setconf_req->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 613d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz setconf_req->sbc_capabilities = active_capabilities; 6142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz setconf_req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? 6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_WRITE : 6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_READ); 617afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 618d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = audioservice_send(data->server.fd, &setconf_req->h); 619d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 620d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 621e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 622d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, 623d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz BT_SETCONFIGURATION_RSP); 624d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 625d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 626afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 627d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz if (rsp_hdr->posix_errno != 0) { 628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("BT_SETCONFIGURATION failed : %s(%d)", 629d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz strerror(rsp_hdr->posix_errno), 630d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz rsp_hdr->posix_errno); 631d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz return -rsp_hdr->posix_errno; 632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 633d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 6342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz data->transport = setconf_rsp->transport; 6352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz data->link_mtu = setconf_rsp->link_mtu; 6362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* Setup SBC encoder now we agree on parameters */ 638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 6392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_reinit(&a2dp->sbc, 0); 6402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else 6412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_init(&a2dp->sbc, 0); 642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc_initialized = 1; 6432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) 645d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.rate = 16000; 646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) 648d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.rate = 32000; 649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 650d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) 651d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.rate = 44100; 652d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) 654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.rate = 48000; 655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.channels = 1; 658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.channels = 2; 660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.channel_mode & 662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz (BT_A2DP_CHANNEL_MODE_MONO || BT_A2DP_CHANNEL_MODE_JOINT_STEREO)) 663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.joint = 1; 664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.joint = 0; 666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation = active_capabilities.allocation_method 668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz == BT_A2DP_ALLOCATION_SNR ? 0x01 : 0x00; 669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.subbands) { 671d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_4: 672d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.subbands = 4; 673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_8: 675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.subbands = 8; 676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.block_length) { 680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_4: 681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.blocks = 4; 682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_8: 684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.blocks = 8; 685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_12: 687d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.blocks = 12; 688d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 689d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_16: 690d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.blocks = 16; 691d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 692d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 693d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 694d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool = active_capabilities.max_bitpool; 695d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->codesize = a2dp->sbc.subbands * a2dp->sbc.blocks * 696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.channels * 2; 697d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 698d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 699d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", 700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks, 701d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool); 702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 703d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 704afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz} 705afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 706e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, 707f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann struct pollfd *pfd, unsigned int space) 708e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 709e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 710e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 711e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(io); 712e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 713e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 714e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 715e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 716e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pfd[0].fd = data->stream.fd; 717e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 718e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 719e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 720e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 721e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 722e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 723e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED, 724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, unsigned int nfds, 725dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 727e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds && nfds == 1 && revents); 728e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 729e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = pfds[0].revents; 730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 734892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io, 73538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfd, unsigned int space) 736e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 737e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 739e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 740e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 741892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz assert(data->pipefd[0] >= 0); 742e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 743e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 744e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 745e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 746892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pfd[0].fd = data->pipefd[0]; 747e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 748e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 749e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 750e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 751e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 752e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 753892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io, 75438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfds, unsigned int nfds, 755dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 756e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 757e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg static char buf[1]; 758e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret; 759e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 760e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 762e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds); 763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(nfds == 1); 764e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(revents); 765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds[0].fd >= 0); 766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (io->state != SND_PCM_STATE_PREPARED) 768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = read(pfds[0].fd, buf, 1); 769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = (pfds[0].revents & ~POLLIN) | POLLOUT; 771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 773e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 7766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, 77738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 778dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 779dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 7808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 7818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 78200c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 78300c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 784f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int nrecv, frame_size = 0; 7858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 78638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u", 78738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 7888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 7893709666344736da68472f754ac52edc356039058Johan Hedberg frame_size = areas->step / 8; 7903709666344736da68472f754ac52edc356039058Johan Hedberg 79100c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 79200c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 79300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 794d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz nrecv = recv(data->stream.fd, data->buffer, data->link_mtu, 79500c71248e732de0230c12df4240087a6b2747179Johan Hedberg MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0)); 79600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 79700c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 79800c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 79900c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 80100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 802d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (nrecv != data->link_mtu) { 80300c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 80400c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 80500c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 8078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 80800c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 809d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % 810721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->buffer_size; 81100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 81200c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 8136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (unsigned char *) areas->addr + 8146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 81500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 816d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 81700c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 81800c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 819d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_write = (data->link_mtu - data->count) / frame_size; 82000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 821f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(buff, data->buffer + data->count, frame_size * frames_to_write); 822f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->count += (frame_size * frames_to_write); 823d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->count %= data->link_mtu; 82400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 82500c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 82600c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 82700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 82800c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 82900c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 8308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 8318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 8328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, 83438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 835dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 836dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 8388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 8398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 8408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 841c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz uint8_t *buff; 842f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int rsend, frame_size; 8438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 84438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u", 84538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 8468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 847892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (io->hw_ptr > io->appl_ptr) { 848892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 849892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (ret == 0) 850892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = -EPIPE; 851892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz goto done; 852892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 853892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 854f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 855d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 8568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 8578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 858d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_read = (data->link_mtu - data->count) / frame_size; 8598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 86038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("count=%d frames_to_read=%lu", data->count, frames_to_read); 861c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 8628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 8636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 865f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(data->buffer + data->count, buff, frame_size * frames_to_read); 8668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 8682a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz data->count += frames_to_read * frame_size; 869d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->count != data->link_mtu) { 8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 8738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 874d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rsend = send(data->stream.fd, data->buffer, data->link_mtu, 875c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz io->nonblock ? MSG_DONTWAIT : 0); 87600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 87700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 87800c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 87900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 88000c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 88200c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 88300c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 88400c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 88600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 887892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz DBG("returning %ld", ret); 8886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 8896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 8906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 8916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io, 89238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 893dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 894dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 8966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t ret = 0; 8976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 8996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 900e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data) 9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 902e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret = 0; 9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_header *header; 9046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_payload *payload; 9059494c146cec1df466c2f331957748beeac8d745aJohan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header = (void *) a2dp->buffer; 9086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload = (void *) (a2dp->buffer + sizeof(*header)); 9096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9106763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); 9116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload->frame_count = a2dp->frame_count; 9136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->v = 2; 9146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->pt = 1; 9156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->sequence_number = htons(a2dp->seq_num); 9166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->timestamp = htonl(a2dp->nsamples); 9176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->ssrc = htonl(1); 9186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 919dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); 920dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (ret < 0) { 921dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("send returned %d errno %s.", ret, strerror(errno)); 922e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -errno; 923dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 9248905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 9256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reset buffer of data to send */ 9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count = 0; 9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples = 0; 9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->seq_num++; 9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 931f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg return ret; 9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io, 93538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 93638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 9386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_data *data = io->private_data; 9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_sframes_t ret = 0; 941dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t frames_to_read, frames_left = size; 942397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz int frame_size, encoded, written; 9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t *buff; 9446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 94538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu", 94638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size); 947dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr, 948dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg io->appl_ptr - io->hw_ptr); 949e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 950cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->hw_ptr > io->appl_ptr) { 951892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 952de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz if (ret == 0) 953e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -EPIPE; 954dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 1; 955de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz goto done; 956de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 957e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 958e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Check if we should autostart */ 959cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->state == SND_PCM_STATE_PREPARED) { 960e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_t *swparams; 961e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_uframes_t threshold; 962de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 963e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_malloc(&swparams); 96438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann if (!snd_pcm_sw_params_current(io->pcm, swparams) && 965dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg !snd_pcm_sw_params_get_start_threshold(swparams, 966dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg &threshold)) { 967cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->appl_ptr >= threshold) { 968e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = snd_pcm_start(io->pcm); 969cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret != 0) 970de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz goto done; 971e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 972e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 973dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 974de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz snd_pcm_sw_params_free(swparams); 975e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 977dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg while (frames_left > 0) { 978dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg frame_size = areas->step / 8; 9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 980dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if ((data->count + frames_left * frame_size) <= a2dp->codesize) 981dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg frames_to_read = frames_left; 982dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg else 983dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg frames_to_read = (a2dp->codesize - data->count) / frame_size; 9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 985dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("count=%d frames_to_read=%lu", data->count, frames_to_read); 986d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("a2dp.count=%d data.link_mtu=%d", a2dp->count, data->link_mtu); 9876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 988dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* FIXME: If state is not streaming then return */ 9896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Ready for more data */ 991dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg buff = (uint8_t *) areas->addr + 992dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg (areas->first + areas->step * (offset + ret)) / 8; 993dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg memcpy(data->buffer + data->count, buff, 994dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg frame_size * frames_to_read); 9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 996dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Remember we have some frames in the pipe now */ 997dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->count += frames_to_read * frame_size; 998dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (data->count != a2dp->codesize) { 999dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg ret = frames_to_read; 1000dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg goto done; 1001dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 10026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1003dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Enough data to encode (sbc wants 1k blocks) */ 1004397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz encoded = sbc_encode(&(a2dp->sbc), data->buffer, a2dp->codesize, 1005fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz a2dp->buffer + a2dp->count, 1006fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz sizeof(a2dp->buffer) - a2dp->count, 1007397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz &written); 1008dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (encoded <= 0) { 1009dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Encoding error %d", encoded); 1010dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg goto done; 1011dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 10126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1013dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->count -= encoded; 1014397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->count += written; 1015397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->frame_count++; 1016397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->samples += encoded / frame_size; 1017397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->nsamples += encoded / frame_size; 10186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1019397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz DBG("encoded=%d written=%d count=%d", encoded, 1020397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz written, a2dp->count); 1021dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1022397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz /* No space left for another frame then send */ 1023d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->count + written >= data->link_mtu) { 1024dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg avdtp_write(data); 1025d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending packet %d, count %d, link_mtu %u", 1026d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->seq_num, a2dp->count, 1027d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->link_mtu); 1028f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 10296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1030dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg ret += frames_to_read; 1031dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg frames_left -= frames_to_read; 1032dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 1033dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1034dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* note: some ALSA apps will get confused otherwise */ 1035dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (ret > size) 1036dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg ret = size; 10376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 10386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 1039e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("returning %ld", ret); 10408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 10418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 10428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 10436967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io, 10446967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg snd_pcm_sframes_t *delayp) 1045a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{ 1046a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley DBG(""); 1047a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 1048a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This updates io->hw_ptr value using pointer() function */ 1049a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley snd_pcm_hwsync(io->pcm); 10506967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1051a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = io->appl_ptr - io->hw_ptr; 1052a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) { 1053a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->callback->stop(io); 1054a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->state = SND_PCM_STATE_XRUN; 1055a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = 0; 1056a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley } 10576967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1058a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This should never fail, ALSA API is really not 1059a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley prepared to handle a non zero return value */ 1060a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley return 0; 1061a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley} 1062a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 10636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { 1064892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1065892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1066e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1067e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1068721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1069e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1070e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_write, 1071892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1072892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1073a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 10746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 10756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 10766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { 1077e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1078e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1079e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1080e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1081721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1082e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1083e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_read, 1084e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1085e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1086b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1087b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 10886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = { 1089892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1090892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1091e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1092e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1093e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1094e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1095e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_write, 1096892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1097892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1098a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 10996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = { 1102e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1103e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1104e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1105e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1106e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1107e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1108e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_read, 1109e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1110e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1111b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1112b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1113b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 1114b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 111533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io) 1116b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1117c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1118b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 1119b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 1120b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 1121b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 1122b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 1123b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 1124b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1125b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 1126b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_FORMAT_S16_LE 1127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1128d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 1129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1130c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* access type */ 1131b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 1132b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 1133b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1134b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1135b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1136c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported formats */ 1137b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1138b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 1139b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1140b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1141b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1142c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported channels */ 1143c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1144d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1, 1); 1145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1146b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1147b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 114835b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported rate */ 1149c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 1150d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 8000, 8000); 1151b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1153b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 115435b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported block size */ 1155c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1156d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->link_mtu, data->link_mtu); 1157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1160c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1161f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann 2, 200); 116233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 116333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 116433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 116533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return 0; 116633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz} 116733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 116833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io) 116933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{ 117033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1171d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 117233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz snd_pcm_access_t access_list[] = { 117333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_RW_INTERLEAVED, 117433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* Mmap access is really useless fo this driver, but we 117533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * support it because some pieces of software out there 117633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * insist on using it */ 117733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_MMAP_INTERLEAVED 117833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 117933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz unsigned int format_list[] = { 118033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_FORMAT_S16_LE 118133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 1182d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_list[4]; 1183d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_count; 1184d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err, min_channels, max_channels; 1185dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned int period_list[] = { 1186db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 2048, 1187db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */ 1188db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 8192 1189dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg }; 119033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 119133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* access type */ 119233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 119333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(access_list), access_list); 119433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 119533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 119633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 119733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported formats */ 119833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 119933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(format_list), format_list); 120033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 120133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 120233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 120333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported channels */ 1204d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 1205d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 1; 1206d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1207d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 2; 120833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1209d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & (~BT_A2DP_CHANNEL_MODE_MONO)) 1210d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 2; 1211d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1212d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 1; 1213d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1214d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1215d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels, max_channels); 121633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 121733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 121833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1219db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported buffer sizes 1220db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg * (can be used as 3*8192, 6*4096, 12*2048, ...) */ 1221db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_BUFFER_BYTES, 1222db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 8192*3, 8192*3); 122383a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg if (err < 0) 122483a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg return err; 122583a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg 1226db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported block sizes: */ 1227db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1228db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg ARRAY_NELEMS(period_list), period_list); 1229b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1231b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1232d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* supported rates */ 1233d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count = 0; 1234d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_16000) { 1235d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_list[rate_count] = 16000; 1236d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 1237ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz } 1238ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 1239d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_32000) { 1240d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_list[rate_count] = 32000; 1241d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 1242c4e21c814832ea94f64821a2360a28074d03be1aJohan Hedberg } 1243ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 1244d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_44100) { 1245d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_list[rate_count] = 44100; 1246d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 12476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 124800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1249d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & BT_A2DP_SAMPLING_FREQ_48000) { 1250d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_list[rate_count] = 48000; 1251d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 1252d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 125300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1254d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1255db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg rate_count, rate_list); 1256d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1257d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 12596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 12606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 12616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1262d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf, 1263d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *bt_config) 12646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 126592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_iterator_t i, next; 1266f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann const char *addr, *pref; 1267f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann const char *mode, *allocation, *rate, *subbands, *blocks, *bitpool; 126892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1269d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(bt_config, 0, sizeof(struct bluetooth_alsa_config)); 1270ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg 127192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_for_each(i, next, conf) { 127292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_t *n = snd_config_iterator_entry(i); 127392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann const char *id; 127492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 127592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_id(n, &id) < 0) 127692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 127792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 127892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) 127992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 128092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1281b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) { 128292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_string(n, &addr) < 0) { 128392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 128492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 128592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1286b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1287d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_device = 1; 1288d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strncpy(bt_config->device, addr, 18); 128992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 129092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 129192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1292b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "profile") == 0) { 129392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_string(n, &pref) < 0) { 129492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 129592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 129692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1297b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (strcmp(pref, "auto") == 0) { 1299d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1300d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1301d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else if (strcmp(pref, "voice") == 0 || 130241b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz strcmp(pref, "hfp") == 0) { 1303d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO; 1304d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1305f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann } else if (strcmp(pref, "hifi") == 0 || 1306d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strcmp(pref, "a2dp") == 0) { 1307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 1308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1309d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 131092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 131192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 131292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 13135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "rate") == 0) { 13145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &rate) < 0) { 13155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1319d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->rate = atoi(rate); 1320d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_rate = 1; 13215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13235402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 132441b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz if (strcmp(id, "mode") == 0) { 13255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &mode) < 0) { 13265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13295402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 133072947933a64f92a798567e74e75c0222375ae599Brad Midgley if (strcmp(mode, "auto") == 0) { 1331d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_AUTO; 1332d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 133372947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(mode, "mono") == 0) { 1334d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 1335d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 133672947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(mode, "dual") == 0) { 1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 1338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 133972947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(mode, "stereo") == 0) { 1340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 1341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 134272947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(mode, "joint") == 0) { 1343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 1344d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1345d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 13465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13475402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 13495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "allocation") == 0) { 13505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &allocation) < 0) { 13515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13525402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 135572947933a64f92a798567e74e75c0222375ae599Brad Midgley if (strcmp(allocation, "auto") == 0) { 1356d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_AUTO; 1357d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 135872947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(allocation, "loudness") == 0) { 1359d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 1360d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 136172947933a64f92a798567e74e75c0222375ae599Brad Midgley } else if (strcmp(allocation, "snr") == 0) { 1362d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR; 1363d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1364d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 13655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 13685402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "subbands") == 0) { 13695402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &subbands) < 0) { 13705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->subbands = atoi(subbands); 1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_subbands = 1; 13765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 13795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "blocks") == 0) { 13805402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &blocks) < 0) { 13815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13845402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->block_length = atoi(blocks); 1386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_block_length = 1; 13875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 13905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "bitpool") == 0) { 13915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (snd_config_get_string(n, &bitpool) < 0) { 13925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 13935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 13945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 13955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->bitpool = atoi(bitpool); 1397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_bitpool = 1; 13985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 13995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 140192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Unknown field %s", id); 140292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 140392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 140492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return 0; 14065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz} 14075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg) 14095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{ 1410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 14116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1412d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending %s", bt_audio_strmsg(msg->msg_type)); 1413d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (send(sk, msg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) 1414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else { 1416d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error sending data to audio service: %s(%d)", 1418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 14198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1420b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 14236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1424d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) 1425d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz const char *type; 1428d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1429d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("trying to receive msg from audio service..."); 1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (recv(sk, inmsg, BT_AUDIO_IPC_PACKET_SIZE, 0) > 0) { 1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz type = bt_audio_strmsg(inmsg->msg_type); 1432d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (type) { 1433d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("Received %s", type); 1434d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1435d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -EINVAL; 1437d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Bogus message type %d " 1438d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz "received from audio service", 1439d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz inmsg->msg_type); 1440d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1441d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1443d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error receiving data from audio service: %s(%d)", 1444d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 14456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 14468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1448d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 1449dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg 1450d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp_hdr, 1451d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int expected_type) 1452d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 1453d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz int err = audioservice_recv(sk, rsp_hdr); 1454d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err == 0) { 1455d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz if (rsp_hdr->msg_type != expected_type) { 1456d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -EINVAL; 1457d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Bogus message %s received while " 1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz "%s was expected", 1459d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz bt_audio_strmsg(rsp_hdr->msg_type), 1460d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_strmsg(expected_type)); 1461d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1462f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 1463d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 14648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 14658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1466ec384afacde8614306abe32cf40c55b795783f0eJohan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, 1467ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg snd_config_t *conf) 14688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 14696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int sk, err; 1470d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *alsa_conf = &data->alsa_config; 1471d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz char buf[BT_AUDIO_IPC_PACKET_SIZE]; 1472d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz bt_audio_rsp_msg_header_t *rsp_hdr = (void*) buf; 1473d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bt_getcapabilities_req *getcaps_req = (void*) buf; 1474d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bt_getcapabilities_rsp *getcaps_rsp = (void*) buf; 1475f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 147600c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 147700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1478d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = bluetooth_parse_config(conf, alsa_conf); 1479d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1481d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1482e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = -1; 1483dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg data->stream.fd = -1; 148400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1485d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sk = bt_audio_service_open(); 1486d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if(sk <= 0) { 1487d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1488d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1489b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1490b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1491e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = sk; 1492e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.events = POLLIN; 1493b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1494892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[0] = -1; 1495892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[1] = -1; 1496892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1497d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (pipe(data->pipefd) < 0) { 1498d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1499d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1500d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1501d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) { 1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1503d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1504d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1505d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) { 1506d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1508d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1509d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1510d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(getcaps_req, 0, BT_AUDIO_IPC_PACKET_SIZE); 1511d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz getcaps_req->h.msg_type = BT_GETCAPABILITIES_REQ; 1512d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strncpy(getcaps_req->device, alsa_conf->device, 18); 1513d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (alsa_conf->has_transport) 1514d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz getcaps_req->transport = alsa_conf->transport; 1515d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1516d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz getcaps_req->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1517721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = audioservice_send(data->server.fd, &getcaps_req->h); 1519d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1520d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1521d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1522d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &rsp_hdr->msg_h, BT_GETCAPABILITIES_RSP); 1523d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1525d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1526d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz if (rsp_hdr->posix_errno != 0) { 1527d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("BT_GETCAPABILITIES failed : %s(%d)", 1528d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz strerror(rsp_hdr->posix_errno), 1529d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz rsp_hdr->posix_errno); 1530d51c190ddd0c2774509d0284979b24b9b0f3524aLuiz Augusto von Dentz return -rsp_hdr->posix_errno; 1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1532d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1533d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->transport = getcaps_rsp->transport; 1534721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 1535d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (getcaps_rsp->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 1536d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->a2dp.sbc_capabilities = getcaps_rsp->sbc_capabilities; 1537892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1538d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 1539d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1540d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed: 1541d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_service_close(sk); 1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 15438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 15448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 15458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 15468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1547f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 15488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 15498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 155000c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 15518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 15528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1553d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg data = malloc(sizeof(struct bluetooth_data)); 155400c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 155500c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 155600c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 155700c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 155800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1559ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg err = bluetooth_init(data, stream, conf); 15608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 15618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 15628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1563f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 1564f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 156500c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 1566f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 1567b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1568d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 15696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 15706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_playback : 15716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_capture; 15726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 15736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 15746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_playback : 15756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_capture; 15766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1577f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 1578b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1579b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 1580b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1581d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 158233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_a2dp_hw_constraint(&data->io); 158333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz else 158433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_hsp_hw_constraint(&data->io); 158533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1586b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 1587f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 15888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 1589b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1590b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1591f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 1592b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1593b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 1594b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1595b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 15965ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 15975ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 1598b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 15995ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 16005ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 16015ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 1602