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 4738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann//#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) { 240e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz SNDERR("poll error: %s (%d)", strerror(errno), errno); 241e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (errno != EINTR) 242e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 243e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } else if (ret > 0) { 244e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz ret = (fds[0].revents) ? 0 : 1; 245e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz SNDERR("poll fd %d revents %d", ret, fds[ret].revents); 246db66c9850fba4892b0c676e2d4d94171dcbae344Marcel Holtmann if (fds[ret].revents & (POLLERR | POLLHUP | POLLNVAL)) 247e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz break; 248e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz } 249e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 250e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Offer opportunity to be canceled by main thread */ 251de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz pthread_testcancel(); 252e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 253e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz 254e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->hw_thread = 0; 255e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pthread_exit(NULL); 256e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 25733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 258892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_start(snd_pcm_ioplug_t *io) 259e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 260e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 261e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int err; 262e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 263e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 264e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 265892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 0; 266f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 267892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) 268f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg return 0; 269e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 270892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz err = pthread_create(&data->hw_thread, 0, playback_hw_thread, data); 271e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -err; 273e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 274e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 275892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_stop(snd_pcm_ioplug_t *io) 276e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 277e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 278e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 279e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 280e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 281892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->stopped = 1; 282e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 2837090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg return 0; 284e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 285e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io) 287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return data->hw_ptr; 291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2935ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data) 2945ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{ 295892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 296892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 297e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->server.fd >= 0) 298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_service_close(data->server.fd); 2995ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 300e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz if (data->stream.fd >= 0) 301e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz close(data->stream.fd); 3022a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz 303892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->hw_thread) { 304892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 305892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 306892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 307f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg 308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 309f883b95e5ca06f863a75a1e2b4d2ec071bb30112Johan Hedberg sbc_finish(&a2dp->sbc); 310d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz 311892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[0] > 0) 312892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[0]); 313de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 314892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (data->pipefd[1] > 0) 315892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz close(data->pipefd[1]); 316de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 3175ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz free(data); 3185ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz} 3195ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io) 321b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 322b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 323b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("%p", io); 325b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3265ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 327b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 328b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 329b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 330b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 3328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 3338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 334e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 3351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 336cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_start_stream_req *req = (void *) buf; 337cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_start_stream_rsp *rsp = (void *) buf; 338cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_new_stream_ind *ind = (void *) buf; 339d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int opt_name, err; 341d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct timeval t = { 0, period_count }; 3428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 34338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 34438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann io->period_size, io->buffer_size); 3458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 346dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 0; 347dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 348d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* As we're gonna receive messages on the server socket, we have to stop the 349d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz hw thread that is polling on it, if any */ 350d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->hw_thread) { 351d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_cancel(data->hw_thread); 352d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz pthread_join(data->hw_thread, 0); 353d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_thread = 0; 354d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 355d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3569217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg if (io->stream == SND_PCM_STREAM_PLAYBACK) 35700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* If not null for playback, xmms doesn't display time 35800c71248e732de0230c12df4240087a6b2747179Johan Hedberg * correctly */ 3598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 3609217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg else 36100c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* ALSA library is really picky on the fact hw_ptr is not null. 36200c71248e732de0230c12df4240087a6b2747179Johan Hedberg * If it is, capture won't start */ 3638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 3649217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* send start */ 3661c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 3671c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.type = BT_REQUEST; 3681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.name = BT_START_STREAM; 3691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz req->h.length = sizeof(*req); 3708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = audioservice_send(data->server.fd, &req->h); 372d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 373d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 374d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3751c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = sizeof(*rsp); 3761c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 3771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_START_STREAM); 378d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 379d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 3811c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg ind->h.length = sizeof(*ind); 3821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = audioservice_expect(data->server.fd, &ind->h, 3831c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_NEW_STREAM); 384d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 385d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 386d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 387d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd >= 0) 388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz close(data->stream.fd); 389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 390d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->stream.fd = bt_audio_service_get_data_fd(data->server.fd); 391d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->stream.fd < 0) { 392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 3949217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 395d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SO_SNDTIMEO : SO_RCVTIMEO; 398ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 399d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SOCKET, opt_name, &t, 400d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sizeof(t)) < 0) 401d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return -errno; 402d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 403d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 40438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SCO_TXBUFS : SCO_RXBUFS; 4058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 406d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 40738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 408d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4099217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 410d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 41138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann SO_SNDBUF : SO_RCVBUF; 41200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 413d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (setsockopt(data->stream.fd, SOL_SCO, opt_name, &period_count, 41438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann sizeof(period_count)) == 0) 415d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 4167090ecad23e84f232648368331cbf41e8d71b6c6Johan Hedberg 417d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* FIXME : handle error codes */ 418d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 41900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* wake up any client polling at us */ 421165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann err = write(data->pipefd[1], &c, 1); 422165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann if (err < 0) 423165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann return err; 424165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann 425165b6e46b5524e2ed623925fa45d80d11032e716Marcel Holtmann return 0; 4268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 428721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, 429721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 430721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz{ 431721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 4321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 433bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_req *open_req = (void *) buf; 434bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_rsp *open_rsp = (void *) buf; 435cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 436cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz int err; 438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 440721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->period_size, io->buffer_size); 441721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 442450e5656a8de08051f221d63e026c259151ef274Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 443bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.type = BT_REQUEST; 444bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.name = BT_OPEN; 445bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.length = sizeof(*open_req); 446bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 447bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz strncpy(open_req->destination, data->alsa_config.device, 18); 448bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->seid = BT_A2DP_SEID_RANGE + 1; 449bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ? 450bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_WRITE_LOCK : BT_READ_LOCK); 451bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 452bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_send(data->server.fd, &open_req->h); 453bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 454bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 455bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 456bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_rsp->h.length = sizeof(*open_rsp); 457bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_expect(data->server.fd, &open_rsp->h, 458bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_OPEN); 459bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 460bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 461bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 462bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 463450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.type = BT_REQUEST; 464450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 465450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length = sizeof(*req); 4661c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 467450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO; 468bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz req->codec.seid = BT_A2DP_SEID_RANGE + 1; 469450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.length = sizeof(pcm_capabilities_t); 470721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 471450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 472450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 473721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 474721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 475721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 476450e5656a8de08051f221d63e026c259151ef274Johan Hedberg rsp->h.length = sizeof(*rsp); 477450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 4781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 479721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 480721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 481721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 482bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz data->transport = BT_CAPABILITIES_TRANSPORT_SCO; 483450e5656a8de08051f221d63e026c259151ef274Johan Hedberg data->link_mtu = rsp->link_mtu; 484721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 485721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return 0; 486721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz} 487721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) 4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (freq) { 491489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_16000: 492489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_32000: 4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 494489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_44100: 4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 31; 4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5052934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 506489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_48000: 5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 5082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 5092934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 5102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 29; 5112934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 5122934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 5132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 5142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid sampling freq %u", freq); 5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5212934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data, 525a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_hw_params_t *params) 5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 5278fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 5288fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities; 5298fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz unsigned int max_bitpool, min_bitpool, rate, channels; 5308fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int dir; 5318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 5328fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_rate(params, &rate, &dir); 5338fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_channels(params, &channels); 5342934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5352934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (rate) { 5362934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 48000: 537489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_48000; 5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 44100: 540489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_44100; 5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 32000: 543489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_32000; 5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 16000: 546489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_16000; 5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Rate %d not supported", rate); 5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 5548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode = cfg->channel_mode; 5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (channels == 2) { 5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } else { 5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (!cap->channel_mode) { 5682934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported channel modes"); 5692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5728fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_block_length) 5738fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->block_length = cfg->block_length; 5748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) 5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_16; 5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) 5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_12; 5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) 5792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_8; 5802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) 5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_4; 5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported block lengths"); 5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_subbands) 5888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->subbands = cfg->subbands; 5892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->subbands & BT_A2DP_SUBBANDS_8) 5902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_8; 5912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->subbands & BT_A2DP_SUBBANDS_4) 5922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_4; 5932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported subbands"); 5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_allocation_method) 5998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->allocation_method = cfg->allocation_method; 6002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) 6012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 6022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) 6032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_SNR; 6042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_bitpool) 6068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = max_bitpool = cfg->bitpool; 6078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else { 6088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool); 6098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz max_bitpool = MIN(default_bitpool(cap->frequency, 6108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode), 6118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->max_bitpool); 6128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 6132934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6142934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->min_bitpool = min_bitpool; 6152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->max_bitpool = max_bitpool; 6162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 0; 6182934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 6192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6208fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp) 621afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{ 6228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities; 623afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 624d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 6252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_reinit(&a2dp->sbc, 0); 6262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else 6272934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_init(&a2dp->sbc, 0); 628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc_initialized = 1; 6292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 630489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000) 63123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_16000; 632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 633489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000) 63423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_32000; 635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 636489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100) 63723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_44100; 638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 639489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000) 64023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_48000; 641d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 64323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_MONO; 644d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 64523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 64623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; 64723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 64823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 64923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_STEREO; 65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 65123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 65223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; 653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation = active_capabilities.allocation_method 65523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR 65623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz : SBC_AM_LOUDNESS; 657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.subbands) { 659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_4: 66023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_4; 661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_8: 66323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_8; 664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.block_length) { 668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_4: 66923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_4; 670d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 671d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_8: 67223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_8; 673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_12: 67523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_12; 676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_16: 67823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_16; 679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool = active_capabilities.max_bitpool; 6838fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->codesize = sbc_get_codesize(&a2dp->sbc); 684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 6858fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz} 6868fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, 6888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 6898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{ 6908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 6918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 6921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 693bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_req *open_req = (void *) buf; 694bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz struct bt_open_rsp *open_rsp = (void *) buf; 695cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 696cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 6978fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int err; 6988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6998fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz io->period_size, io->buffer_size); 7018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 702bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 703bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.type = BT_REQUEST; 704bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.name = BT_OPEN; 705bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->h.length = sizeof(*open_req); 706bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 707bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz strncpy(open_req->destination, data->alsa_config.device, 18); 708bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->seid = a2dp->sbc_capabilities.capability.seid; 709bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_req->lock = (io->stream == SND_PCM_STREAM_PLAYBACK ? 710bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_WRITE_LOCK : BT_READ_LOCK); 711bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 712bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_send(data->server.fd, &open_req->h); 713bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 714bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 715bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 716bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz open_rsp->h.length = sizeof(*open_rsp); 717bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz err = audioservice_expect(data->server.fd, &open_rsp->h, 718bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz BT_OPEN); 719bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz if (err < 0) 720bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz return err; 721bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz 7228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz err = bluetooth_a2dp_init(data, params); 7238fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7261c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 7271c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 7281c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 7291c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 7301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 7311c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memcpy(&req->codec, &a2dp->sbc_capabilities, 7321c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg sizeof(a2dp->sbc_capabilities)); 7331c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 7341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP; 7351c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.length = sizeof(a2dp->sbc_capabilities); 7361c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 7378fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 7398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7408fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7421c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = sizeof(*rsp); 7431c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 7441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 7458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7468fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7478fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 748bd30e5535a6d713727f8f9433954dcb9dd4b7168Luiz Augusto von Dentz data->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 7491c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg data->link_mtu = rsp->link_mtu; 7508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7518fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz /* Setup SBC encoder now we agree on parameters */ 7528fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz bluetooth_a2dp_setup(a2dp); 753d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 754d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", 755d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks, 756d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool); 757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 758d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 759afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz} 760afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, 762f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann struct pollfd *pfd, unsigned int space) 763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 764e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 766e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(io); 767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 769e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 771e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pfd[0].fd = data->stream.fd; 772e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 773e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 774e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 776e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED, 779e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, unsigned int nfds, 780dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 781e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 782e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds && nfds == 1 && revents); 783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = pfds[0].revents; 785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 78937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io) 79037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{ 79137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz} 79337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 794892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io, 79538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfd, unsigned int space) 796e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 797e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 798e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 799e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 800e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 801892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz assert(data->pipefd[0] >= 0); 802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 80337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (space < 2) 804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 805e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 806892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pfd[0].fd = data->pipefd[0]; 807e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 808e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 80937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].fd = data->stream.fd; 81037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].events = POLLERR | POLLHUP | POLLNVAL; 81137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].revents = 0; 812e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 81337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 814e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 815e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 816892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io, 81738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfds, unsigned int nfds, 818dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 819e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 820e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg static char buf[1]; 821e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret; 822e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 823e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 824e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 825e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds); 82637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(nfds == 2); 827e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(revents); 828e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds[0].fd >= 0); 82937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(pfds[1].fd >= 0); 830e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 831e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (io->state != SND_PCM_STATE_PREPARED) 832e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = read(pfds[0].fd, buf, 1); 833e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 83437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) 83537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz io->state = SND_PCM_STATE_DISCONNECTED; 83637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 837593bd41ed861d80f498fa8cfe0cea06e0c11f442Johan Hedberg *revents = (pfds[0].revents & POLLIN) ? POLLOUT : 0; 838e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 839e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 840e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 841e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 842e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 8436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, 84438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 845dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 846dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 8488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 84900c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 85000c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 8510d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int frame_size = 0; 8520d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann int nrecv; 8538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 85438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u", 85538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 8568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8573709666344736da68472f754ac52edc356039058Johan Hedberg frame_size = areas->step / 8; 8583709666344736da68472f754ac52edc356039058Johan Hedberg 85900c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 86000c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 86100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 862d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz nrecv = recv(data->stream.fd, data->buffer, data->link_mtu, 863474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg io->nonblock ? MSG_DONTWAIT : 0); 86400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 86500c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 86700c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 86900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 8700d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann if ((unsigned int) nrecv != data->link_mtu) { 87100c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 87200c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 87300c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 8758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 87600c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 877d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % 878721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->buffer_size; 87900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 88000c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 8816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (unsigned char *) areas->addr + 8826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 88300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 884d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 88500c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 88600c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 887d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_write = (data->link_mtu - data->count) / frame_size; 88800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 889f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(buff, data->buffer + data->count, frame_size * frames_to_write); 890f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->count += (frame_size * frames_to_write); 891d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->count %= data->link_mtu; 89200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 89300c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 89400c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 89500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 89600c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 89700c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 8988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 8998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 9008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, 90238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 903dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 904dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 9058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 9068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 9078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 9088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 909c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz uint8_t *buff; 910f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int rsend, frame_size; 9118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 91238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u", 91338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 9148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 915892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (io->hw_ptr > io->appl_ptr) { 916892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 917892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (ret == 0) 918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = -EPIPE; 919892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz goto done; 920892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 921892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 922f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 923d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 9248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 9258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 926d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_read = (data->link_mtu - data->count) / frame_size; 9278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 92838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("count=%d frames_to_read=%lu", data->count, frames_to_read); 929c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 9308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 9316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 933f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(data->buffer + data->count, buff, frame_size * frames_to_read); 9348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 9362a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz data->count += frames_to_read * frame_size; 937d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->count != data->link_mtu) { 9388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 93900c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 9408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 9418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 942d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rsend = send(data->stream.fd, data->buffer, data->link_mtu, 943c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz io->nonblock ? MSG_DONTWAIT : 0); 94400c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 94500c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 94600c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 94700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 94800c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 94900c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 95000c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 95100c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 95200c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 95300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 95400c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 955892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz DBG("returning %ld", ret); 9566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io, 96038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 961a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 9626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 9636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t ret = 0; 9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 967e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data) 9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 969e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret = 0; 9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_header *header; 9716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_payload *payload; 9729494c146cec1df466c2f331957748beeac8d745aJohan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header = (void *) a2dp->buffer; 9756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload = (void *) (a2dp->buffer + sizeof(*header)); 9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); 9786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload->frame_count = a2dp->frame_count; 9806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->v = 2; 9816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->pt = 1; 9826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->sequence_number = htons(a2dp->seq_num); 9836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->timestamp = htonl(a2dp->nsamples); 9846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->ssrc = htonl(1); 9856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 986bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); 987dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (ret < 0) { 988dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("send returned %d errno %s.", ret, strerror(errno)); 989e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -errno; 990dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 9918905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 9926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reset buffer of data to send */ 9936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 9946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count = 0; 9956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples = 0; 9966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->seq_num++; 9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 998f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg return ret; 9996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 10006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 10016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io, 100238c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 100338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 10046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 10056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_data *data = io->private_data; 10066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 10076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_sframes_t ret = 0; 10080d90af2304c75cc1a3c521bcae7510ff86bb9536Marcel Holtmann unsigned int bytes_left; 1009c43f8bdcc1d527e2d77481a66217771038be3acdLennart Poettering int frame_size, encoded; 101065c9310f96fa78980196002fdf11e8d30b4fe6b6Johan Hedberg ssize_t written; 10116763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t *buff; 10126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 101338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu", 101438c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size); 1015dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr, 1016dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg io->appl_ptr - io->hw_ptr); 1017e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 1018bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Calutate starting pointers */ 1019bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann frame_size = areas->step / 8; 1020bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = size * frame_size; 1021bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff = (uint8_t *) areas->addr + 1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann (areas->first + areas->step * (offset)) / 8; 1023bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1024bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check for underrun */ 1025cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->hw_ptr > io->appl_ptr) { 1026892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 1027de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz if (ret == 0) 1028e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -EPIPE; 1029dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 1; 1030bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 1031de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 1032e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 1033e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Check if we should autostart */ 1034cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->state == SND_PCM_STATE_PREPARED) { 1035e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_t *swparams; 1036e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_uframes_t threshold; 1037de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 1038e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_malloc(&swparams); 103938c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann if (!snd_pcm_sw_params_current(io->pcm, swparams) && 1040dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg !snd_pcm_sw_params_get_start_threshold(swparams, 1041dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg &threshold)) { 1042cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->appl_ptr >= threshold) { 1043e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = snd_pcm_start(io->pcm); 1044cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret != 0) 1045bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 1046e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1047e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1048dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1049de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz snd_pcm_sw_params_free(swparams); 1050e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 10516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1052bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check if we have any left over data from the last write */ 1053bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (data->count > 0 && (bytes_left - data->count) >= a2dp->codesize) { 1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann int additional_bytes_needed = a2dp->codesize - data->count; 10556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1056dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg memcpy(data->buffer + data->count, buff, 1057bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann additional_bytes_needed); 10586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1059dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Enough data to encode (sbc wants 1k blocks) */ 1060bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize, 1061fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz a2dp->buffer + a2dp->count, 1062fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz sizeof(a2dp->buffer) - a2dp->count, 1063bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1064dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (encoded <= 0) { 1065dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Encoding error %d", encoded); 1066dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg goto done; 1067dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 10686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1069bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1070397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->count += written; 1071397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->frame_count++; 1072397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->samples += encoded / frame_size; 1073397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->nsamples += encoded / frame_size; 10746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1075397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz /* No space left for another frame then send */ 1076d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->count + written >= data->link_mtu) { 1077dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg avdtp_write(data); 1078d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending packet %d, count %d, link_mtu %u", 1079d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->seq_num, a2dp->count, 1080bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1081bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1082bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1083bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1084bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1085bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += additional_bytes_needed; 1086bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= additional_bytes_needed; 1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Since data has been process mark it as zero */ 1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count = 0; 1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1093bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Process this buffer in full chunks */ 1094bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann while (bytes_left >= a2dp->codesize) { 1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Enough data to encode (sbc wants 1k blocks) */ 1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize, 1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->buffer + a2dp->count, 1098bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann sizeof(a2dp->buffer) - a2dp->count, 1099bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1100bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (encoded <= 0) { 1101bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("Encoding error %d", encoded); 1102bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann goto done; 1103f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 11046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1105bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1106bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1107bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += a2dp->codesize; 1108bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= a2dp->codesize; 1109bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1110bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1111bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->count += written; 1112bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->frame_count++; 1113bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->samples += encoded / frame_size; 1114bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->nsamples += encoded / frame_size; 1115bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1116bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* No space left for another frame then send */ 1117bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (a2dp->count + written >= data->link_mtu) { 1118bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann avdtp_write(data); 11198a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg DBG("sending packet %d, count %d, link_mtu %u", 1120bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->seq_num, a2dp->count, 1121bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1122bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1123dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 1124dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1125bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Copy the extra to our temp buffer for the next write */ 1126bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (bytes_left > 0) { 1127bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann memcpy(data->buffer + data->count, buff, bytes_left); 1128bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count += bytes_left; 1129bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = 0; 1130bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 11316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 1133bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("returning %ld", size - bytes_left / frame_size); 1134bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1135bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return size - bytes_left / frame_size; 11368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 11378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 11386967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io, 11396967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg snd_pcm_sframes_t *delayp) 1140a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{ 1141a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley DBG(""); 1142a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 1143a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This updates io->hw_ptr value using pointer() function */ 1144a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley snd_pcm_hwsync(io->pcm); 11456967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1146a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = io->appl_ptr - io->hw_ptr; 1147a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) { 1148a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->callback->stop(io); 1149a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->state = SND_PCM_STATE_XRUN; 1150a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = 0; 1151a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley } 11526967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1153a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This should never fail, ALSA API is really not 1154a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley prepared to handle a non zero return value */ 1155a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley return 0; 1156a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley} 1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 11586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { 1159892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1160892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1161e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1162e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1163721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_write, 116637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1167892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1168892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1169a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 11706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { 1173e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1174e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1175e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1176e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1177721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_read, 1180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1182b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1183b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 11846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = { 1185892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1186892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1189e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1190e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1191e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_write, 119237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1193892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1194892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1195a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 11966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = { 1199e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1200e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1201e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1202e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1203e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1204e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_read, 1206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1208b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1209b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1210b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 1211b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 121233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io) 1213b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1214c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1215b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 1218b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 1219b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 1220b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 1221b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1222b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 1223a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka SND_PCM_FORMAT_S16 1224b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1225d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 1226b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1227c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* access type */ 1228b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 1229b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 1230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1231b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1232b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1233c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported formats */ 1234b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1235b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 1236b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1237b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1238b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1239c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported channels */ 1240c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1241d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1, 1); 1242b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1243b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1244b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 124535b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported rate */ 1246c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 1247d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 8000, 8000); 1248b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1249b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1250b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 125135b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported block size */ 1252c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1253d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->link_mtu, data->link_mtu); 1254b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1255b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1257c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1258f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann 2, 200); 125933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 126033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 126133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 126233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return 0; 126333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz} 126433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 126533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io) 126633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{ 126733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1268d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 12698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 127033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz snd_pcm_access_t access_list[] = { 127133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_RW_INTERLEAVED, 127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* Mmap access is really useless fo this driver, but we 127333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * support it because some pieces of software out there 127433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * insist on using it */ 127533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_MMAP_INTERLEAVED 127633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 127733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz unsigned int format_list[] = { 1278a8c57dbfeb6d2c5f6a160df812aacd2983fde6d1Siarhei Siamashka SND_PCM_FORMAT_S16 127933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 1280d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_list[4]; 1281d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_count; 1282d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err, min_channels, max_channels; 1283dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned int period_list[] = { 1284db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 2048, 1285db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */ 1286db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 8192 1287dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg }; 128833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 128933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* access type */ 129033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 129133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(access_list), access_list); 129233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 129333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 129433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 129533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported formats */ 129633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 129733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(format_list), format_list); 129833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 129933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 130033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 130133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported channels */ 13028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 13038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->sbc_capabilities.channel_mode = cfg->channel_mode; 13048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 13058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & 13068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_A2DP_CHANNEL_MODE_MONO) 1307d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 1; 1308d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1309d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 2; 131033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz 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 max_channels = 2; 1314d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1315d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 1; 1316d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1317d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1318d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels, max_channels); 131933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 132033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 132133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1322db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported buffer sizes 1323db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg * (can be used as 3*8192, 6*4096, 12*2048, ...) */ 1324cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg err = snd_pcm_ioplug_set_param_minmax(io, 1325cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg SND_PCM_IOPLUG_HW_BUFFER_BYTES, 1326cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg 8192*3, 8192*3); 132783a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg if (err < 0) 132883a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg return err; 132983a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg 1330db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported block sizes: */ 1331db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1332db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg ARRAY_NELEMS(period_list), period_list); 1333b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1334b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1335b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1336d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* supported rates */ 1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count = 0; 13388fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_rate) { 13398fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = cfg->rate; 1340d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 13418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } else { 13428fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13438fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_16000) { 13448fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 16000; 13458fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13468fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1347ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 13488fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13498fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_32000) { 13508fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 32000; 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_44100) { 13568fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 44100; 13578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13588fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 135900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 13608fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13618fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_48000) { 13628fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 48000; 13638fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1365d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 136600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1367d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1368db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg rate_count, rate_list); 1369d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1370d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1371e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 13726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 13736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 13746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1375d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf, 1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *bt_config) 13776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 137892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_iterator_t i, next; 137992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1380d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(bt_config, 0, sizeof(struct bluetooth_alsa_config)); 1381ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg 13829fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg /* Set defaults */ 13839fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg bt_config->autoconnect = 1; 13849fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_for_each(i, next, conf) { 138692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_t *n = snd_config_iterator_entry(i); 1387d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg const char *id, *value; 138892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 138992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_id(n, &id) < 0) 139092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 139192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 139292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) 139392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 139492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 13959fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (strcmp(id, "autoconnect") == 0) { 1396a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg int b; 1397a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg 1398a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg b = snd_config_get_bool(n); 1399a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg if (b < 0) { 14009fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg SNDERR("Invalid type for %s", id); 14019fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg return -EINVAL; 14029fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 14039fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1404a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg bt_config->autoconnect = b; 14059fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg continue; 14069fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 14079fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1408b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) { 1409d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 141092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 141192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 141292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1413b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1414d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_device = 1; 1415d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strncpy(bt_config->device, value, 18); 141692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 141792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 141892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1419b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "profile") == 0) { 1420d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 142192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 142292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 142392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1424b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1425d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (strcmp(value, "auto") == 0) { 1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1428d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "voice") == 0 || 1429d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "hfp") == 0) { 1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO; 1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1432d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "hifi") == 0 || 1433d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "a2dp") == 0) { 1434d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 1435d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1436d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 143792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 143892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 143992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "rate") == 0) { 1441d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14425402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14435402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14445402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14455402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1446d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->rate = atoi(value); 1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_rate = 1; 14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 145141b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz if (strcmp(id, "mode") == 0) { 1452d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14535402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14545402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14555402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14565402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14578fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "mono") == 0) { 1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 1459d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1460d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "dual") == 0) { 1461d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 1462d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1463d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "stereo") == 0) { 1464d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 1465d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1466d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "joint") == 0) { 1467d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 1468d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1469d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "allocation") == 0) { 1474d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14755402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14765402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14775402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14785402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "loudness") == 0) { 1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 1481d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1482d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "snr") == 0) { 1483d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR; 1484d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1485d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14865402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14875402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "subbands") == 0) { 1490d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14915402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14935402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14945402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1495d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->subbands = atoi(value); 1496d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_subbands = 1; 14975402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14985402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14995402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 15005402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "blocks") == 0) { 1501d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 15025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 15035402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 15045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1506d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->block_length = atoi(value); 1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_block_length = 1; 15085402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 15095402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 15115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "bitpool") == 0) { 1512d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 15135402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 15145402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 15155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1517d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->bitpool = atoi(value); 1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_bitpool = 1; 15195402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 15205402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 15215402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 152292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Unknown field %s", id); 152392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 152492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 152592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 15265402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return 0; 15275402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz} 15285402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1529d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg) 15305402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{ 1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 15321c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 15331c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 15341c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE; 15356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1536a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz DBG("sending %s:%s", bt_audio_strtype(msg->type), 1537a2da56b3aa57890db60205c9e75618c264bec6b0Luiz Augusto von Dentz bt_audio_strname(msg->name)); 15381c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg if (send(sk, msg, length, 0) > 0) 1539d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1540d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else { 1541d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error sending data to audio service: %s(%d)", 1543d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 15448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1545b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1546d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1547d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 15486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1549d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) 1550d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 15517c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg int err; 15527c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg ssize_t ret; 15531c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz const char *type, *name; 15541c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 15551c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 15561c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE; 1557d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1558d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("trying to receive msg from audio service..."); 15592f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg 15602f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg ret = recv(sk, inmsg, length, 0); 15612f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg if (ret < 0) { 15622f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg err = -errno; 15632f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg SNDERR("Error receiving IPC data from bluetoothd: %s (%d)", 15642f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg strerror(errno), errno); 15657c27b3e218470ba0bc2beaad39635f7b3548e53aJohan Hedberg } else if ((size_t) ret < sizeof(bt_audio_msg_header_t)) { 15662f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg SNDERR("Too short (%d bytes) IPC packet from bluetoothd", ret); 15672f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg err = -EINVAL; 15682f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg } else { 15691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz type = bt_audio_strtype(inmsg->type); 15701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz name = bt_audio_strname(inmsg->name); 15711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (type && name) { 15721c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz DBG("Received %s - %s", type, name); 1573d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1574d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1575d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -EINVAL; 15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message type %d - name %d" 15772f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg " received from audio service", 15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz inmsg->type, inmsg->name); 1579d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 15802f3ccc305172436b6cf4e5894fc8d196afea1447Johan Hedberg 15816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 15828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1583d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1584d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 1585dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg 15861c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp, 1587a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann int expected_name) 1588d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 15891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_error_t *error; 15901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int err = audioservice_recv(sk, rsp); 15911c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (err != 0) 15931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return err; 15941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->name != expected_name) { 15961c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = -EINVAL; 15971c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message %s received while %s was expected", 15981c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 15991c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(expected_name)); 16001c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16021c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->type == BT_ERROR) { 16031c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error = (void *) rsp; 16041c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("%s failed : %s(%d)", 16051c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 16061c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz strerror(error->posix_errno), 16071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error->posix_errno); 16081c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -error->posix_errno; 1609f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 16101c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1611d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 16128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 16138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 16141c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data, 16151c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz struct bt_get_capabilities_rsp *rsp) 16161c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{ 16171c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int bytes_left = rsp->h.length - sizeof(*rsp); 16181c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec_capabilities_t *codec = (void *) rsp->data; 16191c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz data->transport = codec->transport; 16211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP) 16231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 16241c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16251c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz while (bytes_left > 0) { 1626379d756055f32d46fe7e09e1d89be1f780abb144Luiz Augusto von Dentz if ((codec->type == BT_A2DP_SBC_SINK) && 1627c5e75a5051967530f29f9fabfb8593ef2723d57eLuiz Augusto von Dentz !(codec->lock & BT_WRITE_LOCK)) 16281c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz break; 16291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16301c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bytes_left -= codec->length; 16311c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec = (void *) codec + codec->length; 16321c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 16331c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16341c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (bytes_left <= 0 || 16351c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec->length != sizeof(data->a2dp.sbc_capabilities)) 16361c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -EINVAL; 16371c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16381c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz memcpy(&data->a2dp.sbc_capabilities, codec, codec->length); 16391c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 16411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz} 16421c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1643a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmannstatic int bluetooth_init(struct bluetooth_data *data, 1644a90d88b37e38b8f4c60303ea2006fd3425eef299Marcel Holtmann snd_pcm_stream_t stream, snd_config_t *conf) 16458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 16466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int sk, err; 1647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *alsa_conf = &data->alsa_config; 16481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 1649cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_req *req = (void *) buf; 1650cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_rsp *rsp = (void *) buf; 1651f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 165200c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 165300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = bluetooth_parse_config(conf, alsa_conf); 1655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1656d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1658e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = -1; 1659dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg data->stream.fd = -1; 166000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sk = bt_audio_service_open(); 1662e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley if (sk <= 0) { 1663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1665b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1666b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1667e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = sk; 1668e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.events = POLLIN; 1669b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1670892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[0] = -1; 1671892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[1] = -1; 1672892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1673d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (pipe(data->pipefd) < 0) { 1674d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1675d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1676d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1677d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) { 1678d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1679d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1680d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1681d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) { 1682d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1683d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1684d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1685d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 16861c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 16871c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 16881c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_GET_CAPABILITIES; 16891c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 16901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16919fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (alsa_conf->autoconnect) 16921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->flags |= BT_FLAG_AUTOCONNECT; 16939bdf6ba0c50a3d5500e616b0f9d63a190692cc2cLuiz Augusto von Dentz strncpy(req->destination, alsa_conf->device, 18); 1694d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (alsa_conf->has_transport) 16951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = alsa_conf->transport; 1696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 16971c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1698721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 16991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 1700d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1701d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1702d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 17031c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = 0; 17041c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 17051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg BT_GET_CAPABILITIES); 1706d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1707d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1708d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 17091c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg bluetooth_parse_capabilities(data, rsp); 1710892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1711d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 1712d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1713d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed: 17149d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg if (sk >= 0) 17159d326306a1ff9cb6421ce47d07d4367e8ff46418Johan Hedberg bt_audio_service_close(sk); 1716d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 17178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 17188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1719ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth); 1720ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann 17218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 17228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1723f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 17248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 17258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 172600c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 17278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 17288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1729d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg data = malloc(sizeof(struct bluetooth_data)); 173000c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 173100c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 173200c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 173300c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 173400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1735ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg err = bluetooth_init(data, stream, conf); 17368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 17378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 17388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1739f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 1740f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 174100c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 1742f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 1743b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1744d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 17456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 17466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_playback : 17476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_capture; 17486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 17496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 17506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_playback : 17516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_capture; 17526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1753f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 1754b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1755b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 1756b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1757d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 175833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_a2dp_hw_constraint(&data->io); 175933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz else 176033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_hsp_hw_constraint(&data->io); 176133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1762b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 1763f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 17648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 1765b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1766b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1767f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 1768b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1769b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 1770b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1771b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 177265aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg if (data) 177365aaf349ebcb2f029e3904b03060b32f7dead31eJohan Hedberg bluetooth_exit(data); 17745ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 1775b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 17765ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 17775ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 17785ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 1779