1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/* 2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 55592142cb9383df0556b27ac59e96547b380310bJohan Hedberg * Copyright (C) 2006-2010 Nokia Corporation 69184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann * Copyright (C) 2004-2010 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> 36a1ddddc934657aa734ceb4bf581423647cc68060Marcel Holtmann#include <limits.h> 376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h> 39b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 405ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h> 415ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h> 425ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 43b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h" 446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h" 45347675ea994642c0ccd60f7af70f369f7a2d7a88Luiz Augusto von Dentz#include "rtp.h" 466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 473d586da1dd17ca73a4bd4a5cad9284a331860042Szymon Janc/* #define ENABLE_DEBUG */ 486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 49714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg#define UINT_SECS_MAX (UINT_MAX / 1000000 - 1) 50714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg 51e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz#define MIN_PERIOD_TIME 1 52714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg 53f5befe8ab54b797a0a5357ceddf2f05ab0ff163cJohan Hedberg#define BUFFER_SIZE 2048 54b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 55f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG 56b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...) printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg) 57f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else 58f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...) 59f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif 60b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 6197c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#ifndef SOL_SCO 6297c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#define SOL_SCO 17 6397c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann#endif 6497c120e3f1425d9c431c12167ca4684a0af5f844Marcel Holtmann 658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS 668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03 678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS 708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04 718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MIN 742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MIN(x, y) ((x) < (y) ? (x) : (y)) 752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif 762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#ifndef MAX 782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz# define MAX(x, y) ((x) > (y) ? (x) : (y)) 792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#endif 802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MAX_BITPOOL 64 822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz#define MIN_BITPOOL 2 832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 84d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg/* adapted from glibc sys/time.h timersub() macro */ 85d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg#define priv_timespecsub(a, b, result) \ 86d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg do { \ 87d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 88d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \ 89d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg if ((result)->tv_nsec < 0) { \ 90d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg --(result)->tv_sec; \ 91d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg (result)->tv_nsec += 1000000000; \ 92d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg } \ 93d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg } while (0) 94344e38a9616a11072a123dacb70daf6ab69d5270Johan Hedberg 956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp { 96d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sbc_capabilities_t sbc_capabilities; 97d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sbc_t sbc; /* Codec data */ 98d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int sbc_initialized; /* Keep track if the encoder is initialized */ 990d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int codesize; /* SBC codesize */ 100d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int samples; /* Number of encoded samples */ 101d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t buffer[BUFFER_SIZE]; /* Codec transfer buffer */ 1020d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int count; /* Codec transfer buffer counter */ 103d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 104d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int nsamples; /* Cumulative number of codec samples */ 105d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint16_t seq_num; /* Cumulative packet sequence */ 106d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int frame_count; /* Current frames in buffer*/ 107d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz}; 108d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 109d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstruct bluetooth_alsa_config { 110d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz char device[18]; /* Address of the remote Device */ 111d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_device; 112d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t transport; /* Requested transport */ 113d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_transport; 114d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint16_t rate; 115d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_rate; 116d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t channel_mode; /* A2DP only */ 117d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_channel_mode; 118d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t allocation_method; /* A2DP only */ 119d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_allocation_method; 120d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t subbands; /* A2DP only */ 121d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_subbands; 122d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t block_length; /* A2DP only */ 123d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_block_length; 124d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t bitpool; /* A2DP only */ 125d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int has_bitpool; 1269fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg int autoconnect; 1276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 1286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data { 130b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_ioplug_t io; 131d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config alsa_config; /* ALSA resource file parameters */ 132e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg volatile snd_pcm_sframes_t hw_ptr; 133d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int transport; /* chosen transport SCO or AD2P */ 1340d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int link_mtu; /* MTU for selected transport channel */ 135d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz volatile struct pollfd stream; /* Audio stream filedescriptor */ 136d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct pollfd server; /* Audio daemon filedescriptor */ 137d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint8_t buffer[BUFFER_SIZE]; /* Encoded transfer buffer */ 1380d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int count; /* Transfer buffer counter */ 139d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp a2dp; /* A2DP data */ 140d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 141d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_t hw_thread; /* Makes virtual hw pointer move */ 142d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int pipefd[2]; /* Inter thread communication */ 143892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz int stopped; 144cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg sig_atomic_t reset; /* Request XRUN handling */ 145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 146b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 147d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg); 148d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *outmsg, 149a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann int expected_type); 150d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 151b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io) 152b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1539217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_start %p", io); 154b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 155b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 156b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 157b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 158b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io) 159b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1609217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_stop %p", io); 161b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 162b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 163b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 164b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 165892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic void *playback_hw_thread(void *param) 166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = param; 168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int prev_periods; 169e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg double period_time; 170d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg struct timespec start; 171e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz struct pollfd fds[2]; 1723e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg int poll_timeout; 173e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz 174dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->server.events = POLLIN; 175dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* note: only errors for data->stream.events */ 176dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 177e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz fds[0] = data->server; 178e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz fds[1] = data->stream; 179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg prev_periods = 0; 181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg period_time = 1000000.0 * data->io.period_size / data->io.rate; 1823e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg if (period_time > (int) (MIN_PERIOD_TIME * 1000)) 1833e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg poll_timeout = (int) (period_time / 1000.0f); 1843e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg else 1853e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg poll_timeout = MIN_PERIOD_TIME; 186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 187d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 189e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg while (1) { 190714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg unsigned int dtime, periods; 191d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg struct timespec cur, delta; 192e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz int ret; 193e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 194892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->stopped) 195f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg goto iter_sleep; 196f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 197dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (data->reset) { 198dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Handle XRUN in hw-thread."); 199dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 0; 200d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 201dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg prev_periods = 0; 202dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 203dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 204d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &cur); 205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 206d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg priv_timespecsub(&cur, &start, &delta); 207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 208d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg dtime = delta.tv_sec * 1000000 + delta.tv_nsec / 1000; 209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg periods = 1.0 * dtime / period_time; 210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (periods > prev_periods) { 212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 213dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg int frags = periods - prev_periods, n; 214e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 215dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->hw_ptr += frags * data->io.period_size; 216e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data->hw_ptr %= data->io.buffer_size; 217e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 218dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg for (n = 0; n < frags; n++) { 219dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Notify user that hardware pointer 220dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg * has moved * */ 221dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (write(data->pipefd[1], &c, 1) < 0) 222dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg pthread_testcancel(); 223dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 224e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 225714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg /* Reset point of reference to avoid too big values 226714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg * that wont fit an unsigned int */ 227b47d1eeb490aa518b0bafb0fe5d968e4ef313e60Marcel Holtmann if ((unsigned int) delta.tv_sec < UINT_SECS_MAX) 2288dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg prev_periods = periods; 2298dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg else { 230714cd0ab444bd51731131866463f5c565c8a33f6Johan Hedberg prev_periods = 0; 231d00d4028e7a30da863489e822935ef6d7dc91242Johan Hedberg clock_gettime(CLOCK_MONOTONIC, &start); 2328dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg } 233de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 234e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 235f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedbergiter_sleep: 2363e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg /* sleep up to one period interval */ 2373e1e3e3679cbe30eb8a2cf7905d709b658c4c1adJohan Hedberg ret = poll(fds, 2, poll_timeout); 238dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 239e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (ret < 0) { 24050c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier if (errno != EINTR) { 24150c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier SNDERR("poll error: %s (%d)", strerror(errno), 24250c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier errno); 243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 24450c1564d86f8a0275e268d7cd67ad22883b248bbColin Didier } 245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } else if (ret > 0) { 246e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz ret = (fds[0].revents) ? 0 : 1; 247e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz SNDERR("poll fd %d revents %d", ret, fds[ret].revents); 248db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL)) 249e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 250e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } 251e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 252e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Offer opportunity to be canceled by main thread */ 253de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz pthread_testcancel(); 254e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 255e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz 256e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->hw_thread = 0; 257e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pthread_exit(NULL); 258e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 25933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 260892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io) 261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 263e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int err; 264e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 265e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 266e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 267892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 0; 268f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 269892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) 270f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg return 0; 271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 272892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data); 273e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -err; 275e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 277892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io) 278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 279e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 281e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 283892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 1; 284e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 2857090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg return 0; 286e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 287e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io) 289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return data->hw_ptr; 293b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 294b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2955ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data) 2965ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{ 297892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 298892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 299e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->server.fd >= 0) 300d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_service_close(data->server.fd); 3015ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 302e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->stream.fd >= 0) 303e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz close(data->stream.fd); 3042a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz 305892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) { 306892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 307892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 308892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 309f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 310d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 311f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg sbc_finish(&a2dp->sbc); 312d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz 313892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[0] > 0) 314892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[0]); 315de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 316892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[1] > 0) 317892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[1]); 318de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 3195ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz free(data); 3205ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz} 3215ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 322b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io) 323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 324b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("%p", io); 327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3285ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 329b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 330b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 331b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 332b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 3348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 3358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 336e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 3371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 338cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_start_stream_req *req = (void *) buf; 339cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_start_stream_rsp *rsp = (void *) buf; 340cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_new_stream_ind *ind = (void *) buf; 341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int opt_name, err; 343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct timeval t = { 0, period_count }; 3448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 34538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 34638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann io->period_size, io->buffer_size); 3478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 348dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 0; 349dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* As we're gonna receive messages on the server socket, we have to stop the 351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz hw thread that is polling on it, if any */ 352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->hw_thread) { 353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 355d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_thread = 0; 356d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 357d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3589217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg if (io->stream == SND_PCM_STREAM_PLAYBACK) 35900c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* If not null for playback, xmms doesn't display time 36000c71248e732de0230c12df4240087a6b2747179Johan Hedberg * correctly */ 3618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 3629217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg else 36300c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* ALSA library is really picky on the fact hw_ptr is not null. 36400c71248e732de0230c12df4240087a6b2747179Johan Hedberg * If it is, capture won't start */ 3658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 3669217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* send start */ 3681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 3691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.type = BT_REQUEST; 3701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.name = BT_START_STREAM; 3711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.length = sizeof(*req); 3728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = audioservice_send(data->server.fd, &req->h); 374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3771c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = sizeof(*rsp); 3781c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 3791c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_START_STREAM); 380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3831c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg ind->h.length = sizeof(*ind); 3841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &ind->h, 3851c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_NEW_STREAM); 386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd >= 0) 390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz close(data->stream.fd); 391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->stream.fd = bt_audio_service_get_data_fd(data->server.fd); 393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd < 0) { 394d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 3969217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 399d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SO_SNDTIMEO : SO_RCVTIMEO; 400ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t, 402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sizeof(t)) < 0) 403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 404d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 405d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 40638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SCO_TXBUFS : SCO_RXBUFS; 4078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 40938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4119217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 412d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 41338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SO_SNDBUF : SO_RCVBUF; 41400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 41638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4187090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg 419d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* FIXME : handle error codes */ 420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 42100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 422d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* wake up any client polling at us */ 423165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann err = write(data->pipefd[1], &c, 1); 424165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann if (err < 0) 425165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann return err; 426165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann 427165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann return 0; 4288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, 431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 432721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{ 433721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 4341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 435bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_req *open_req = (void *) buf; 436bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_rsp *open_rsp = (void *) buf; 437cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 438cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz int err; 440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 442721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->period_size, io->buffer_size); 443721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 444450e5656a8de08051f221d63e026c259151ef274Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 445bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.type = BT_REQUEST; 446bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.name = BT_OPEN; 447bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.length = sizeof(*open_req); 448bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 449bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz strncpy(open_req->destination, data->alsa_config.device, 18); 450bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->seid = BT_A2DP_SEID_RANGE + 1; 451bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ? 452bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_WRITE_LOCK : BT_READ_LOCK); 453bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 454bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_send(data->server.fd, &open_req->h); 455bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 456bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 457bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 458bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_rsp->h.length = sizeof(*open_rsp); 459bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_expect(data->server.fd, &open_rsp->h, 460bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_OPEN); 461bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 462bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 463bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 464bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 465450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.type = BT_REQUEST; 466450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 467450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length = sizeof(*req); 4681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 469450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO; 470bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz req->codec.seid = BT_A2DP_SEID_RANGE + 1; 471450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.length = sizeof(pcm_capabilities_t); 472721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 473450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 474450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 475721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 476721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 477721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 478450e5656a8de08051f221d63e026c259151ef274Johan Hedberg rsp->h.length = sizeof(*rsp); 479450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 4801c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 481721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 482721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 483721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 484bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz data->transport = BT_CAPABILITIES_TRANSPORT_SCO; 485450e5656a8de08051f221d63e026c259151ef274Johan Hedberg data->link_mtu = rsp->link_mtu; 486721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 487721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return 0; 488721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz} 489721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) 4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (freq) { 493489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_16000: 494489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_32000: 4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 496489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_44100: 4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 31; 5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 5062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 508489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_48000: 5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 29; 5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid sampling freq %u", freq); 5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5242934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data, 527a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_hw_params_t *params) 5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 5298fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 5308fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities; 5318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz unsigned int max_bitpool, min_bitpool, rate, channels; 5328fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int dir; 5338fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 5348fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_rate(params, &rate, &dir); 5358fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_channels(params, &channels); 5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (rate) { 5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 48000: 539489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_48000; 5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 44100: 542489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_44100; 5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 32000: 545489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_32000; 5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 16000: 548489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_16000; 5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Rate %d not supported", rate); 5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5532934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5542934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 5568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode = cfg->channel_mode; 5578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (channels == 2) { 5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } else { 5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (!cap->channel_mode) { 5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported channel modes"); 5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_block_length) 5758fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->block_length = cfg->block_length; 5768fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) 5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_16; 5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) 5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_12; 5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) 5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_8; 5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) 5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_4; 5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported block lengths"); 5862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5872934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_subbands) 5908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->subbands = cfg->subbands; 5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->subbands & BT_A2DP_SUBBANDS_8) 5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_8; 5932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->subbands & BT_A2DP_SUBBANDS_4) 5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_4; 5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported subbands"); 5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_allocation_method) 6018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->allocation_method = cfg->allocation_method; 6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) 6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) 6052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_SNR; 6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_bitpool) 6088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = max_bitpool = cfg->bitpool; 6098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else { 6108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool); 6118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz max_bitpool = MIN(default_bitpool(cap->frequency, 6128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode), 6138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->max_bitpool); 6148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->min_bitpool = min_bitpool; 6172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->max_bitpool = max_bitpool; 6182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 0; 6202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 6212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp) 623afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{ 6248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities; 625afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 626d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 6272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_reinit(&a2dp->sbc, 0); 6282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else 6292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_init(&a2dp->sbc, 0); 630d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc_initialized = 1; 6312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 632489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000) 63323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_16000; 634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 635489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000) 63623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_32000; 637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 638489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100) 63923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_44100; 640d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 641489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000) 64223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_48000; 643d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 64523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_MONO; 646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 64723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 64823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; 64923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 65123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_STEREO; 65223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 65323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 65423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; 655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation = active_capabilities.allocation_method 65723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR 65823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz : SBC_AM_LOUDNESS; 659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.subbands) { 661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_4: 66223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_4; 663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_8: 66523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_8; 666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.block_length) { 670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_4: 67123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_4; 672d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_8: 67423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_8; 675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_12: 67723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_12; 678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_16: 68023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_16; 681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool = active_capabilities.max_bitpool; 6858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->codesize = sbc_get_codesize(&a2dp->sbc); 686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 6878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz} 6888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, 6908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 6918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{ 6928fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 6938fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 6941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 695bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_req *open_req = (void *) buf; 696bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_rsp *open_rsp = (void *) buf; 697cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 698cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 6998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int err; 7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 7028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz io->period_size, io->buffer_size); 7038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 704bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 705bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.type = BT_REQUEST; 706bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.name = BT_OPEN; 707bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.length = sizeof(*open_req); 708bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 709bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz strncpy(open_req->destination, data->alsa_config.device, 18); 710bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->seid = a2dp->sbc_capabilities.capability.seid; 711bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ? 712bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_WRITE_LOCK : BT_READ_LOCK); 713bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 714bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_send(data->server.fd, &open_req->h); 715bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 716bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 717bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 718bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_rsp->h.length = sizeof(*open_rsp); 719bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_expect(data->server.fd, &open_rsp->h, 720bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_OPEN); 721bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 722bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 723bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 7248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz err = bluetooth_a2dp_init(data, params); 7258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7278fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7281c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 7291c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 7301c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 7311c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 7321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 7331c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memcpy(&req->codec, &a2dp->sbc_capabilities, 7341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg sizeof(a2dp->sbc_capabilities)); 7351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 7361c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP; 7371c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.length = sizeof(a2dp->sbc_capabilities); 7381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 7398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 7418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7428fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7438fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7441c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = sizeof(*rsp); 7451c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 7461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 7478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 750bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz data->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 7511c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg data->link_mtu = rsp->link_mtu; 7528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz /* Setup SBC encoder now we agree on parameters */ 7548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz bluetooth_a2dp_setup(a2dp); 755d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 756d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", 757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks, 758d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool); 759d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 760d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 761afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz} 762afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, 764f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann struct pollfd *pfd, unsigned int space) 765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(io); 769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 773e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pfd[0].fd = data->stream.fd; 774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 776e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 779e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 780e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED, 781e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, unsigned int nfds, 782dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds && nfds == 1 && revents); 785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = pfds[0].revents; 787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 789e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 790e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 79137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io) 79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{ 79337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 79437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz} 79537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 796892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io, 79738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfd, unsigned int space) 798e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 799e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 800e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 801e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 803892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz assert(data->pipefd[0] >= 0); 804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 80537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (space < 2) 806e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 807e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 808892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pfd[0].fd = data->pipefd[0]; 809e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 810e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 81137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].fd = data->stream.fd; 81237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].events = POLLERR | POLLHUP | POLLNVAL; 81337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].revents = 0; 814e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 81537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 816e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 817e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 818892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io, 81938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfds, unsigned int nfds, 820dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 821e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 822e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg static char buf[1]; 823e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 824e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 825e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 826e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds); 82737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(nfds == 2); 828e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(revents); 829e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds[0].fd >= 0); 83037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(pfds[1].fd >= 0); 831e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 832e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (io->state != SND_PCM_STATE_PREPARED) 83310a0350126bb517c36ac1d0d95e4995b6e303d8fSzymon Janc if (read(pfds[0].fd, buf, 1) < 0) 83410a0350126bb517c36ac1d0d95e4995b6e303d8fSzymon Janc SYSERR("read error: %s (%d)", strerror(errno), errno); 835e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 83637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) 83737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz io->state = SND_PCM_STATE_DISCONNECTED; 83837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 839593bd41ed861d80f498fa8cfe0cea06e0c11f442Johan Hedberg *revents = (pfds[0].revents & POLLIN) ? POLLOUT : 0; 840e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 841e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 842e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 843e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 844e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, 84638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 847dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 848dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 8508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 85100c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 85200c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 8530d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int frame_size = 0; 8540d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann int nrecv; 8558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 85638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u", 85738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 8588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8593709666344736da68472f754ac52edc356039058Johan Hedberg frame_size = areas->step / 8; 8603709666344736da68472f754ac52edc356039058Johan Hedberg 86100c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 86200c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 86300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 864d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz nrecv = recv(data->stream.fd, data->buffer, data->link_mtu, 865474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg io->nonblock ? MSG_DONTWAIT : 0); 86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 86700c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 86800c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 86900c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 8720d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann if ((unsigned int) nrecv != data->link_mtu) { 87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 87400c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 87500c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 8778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 87800c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 879d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % 880721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->buffer_size; 88100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 88200c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 8836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (unsigned char *) areas->addr + 8846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 886d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 88700c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 88800c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 889d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_write = (data->link_mtu - data->count) / frame_size; 89000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 891f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(buff, data->buffer + data->count, frame_size * frames_to_write); 892f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->count += (frame_size * frames_to_write); 893d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->count %= data->link_mtu; 89400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 89500c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 89600c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 89700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 89800c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 89900c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 9008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 9018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 9028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, 90438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 905dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 906dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 9078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 9088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 9098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 9108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 911c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz uint8_t *buff; 912f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int rsend, frame_size; 9138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 91438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u", 91538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 9168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 917892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (io->hw_ptr > io->appl_ptr) { 918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 919892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (ret == 0) 920892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = -EPIPE; 921892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz goto done; 922892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 923892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 924f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 925d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 9268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 9278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 928d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_read = (data->link_mtu - data->count) / frame_size; 9298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 93038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("count=%d frames_to_read=%lu", data->count, frames_to_read); 931c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 9328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 935f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(data->buffer + data->count, buff, frame_size * frames_to_read); 9368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 9382a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz data->count += frames_to_read * frame_size; 939d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->count != data->link_mtu) { 9408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 94100c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 9428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 9438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 944d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rsend = send(data->stream.fd, data->buffer, data->link_mtu, 945c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz io->nonblock ? MSG_DONTWAIT : 0); 94600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 94700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 94800c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 94900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 95000c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 95100c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 95200c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 95300c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 95400c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 95500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 95600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 957892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz DBG("returning %ld", ret); 9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io, 96238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 963a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t ret = 0; 9666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 969e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data) 9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 971e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret = 0; 9726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_header *header; 9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_payload *payload; 9749494c146cec1df466c2f331957748beeac8d745aJohan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header = (void *) a2dp->buffer; 9776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload = (void *) (a2dp->buffer + sizeof(*header)); 9786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); 9806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload->frame_count = a2dp->frame_count; 9826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->v = 2; 9836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->pt = 1; 9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->sequence_number = htons(a2dp->seq_num); 9856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->timestamp = htonl(a2dp->nsamples); 9866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->ssrc = htonl(1); 9876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 988bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); 989dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (ret < 0) { 990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("send returned %d errno %s.", ret, strerror(errno)); 991e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -errno; 992dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 9938905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 9946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reset buffer of data to send */ 9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 9966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count = 0; 9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples = 0; 9986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->seq_num++; 9996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1000f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg return ret; 10016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 10026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 10036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io, 100438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 100538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 10066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 10076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_data *data = io->private_data; 10086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 10096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_sframes_t ret = 0; 10100d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int bytes_left; 1011c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering int frame_size, encoded; 101265c9310f96fa78980196002fdf11e8d30b4fe6b6Johan Hedberg ssize_t written; 10136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t *buff; 10146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 101538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu", 101638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size); 1017dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr, 1018dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg io->appl_ptr - io->hw_ptr); 1019e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 1020bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Calutate starting pointers */ 1021bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann frame_size = areas->step / 8; 1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = size * frame_size; 1023bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff = (uint8_t *) areas->addr + 1024bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann (areas->first + areas->step * (offset)) / 8; 1025bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1026bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check for underrun */ 1027cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->hw_ptr > io->appl_ptr) { 1028892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 1029de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz if (ret == 0) 1030e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -EPIPE; 1031dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 1; 1032bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 1033de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 1034e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 1035e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Check if we should autostart */ 1036cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->state == SND_PCM_STATE_PREPARED) { 1037e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_t *swparams; 1038e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_uframes_t threshold; 1039de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 1040e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_malloc(&swparams); 104138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann if (!snd_pcm_sw_params_current(io->pcm, swparams) && 1042dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg !snd_pcm_sw_params_get_start_threshold(swparams, 1043dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg &threshold)) { 1044cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->appl_ptr >= threshold) { 1045e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = snd_pcm_start(io->pcm); 1046cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret != 0) 1047bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 1048e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1049e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1050dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1051de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz snd_pcm_sw_params_free(swparams); 1052e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 10536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check if we have any left over data from the last write */ 105569b0d50a87f9786562de76c42045629b29304b27Colin Didier if (data->count > 0) { 105669b0d50a87f9786562de76c42045629b29304b27Colin Didier unsigned int additional_bytes_needed = 105769b0d50a87f9786562de76c42045629b29304b27Colin Didier a2dp->codesize - data->count; 105869b0d50a87f9786562de76c42045629b29304b27Colin Didier if (additional_bytes_needed > bytes_left) 105969b0d50a87f9786562de76c42045629b29304b27Colin Didier goto out; 10606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1061dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg memcpy(data->buffer + data->count, buff, 1062bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann additional_bytes_needed); 10636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1064dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Enough data to encode (sbc wants 1k blocks) */ 1065bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize, 1066fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz a2dp->buffer + a2dp->count, 1067fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz sizeof(a2dp->buffer) - a2dp->count, 1068bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1069dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (encoded <= 0) { 1070dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Encoding error %d", encoded); 1071dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg goto done; 1072dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 10736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1074bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1075397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->count += written; 1076397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->frame_count++; 1077397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->samples += encoded / frame_size; 1078397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->nsamples += encoded / frame_size; 10796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1080397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz /* No space left for another frame then send */ 1081d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->count + written >= data->link_mtu) { 1082dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg avdtp_write(data); 1083d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending packet %d, count %d, link_mtu %u", 1084d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->seq_num, a2dp->count, 1085bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1086bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += additional_bytes_needed; 1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= additional_bytes_needed; 1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1093bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Since data has been process mark it as zero */ 1094bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count = 0; 1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1098bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Process this buffer in full chunks */ 1099bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann while (bytes_left >= a2dp->codesize) { 1100bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Enough data to encode (sbc wants 1k blocks) */ 1101bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize, 1102bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->buffer + a2dp->count, 1103bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann sizeof(a2dp->buffer) - a2dp->count, 1104bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1105bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (encoded <= 0) { 1106bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("Encoding error %d", encoded); 1107bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann goto done; 1108f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 11096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1110bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1111bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1112bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += a2dp->codesize; 1113bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= a2dp->codesize; 1114bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1115bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1116bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->count += written; 1117bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->frame_count++; 1118bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->samples += encoded / frame_size; 1119bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->nsamples += encoded / frame_size; 1120bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1121bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* No space left for another frame then send */ 1122bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (a2dp->count + written >= data->link_mtu) { 1123bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann avdtp_write(data); 11248a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg DBG("sending packet %d, count %d, link_mtu %u", 1125bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->seq_num, a2dp->count, 1126bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1127bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1128dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 1129dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 113069b0d50a87f9786562de76c42045629b29304b27Colin Didierout: 1131bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Copy the extra to our temp buffer for the next write */ 1132bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (bytes_left > 0) { 1133bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann memcpy(data->buffer + data->count, buff, bytes_left); 1134bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count += bytes_left; 1135bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = 0; 1136bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 11376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 1139bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("returning %ld", size - bytes_left / frame_size); 1140bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1141bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return size - bytes_left / frame_size; 11428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 11438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 11446967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io, 11456967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg snd_pcm_sframes_t *delayp) 1146a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{ 1147a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley DBG(""); 1148a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 1149a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This updates io->hw_ptr value using pointer() function */ 1150a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley snd_pcm_hwsync(io->pcm); 11516967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1152a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = io->appl_ptr - io->hw_ptr; 1153a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) { 1154a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->callback->stop(io); 1155a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->state = SND_PCM_STATE_XRUN; 1156a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = 0; 1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley } 11586967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1159a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This should never fail, ALSA API is really not 1160a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley prepared to handle a non zero return value */ 1161a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley return 0; 1162a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley} 1163a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 11646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { 1165892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1166892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1169721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1170e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1171e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_write, 117237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1173892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1174892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1175a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 11766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { 1179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1182e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1183721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1184e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1185e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_read, 1186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1188b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1189b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 11906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = { 1191892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1192892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1193e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1194e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1195e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1196e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1197e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_write, 119837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1199892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1200892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1201a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 12026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 12036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 12046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = { 1205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_read, 1212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1213e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1214b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1215b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 121833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io) 1219b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1220c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1221b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 1222b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 1223b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 1224b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 1225b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 1226b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 1227b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1228b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 1229a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka SND_PCM_FORMAT_S16 1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1231d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 1232b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1233c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* access type */ 1234b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 1235b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 1236b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1237b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1238b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1239c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported formats */ 1240b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1241b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 1242b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1243b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1244b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1245c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported channels */ 1246c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1247d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1, 1); 1248b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1249b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1250b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 125135b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported rate */ 1252c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 1253d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 8000, 8000); 1254b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1255b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 125735b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported block size */ 1258c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1259d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->link_mtu, data->link_mtu); 1260b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1261b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1262b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1263c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1264f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann 2, 200); 126533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 126633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 126733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 126833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return 0; 126933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz} 127033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 127133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io) 127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{ 127333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1274d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 12758fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 127633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz snd_pcm_access_t access_list[] = { 127733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_RW_INTERLEAVED, 127833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* Mmap access is really useless fo this driver, but we 127933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * support it because some pieces of software out there 128033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * insist on using it */ 128133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_MMAP_INTERLEAVED 128233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 128333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz unsigned int format_list[] = { 1284a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka SND_PCM_FORMAT_S16 128533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 1286d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_list[4]; 1287d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_count; 1288d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err, min_channels, max_channels; 1289dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned int period_list[] = { 1290db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 2048, 1291db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */ 1292db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 8192 1293dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg }; 129433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 129533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* access type */ 129633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 129733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(access_list), access_list); 129833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 129933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 130033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 130133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported formats */ 130233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 130333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(format_list), format_list); 130433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 130533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 130633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 130733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported channels */ 13088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 13098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->sbc_capabilities.channel_mode = cfg->channel_mode; 13108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 13118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & 13128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_A2DP_CHANNEL_MODE_MONO) 1313d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 1; 1314d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1315d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 2; 131633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 13178fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & 13188fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz (~BT_A2DP_CHANNEL_MODE_MONO)) 1319d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 2; 1320d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1321d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 1; 1322d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1323d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1324d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels, max_channels); 132533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 132633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 132733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1328db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported buffer sizes 1329db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg * (can be used as 3*8192, 6*4096, 12*2048, ...) */ 1330cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg err = snd_pcm_ioplug_set_param_minmax(io, 1331cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg SND_PCM_IOPLUG_HW_BUFFER_BYTES, 1332cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg 8192*3, 8192*3); 133383a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg if (err < 0) 133483a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg return err; 133583a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg 1336db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported block sizes: */ 1337db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1338db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg ARRAY_NELEMS(period_list), period_list); 1339b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1340b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1341b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* supported rates */ 1343d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count = 0; 13448fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_rate) { 13458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = cfg->rate; 1346d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 13478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } else { 13488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_16000) { 13508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 16000; 13518fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1353ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 13548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_32000) { 13568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 32000; 13578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13588fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1359ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 13608fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13618fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_44100) { 13628fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 44100; 13638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 136500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 13668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_48000) { 13688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 48000; 13698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13708fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1371d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 137200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1374db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg rate_count, rate_list); 1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1377e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 13786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 13796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 13806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1381d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf, 1382d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *bt_config) 13836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 138492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_iterator_t i, next; 138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(bt_config, 0, sizeof(struct bluetooth_alsa_config)); 1387ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg 13889fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg /* Set defaults */ 13899fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg bt_config->autoconnect = 1; 13909fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 139192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_for_each(i, next, conf) { 139292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_t *n = snd_config_iterator_entry(i); 1393d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg const char *id, *value; 139492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 139592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_id(n, &id) < 0) 139692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 139792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 139892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) 139992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 140092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14019fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (strcmp(id, "autoconnect") == 0) { 1402a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg int b; 1403a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg 1404a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg b = snd_config_get_bool(n); 1405a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg if (b < 0) { 14069fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg SNDERR("Invalid type for %s", id); 14079fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg return -EINVAL; 14089fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 14099fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1410a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg bt_config->autoconnect = b; 14119fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg continue; 14129fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 14139fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1414b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) { 1415d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 141692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 141792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 141892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1419b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_device = 1; 1421d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strncpy(bt_config->device, value, 18); 142292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 142392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 142492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1425b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "profile") == 0) { 1426d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 142792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 142892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 142992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1430b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1431d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (strcmp(value, "auto") == 0) { 1432d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1433d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1434d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "voice") == 0 || 1435d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "hfp") == 0) { 1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO; 1437d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1438d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "hifi") == 0 || 1439d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "a2dp") == 0) { 1440d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 1441d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 144392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 144492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 144592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14465402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "rate") == 0) { 1447d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1452d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->rate = atoi(value); 1453d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_rate = 1; 14545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 145741b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz if (strcmp(id, "mode") == 0) { 1458d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "mono") == 0) { 1464d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 1465d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1466d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "dual") == 0) { 1467d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 1468d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1469d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "stereo") == 0) { 1470d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 1471d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1472d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "joint") == 0) { 1473d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 1474d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1475d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14795402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "allocation") == 0) { 1480d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14845402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "loudness") == 0) { 1486d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 1487d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1488d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "snr") == 0) { 1489d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR; 1490d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1491d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14955402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "subbands") == 0) { 1496d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1501d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->subbands = atoi(value); 1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_subbands = 1; 15035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 15045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 15065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "blocks") == 0) { 1507d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 15085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 15095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 15105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1512d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->block_length = atoi(value); 1513d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_block_length = 1; 15145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 15155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 15175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "bitpool") == 0) { 1518d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 15195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 15205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 15215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15225402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1523d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->bitpool = atoi(value); 1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_bitpool = 1; 15255402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 15265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 152892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Unknown field %s", id); 152992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 153092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 153192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 15325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return 0; 15335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz} 15345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1535d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg) 15365402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{ 1537d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 15381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 15391c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 15401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE; 15416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1542a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz DBG("sending %s:%s", bt_audio_strtype(msg->type), 1543a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz bt_audio_strname(msg->name)); 15441c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg if (send(sk, msg, length, 0) > 0) 1545d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1546d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else { 1547d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1548d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error sending data to audio service: %s(%d)", 1549d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 15508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1551b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1552d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1553d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 15546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1555d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) 1556d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 15577c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg int err; 15587c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg ssize_t ret; 15591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz const char *type, *name; 15601c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 15611c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 15621c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE; 1563d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1564d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("trying to receive msg from audio service..."); 15652f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg 15662f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg ret = recv(sk, inmsg, length, 0); 15672f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg if (ret < 0) { 15682f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg err = -errno; 15692f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg SNDERR("Error receiving IPC data from bluetoothd: %s (%d)", 15702f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg strerror(errno), errno); 15717c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg } else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) { 15722f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg SNDERR("Too short (%d bytes) IPC packet from bluetoothd", ret); 15732f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg err = -EINVAL; 15742f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg } else { 15751c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz type = bt_audio_strtype(inmsg->type); 15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz name = bt_audio_strname(inmsg->name); 15771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (type && name) { 15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz DBG("Received %s - %s", type, name); 1579d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1580d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1581d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -EINVAL; 15821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message type %d - name %d" 15832f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg " received from audio service", 15841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz inmsg->type, inmsg->name); 1585d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 15862f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg 15876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 15888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1589d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1590d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 1591dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg 15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp, 1593a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann int expected_name) 1594d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_error_t *error; 15961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int err = audioservice_recv(sk, rsp); 15971c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15981c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (err != 0) 15991c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return err; 16001c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->name != expected_name) { 16021c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = -EINVAL; 16031c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message %s received while %s was expected", 16041c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 16051c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(expected_name)); 16061c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 16071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16081c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->type == BT_ERROR) { 16091c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error = (void *) rsp; 16101c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("%s failed : %s(%d)", 16111c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 16121c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz strerror(error->posix_errno), 16131c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error->posix_errno); 16141c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -error->posix_errno; 1615f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 16161c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1617d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 16188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 16198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 16201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data, 16211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz struct bt_get_capabilities_rsp *rsp) 16221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{ 16231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int bytes_left = rsp->h.length - sizeof(*rsp); 16241c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec_capabilities_t *codec = (void *) rsp->data; 16251c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16261c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz data->transport = codec->transport; 16271c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16281c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP) 16291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 16301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16311c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz while (bytes_left > 0) { 1632379d756055f32d46fe7e09e1d89be1f780abb144Luiz Augusto von Dentz if ((codec->type == BT_A2DP_SBC_SINK) && 1633c5e75a5051967530f29f9fabfb8593ef2723d57eLuiz Augusto von Dentz !(codec->lock & BT_WRITE_LOCK)) 16341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz break; 16351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16361c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bytes_left -= codec->length; 16371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec = (void *) codec + codec->length; 16381c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 16391c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (bytes_left <= 0 || 16411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec->length != sizeof(data->a2dp.sbc_capabilities)) 16421c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -EINVAL; 16431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz memcpy(&data->a2dp.sbc_capabilities, codec, codec->length); 16451c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 16471c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz} 16481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1649a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmannstatic int bluetooth_init(struct bluetooth_data *data, 1650a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_stream_t stream, snd_config_t *conf) 16518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 16526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int sk, err; 1653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *alsa_conf = &data->alsa_config; 16541c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 1655cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_req *req = (void *) buf; 1656cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_rsp *rsp = (void *) buf; 1657f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 165800c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 165900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = bluetooth_parse_config(conf, alsa_conf); 1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1664e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = -1; 1665dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg data->stream.fd = -1; 166600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sk = bt_audio_service_open(); 1668e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley if (sk <= 0) { 1669d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1671b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1672b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1673e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = sk; 1674e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.events = POLLIN; 1675b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1676892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[0] = -1; 1677892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[1] = -1; 1678892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (pipe(data->pipefd) < 0) { 1680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) { 1684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1686d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1687d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) { 1688d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1689d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1690d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1691d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 16921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 16931c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 16941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_GET_CAPABILITIES; 16951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 16961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16979fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (alsa_conf->autoconnect) 16981c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->flags |= BT_FLAG_AUTOCONNECT; 16999bdf6ba0c50a3d5500e616b0f9d63a190692cc2cLuiz Augusto von Dentz strncpy(req->destination, alsa_conf->device, 18); 1700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (alsa_conf->has_transport) 17011c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = alsa_conf->transport; 1702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 17031c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1704721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 17051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 1706d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1707d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1708d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 17091c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = 0; 17101c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 17111c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg BT_GET_CAPABILITIES); 1712d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1713d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1714d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 17151c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg bluetooth_parse_capabilities(data, rsp); 1716892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1717d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 1718d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1719d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed: 17209d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg if (sk >= 0) 17219d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg bt_audio_service_close(sk); 1722d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 17238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 17248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1725ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth); 1726ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann 17278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 17288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1729f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 17308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 17318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 173200c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 17338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 17348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1735d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg data = malloc(sizeof(struct bluetooth_data)); 173600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 173700c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 173800c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 173900c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 174000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1741ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg err = bluetooth_init(data, stream, conf); 17428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 17438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 17448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1745f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 1746f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 174700c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 1748f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 1749b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1750d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 17516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 17526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_playback : 17536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_capture; 17546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 17556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 17566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_playback : 17576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_capture; 17586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1759f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 1760b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1761b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 1762b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1763d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 176433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_a2dp_hw_constraint(&data->io); 176533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz else 176633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_hsp_hw_constraint(&data->io); 176733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1768b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 1769f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 17708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 1771b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1772b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1773f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 1774b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1775b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 1776b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1777b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 177865aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg if (data) 177965aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg bluetooth_exit(data); 17805ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 1781b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 17825ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 17835ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 17845ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 1785