pcm_bluetooth.c revision 474420e554deeec2f7a6e2f4459c04cc90b038e8
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/* 2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 53ff24ea225437af91db69a069caa65b00ed642d9Marcel Holtmann * Copyright (C) 2006-2007 Nokia Corporation 6e823c15e43a6f924779e466d434c51157002d9eeMarcel Holtmann * Copyright (C) 2004-2008 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 */ 99d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 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 */ 102d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 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 */ 134d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 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 */ 138d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 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, 149d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 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 */ 2278dfa81ccf2c3eeb7518958428524a9850be1fd3dJohan Hedberg if (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]; 433cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 434cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 435721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz int err; 436721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 437721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 438721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->period_size, io->buffer_size); 439721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 440450e5656a8de08051f221d63e026c259151ef274Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 441450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.type = BT_REQUEST; 442450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 443450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length = sizeof(*req); 4441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 445450e5656a8de08051f221d63e026c259151ef274Johan Hedberg strncpy(req->device, data->alsa_config.device, 18); 446450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_SCO; 447450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->codec.length = sizeof(pcm_capabilities_t); 448450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? 449721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_WRITE : 450721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_READ); 451721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 452450e5656a8de08051f221d63e026c259151ef274Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 453450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 454721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 455721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 456721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 457450e5656a8de08051f221d63e026c259151ef274Johan Hedberg rsp->h.length = sizeof(*rsp); 458450e5656a8de08051f221d63e026c259151ef274Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 4591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 460721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz if (err < 0) 461721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return err; 462721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 463450e5656a8de08051f221d63e026c259151ef274Johan Hedberg data->transport = rsp->transport; 464450e5656a8de08051f221d63e026c259151ef274Johan Hedberg data->link_mtu = rsp->link_mtu; 465721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 466721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz return 0; 467721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz} 468721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 4692934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentzstatic uint8_t default_bitpool(uint8_t freq, uint8_t mode) 4702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 4712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (freq) { 472489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_16000: 473489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_32000: 4742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 475489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_44100: 4762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 4792934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 31; 4802934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 4812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 4822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 4832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 4842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 4852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 4862934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 487489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz case BT_SBC_SAMPLING_FREQ_48000: 4882934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (mode) { 4892934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_MONO: 4902934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 4912934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 29; 4922934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_STEREO: 4932934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 4942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 4952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 4962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid channel mode %u", mode); 4972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 51; 4982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 4992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Invalid sampling freq %u", freq); 5012934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 53; 5022934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5032934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 5042934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_init(struct bluetooth_data *data, 5068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 5072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz{ 5088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 5098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t *cap = &data->a2dp.sbc_capabilities; 5108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz unsigned int max_bitpool, min_bitpool, rate, channels; 5118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int dir; 5128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 5138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_rate(params, &rate, &dir); 5148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_get_channels(params, &channels); 5152934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5162934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz switch (rate) { 5172934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 48000: 518489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_48000; 5192934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5202934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 44100: 521489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_44100; 5222934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5232934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 32000: 524489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_32000; 5252934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5262934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz case 16000: 527489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz cap->frequency = BT_SBC_SAMPLING_FREQ_16000; 5282934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz break; 5292934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz default: 5302934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("Rate %d not supported", rate); 5312934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5322934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5332934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5348fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 5358fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode = cfg->channel_mode; 5368fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (channels == 2) { 5372934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 5382934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 5392934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 5402934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 5412934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 5422934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 5432934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } else { 5442934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 5452934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 5462934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5472934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5482934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (!cap->channel_mode) { 5492934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported channel modes"); 5502934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5512934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5522934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5538fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_block_length) 5548fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->block_length = cfg->block_length; 5558fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) 5562934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_16; 5572934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) 5582934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_12; 5592934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) 5602934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_8; 5612934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) 5622934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->block_length = BT_A2DP_BLOCK_LENGTH_4; 5632934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5642934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported block lengths"); 5652934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5662934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5672934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_subbands) 5698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->subbands = cfg->subbands; 5702934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->subbands & BT_A2DP_SUBBANDS_8) 5712934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_8; 5722934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->subbands & BT_A2DP_SUBBANDS_4) 5732934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->subbands = BT_A2DP_SUBBANDS_4; 5742934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else { 5752934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz DBG("No supported subbands"); 5762934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return -1; 5772934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz } 5782934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_allocation_method) 5808fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->allocation_method = cfg->allocation_method; 5812934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) 5822934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 5832934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) 5842934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->allocation_method = BT_A2DP_ALLOCATION_SNR; 5852934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5868fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_bitpool) 5878fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = max_bitpool = cfg->bitpool; 5888fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz else { 5898fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz min_bitpool = MAX(MIN_BITPOOL, cap->min_bitpool); 5908fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz max_bitpool = MIN(default_bitpool(cap->frequency, 5918fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->channel_mode), 5928fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz cap->max_bitpool); 5938fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 5942934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5952934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->min_bitpool = min_bitpool; 5962934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz cap->max_bitpool = max_bitpool; 5972934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 5982934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz return 0; 5992934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz} 6002934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 6018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic void bluetooth_a2dp_setup(struct bluetooth_a2dp *a2dp) 602afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{ 6038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz sbc_capabilities_t active_capabilities = a2dp->sbc_capabilities; 604afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 605d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->sbc_initialized) 6062934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_reinit(&a2dp->sbc, 0); 6072934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz else 6082934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz sbc_init(&a2dp->sbc, 0); 609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc_initialized = 1; 6102934e194f3ffe754e18477113c870a7b98f88454Luiz Augusto von Dentz 611489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_16000) 61223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_16000; 613d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 614489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_32000) 61523a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_32000; 616d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 617489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_44100) 61823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_44100; 619d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 620489c2e0dbd76d9cecec62d19fafd9e7baddb72e7Luiz Augusto von Dentz if (active_capabilities.frequency & BT_SBC_SAMPLING_FREQ_48000) 62123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.frequency = SBC_FREQ_48000; 622d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 623d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_MONO) 62423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_MONO; 625d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 62623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 62723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; 62823a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 62923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 63023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_STEREO; 63123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz 63223a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz if (active_capabilities.channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 63323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; 634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation = active_capabilities.allocation_method 63623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz == BT_A2DP_ALLOCATION_SNR ? SBC_AM_SNR 63723a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz : SBC_AM_LOUDNESS; 638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 639d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.subbands) { 640d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_4: 64123a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_4; 642d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 643d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_SUBBANDS_8: 64423a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.subbands = SBC_SB_8; 645d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 646d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 648d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz switch (active_capabilities.block_length) { 649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_4: 65023a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_4; 651d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 652d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_8: 65323a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_8; 654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_12: 65623a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_12; 657d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 658d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz case BT_A2DP_BLOCK_LENGTH_16: 65923a5ed9f697a1e42a0d36c72dd9a297792c61082Luiz Augusto von Dentz a2dp->sbc.blocks = SBC_BLK_16; 660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz break; 661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 662d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 663d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool = active_capabilities.max_bitpool; 6648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->codesize = sbc_get_codesize(&a2dp->sbc); 665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 6668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz} 6678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, 6698fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 6708fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz{ 6718fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 6728fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 6731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 674cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_req *req = (void *) buf; 675cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_set_configuration_rsp *rsp = (void *) buf; 6768fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz int err; 6778fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6788fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz DBG("Preparing with io->period_size=%lu io->buffer_size=%lu", 6798fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz io->period_size, io->buffer_size); 6808fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6818fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz err = bluetooth_a2dp_init(data, params); 6828fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 6838fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 6848fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 6851c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 6861c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 6871c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_SET_CONFIGURATION; 6881c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 6891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 6901c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg strncpy(req->device, data->alsa_config.device, 18); 6911c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memcpy(&req->codec, &a2dp->sbc_capabilities, 6921c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg sizeof(a2dp->sbc_capabilities)); 6931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 6941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.transport = BT_CAPABILITIES_TRANSPORT_A2DP; 6951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->codec.length = sizeof(a2dp->sbc_capabilities); 6961c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->access_mode = (io->stream == SND_PCM_STREAM_PLAYBACK ? 6978fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_WRITE : 6988fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_CAPABILITIES_ACCESS_MODE_READ); 6991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length += req->codec.length - sizeof(req->codec); 7008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7011c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 7028fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7051c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = sizeof(*rsp); 7061c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 7071c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz BT_SET_CONFIGURATION); 7088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (err < 0) 7098fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz return err; 7108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7111c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg data->transport = rsp->transport; 7121c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg data->link_mtu = rsp->link_mtu; 7138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 7148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz /* Setup SBC encoder now we agree on parameters */ 7158fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz bluetooth_a2dp_setup(a2dp); 716d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 717d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", 718d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.allocation, a2dp->sbc.subbands, a2dp->sbc.blocks, 719d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->sbc.bitpool); 720d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 721d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 722afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz} 723afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, 725f40848f9ef7ecdf101a32d7ec1f41c267e7756ebMarcel Holtmann struct pollfd *pfd, unsigned int space) 726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 727e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 728e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 729e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(io); 730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 734e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz pfd[0].fd = data->stream.fd; 735e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 736e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 737e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 739e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 740e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 741e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED, 742e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, unsigned int nfds, 743dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 744e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 745e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds && nfds == 1 && revents); 746e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 747e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = pfds[0].revents; 748e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 749e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 750e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 751e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 75237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors_count(snd_pcm_ioplug_t *io) 75337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz{ 75437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 75537c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz} 75637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 757892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_descriptors(snd_pcm_ioplug_t *io, 75838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfd, unsigned int space) 759e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 760e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 761e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 762e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 763e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 764892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz assert(data->pipefd[0] >= 0); 765e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 76637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (space < 2) 767e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 768e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 769892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz pfd[0].fd = data->pipefd[0]; 770e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 771e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 77237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].fd = data->stream.fd; 77337c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].events = POLLERR | POLLHUP | POLLNVAL; 77437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz pfd[1].revents = 0; 775e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 77637c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz return 2; 777e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 778e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 779892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentzstatic int bluetooth_playback_poll_revents(snd_pcm_ioplug_t *io, 78038c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann struct pollfd *pfds, unsigned int nfds, 781dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned short *revents) 782e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 783e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg static char buf[1]; 784e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret; 785e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 786e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 787e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 788e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds); 78937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(nfds == 2); 790e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(revents); 791e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds[0].fd >= 0); 79237c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz assert(pfds[1].fd >= 0); 793e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 794e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (io->state != SND_PCM_STATE_PREPARED) 795e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = read(pfds[0].fd, buf, 1); 796e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 79737c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz if (pfds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) 79837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz io->state = SND_PCM_STATE_DISCONNECTED; 79937c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz 80037c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz revents[0] = (pfds[0].revents & ~POLLIN) | POLLOUT; 80137c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz revents[1] = (pfds[1].revents & ~POLLIN); 802e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 803e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 804e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 805e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 806e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 8076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, 80838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 809dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 810dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 8128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 81300c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 81400c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 815f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int nrecv, frame_size = 0; 8168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 81738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu io->nonblock=%u", 81838c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 8198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8203709666344736da68472f754ac52edc356039058Johan Hedberg frame_size = areas->step / 8; 8213709666344736da68472f754ac52edc356039058Johan Hedberg 82200c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 82300c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 82400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 825d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz nrecv = recv(data->stream.fd, data->buffer, data->link_mtu, 826474420e554deeec2f7a6e2f4459c04cc90b038e8Johan Hedberg io->nonblock ? MSG_DONTWAIT : 0); 82700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 82800c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 82900c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 83000c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 83200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 833d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (nrecv != data->link_mtu) { 83400c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 83500c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 83600c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 8378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 8388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 83900c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 840d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + data->link_mtu / frame_size) % 841721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz io->buffer_size; 84200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 84300c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 8446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (unsigned char *) areas->addr + 8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 84600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 847d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 84800c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 84900c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 850d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_write = (data->link_mtu - data->count) / frame_size; 85100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 852f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(buff, data->buffer + data->count, frame_size * frames_to_write); 853f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->count += (frame_size * frames_to_write); 854d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->count %= data->link_mtu; 85500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 85600c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 85700c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 85800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 85900c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 86000c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 8618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 8628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 8638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, 86538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 866dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 867dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 8688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 8698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 8708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 8718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 872c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz uint8_t *buff; 873f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int rsend, frame_size; 8748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 87538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu, size=%lu io->nonblock=%u", 87638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size, io->nonblock); 8778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 878892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (io->hw_ptr > io->appl_ptr) { 879892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 880892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz if (ret == 0) 881892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = -EPIPE; 882892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz goto done; 883892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz } 884892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 885f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 886d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if ((data->count + size * frame_size) <= data->link_mtu) 8878742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 8888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 889d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz frames_to_read = (data->link_mtu - data->count) / frame_size; 8908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 89138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("count=%d frames_to_read=%lu", data->count, frames_to_read); 892c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 8938742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 8946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 896f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(data->buffer + data->count, buff, frame_size * frames_to_read); 8978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 8992a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz data->count += frames_to_read * frame_size; 900d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->count != data->link_mtu) { 9018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 90200c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 9038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 9048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 905d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rsend = send(data->stream.fd, data->buffer, data->link_mtu, 906c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz io->nonblock ? MSG_DONTWAIT : 0); 90700c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 90800c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 90900c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 91000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 91100c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 91200c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 91300c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 91400c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 91500c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 91600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 91700c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 918892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz DBG("returning %ld", ret); 9196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9226763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io, 92338c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 924dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t offset, 925dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg snd_pcm_uframes_t size) 9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t ret = 0; 9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 931e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data) 9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 933e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret = 0; 9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_header *header; 9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_payload *payload; 9369494c146cec1df466c2f331957748beeac8d745aJohan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header = (void *) a2dp->buffer; 9396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload = (void *) (a2dp->buffer + sizeof(*header)); 9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); 9426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload->frame_count = a2dp->frame_count; 9446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->v = 2; 9456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->pt = 1; 9466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->sequence_number = htons(a2dp->seq_num); 9476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->timestamp = htonl(a2dp->nsamples); 9486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->ssrc = htonl(1); 9496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 950bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann ret = send(data->stream.fd, a2dp->buffer, a2dp->count, MSG_DONTWAIT); 951dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (ret < 0) { 952dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("send returned %d errno %s.", ret, strerror(errno)); 953e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -errno; 954dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 9558905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 9566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reset buffer of data to send */ 9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count = 0; 9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples = 0; 9606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->seq_num++; 9616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 962f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg return ret; 9636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 9646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io, 96638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann const snd_pcm_channel_area_t *areas, 96738c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann snd_pcm_uframes_t offset, snd_pcm_uframes_t size) 9686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 9696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_data *data = io->private_data; 9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_sframes_t ret = 0; 972bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann int frame_size, encoded, written, bytes_left; 9736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t *buff; 9746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 97538c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann DBG("areas->step=%u areas->first=%u offset=%lu size=%lu", 97638c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann areas->step, areas->first, offset, size); 977dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("hw_ptr=%lu appl_ptr=%lu diff=%lu", io->hw_ptr, io->appl_ptr, 978dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg io->appl_ptr - io->hw_ptr); 979e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 980bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Calutate starting pointers */ 981bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann frame_size = areas->step / 8; 982bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = size * frame_size; 983bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff = (uint8_t *) areas->addr + 984bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann (areas->first + areas->step * (offset)) / 8; 985bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 986bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check for underrun */ 987cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->hw_ptr > io->appl_ptr) { 988892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz ret = bluetooth_playback_stop(io); 989de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz if (ret == 0) 990e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -EPIPE; 991dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg data->reset = 1; 992bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 993de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz } 994e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 995e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Check if we should autostart */ 996cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->state == SND_PCM_STATE_PREPARED) { 997e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_t *swparams; 998e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_uframes_t threshold; 999de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz 1000e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_malloc(&swparams); 100138c5be0cc3029bf78445be15470d18343a5b4daeMarcel Holtmann if (!snd_pcm_sw_params_current(io->pcm, swparams) && 1002dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg !snd_pcm_sw_params_get_start_threshold(swparams, 1003dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg &threshold)) { 1004cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->appl_ptr >= threshold) { 1005e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = snd_pcm_start(io->pcm); 1006cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret != 0) 1007bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return ret; 1008e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1009e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 1010dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1011de584ba3b958b48a123dde4e6042af11ff8a196fLuiz Augusto von Dentz snd_pcm_sw_params_free(swparams); 1012e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 10136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1014bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Check if we have any left over data from the last write */ 1015bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (data->count > 0 && (bytes_left - data->count) >= a2dp->codesize) { 1016bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann int additional_bytes_needed = a2dp->codesize - data->count; 10176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1018dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg memcpy(data->buffer + data->count, buff, 1019bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann additional_bytes_needed); 10206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1021dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg /* Enough data to encode (sbc wants 1k blocks) */ 1022bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, data->buffer, a2dp->codesize, 1023fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz a2dp->buffer + a2dp->count, 1024fad46eca75efef391fbaf18117ef15ee8000dbeaLuiz Augusto von Dentz sizeof(a2dp->buffer) - a2dp->count, 1025bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1026dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg if (encoded <= 0) { 1027dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg DBG("Encoding error %d", encoded); 1028dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg goto done; 1029dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 10306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1031bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1032397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->count += written; 1033397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->frame_count++; 1034397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->samples += encoded / frame_size; 1035397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz a2dp->nsamples += encoded / frame_size; 10366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1037397d6c2b3bc7661f978c1777442d33fd86ada21eLuiz Augusto von Dentz /* No space left for another frame then send */ 1038d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (a2dp->count + written >= data->link_mtu) { 1039dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg avdtp_write(data); 1040d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending packet %d, count %d, link_mtu %u", 1041d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz a2dp->seq_num, a2dp->count, 1042bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1043bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1044bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1045bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1046bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1047bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += additional_bytes_needed; 1048bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= additional_bytes_needed; 1049bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1050bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Since data has been process mark it as zero */ 1051bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count = 0; 1052bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1053bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1054bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1055bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Process this buffer in full chunks */ 1056bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann while (bytes_left >= a2dp->codesize) { 1057bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Enough data to encode (sbc wants 1k blocks) */ 1058bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann encoded = sbc_encode(&a2dp->sbc, buff, a2dp->codesize, 1059bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->buffer + a2dp->count, 1060bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann sizeof(a2dp->buffer) - a2dp->count, 1061bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann &written); 1062bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (encoded <= 0) { 1063bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("Encoding error %d", encoded); 1064bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann goto done; 1065f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 10666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1067bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment up buff pointer to take into account 1068bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann * the data processed */ 1069bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann buff += a2dp->codesize; 1070bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left -= a2dp->codesize; 1071bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1072bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Increment a2dp buffers */ 1073bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->count += written; 1074bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->frame_count++; 1075bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->samples += encoded / frame_size; 1076bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->nsamples += encoded / frame_size; 1077bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1078bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* No space left for another frame then send */ 1079bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (a2dp->count + written >= data->link_mtu) { 1080bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann avdtp_write(data); 10818a74ae3846bc1fb887c80a355265e701f1546df6Johan Hedberg DBG("sending packet %d, count %d, link_mtu %u", 1082bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann a2dp->seq_num, a2dp->count, 1083bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->link_mtu); 1084bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 1085dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg } 1086dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg 1087bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann /* Copy the extra to our temp buffer for the next write */ 1088bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann if (bytes_left > 0) { 1089bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann memcpy(data->buffer + data->count, buff, bytes_left); 1090bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann data->count += bytes_left; 1091bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann bytes_left = 0; 1092bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann } 10936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 10946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 1095bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann DBG("returning %ld", size - bytes_left / frame_size); 1096bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann 1097bd022e2e05b7adb33c1b5328ddb652231cbf7e58Marcel Holtmann return size - bytes_left / frame_size; 10988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 10998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 11006967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedbergstatic int bluetooth_playback_delay(snd_pcm_ioplug_t *io, 11016967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg snd_pcm_sframes_t *delayp) 1102a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley{ 1103a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley DBG(""); 1104a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 1105a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This updates io->hw_ptr value using pointer() function */ 1106a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley snd_pcm_hwsync(io->pcm); 11076967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1108a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = io->appl_ptr - io->hw_ptr; 1109a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley if ((io->state == SND_PCM_STATE_RUNNING) && (*delayp < 0)) { 1110a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->callback->stop(io); 1111a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley io->state = SND_PCM_STATE_XRUN; 1112a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley *delayp = 0; 1113a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley } 11146967924ef97d377c90d73d4b5127a9b3748cb068Johan Hedberg 1115a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley /* This should never fail, ALSA API is really not 1116a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley prepared to handle a non zero return value */ 1117a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley return 0; 1118a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley} 1119a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley 11206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { 1121892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1122892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1123e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1124e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1125721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1126e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1127e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_write, 112837c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1129892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1130892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1131a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 11326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { 1135e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1136e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1137e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1138e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1139721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz .hw_params = bluetooth_hsp_hw_params, 1140e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1141e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_read, 1142e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1143e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1144b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1145b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 11466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = { 1147892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .start = bluetooth_playback_start, 1148892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .stop = bluetooth_playback_stop, 1149e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1150e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1151e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1152e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1153e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_write, 115437c2fa54a9eb3d086849acdf4a4d64157334b21aLuiz Augusto von Dentz .poll_descriptors_count = bluetooth_playback_poll_descriptors_count, 1155892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_descriptors = bluetooth_playback_poll_descriptors, 1156892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz .poll_revents = bluetooth_playback_poll_revents, 1157a8b6f0d51cbae34d78acb664c96b8e54a25b7640Brad Midgley .delay = bluetooth_playback_delay, 11586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 11596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 11606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = { 1161e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 1162e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 1163e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 1164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 1165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 1166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 1167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_read, 1168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 1169e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 1170b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 1171b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1172b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 1173b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 117433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_constraint(snd_pcm_ioplug_t *io) 1175b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1176c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1177b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 1178b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 1179b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 1180b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 1181b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 1182b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 1183b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1184b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 1185b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_FORMAT_S16_LE 1186b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 1187d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 1188b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1189c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* access type */ 1190b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 1191b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 1192b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1193b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1194b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1195c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported formats */ 1196b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 1197b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 1198b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1199b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1200b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1201c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported channels */ 1202c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1203d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1, 1); 1204b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1205b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1206b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 120735b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported rate */ 1208c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 1209d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 8000, 8000); 1210b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1211b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1212b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 121335b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported block size */ 1214c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1215d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz data->link_mtu, data->link_mtu); 1216b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1217b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1218b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1219c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 1220f803f3511095e17811c50ebc85971ddd40c55618Marcel Holtmann 2, 200); 122133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 122233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 122333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 122433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return 0; 122533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz} 122633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 122733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_constraint(snd_pcm_ioplug_t *io) 122833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz{ 122933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1230d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_a2dp *a2dp = &data->a2dp; 12318fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz struct bluetooth_alsa_config *cfg = &data->alsa_config; 123233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz snd_pcm_access_t access_list[] = { 123333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_RW_INTERLEAVED, 123433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* Mmap access is really useless fo this driver, but we 123533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * support it because some pieces of software out there 123633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz * insist on using it */ 123733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_ACCESS_MMAP_INTERLEAVED 123833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 123933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz unsigned int format_list[] = { 124033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz SND_PCM_FORMAT_S16_LE 124133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz }; 1242d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_list[4]; 1243d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz unsigned int rate_count; 1244d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err, min_channels, max_channels; 1245dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg unsigned int period_list[] = { 1246db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 2048, 1247db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 4096, /* e.g. 23.2msec/period (stereo 16bit at 44.1kHz) */ 1248db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg 8192 1249dff420207b69768a305ed014f7c7648d027d6b38Johan Hedberg }; 125033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 125133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* access type */ 125233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 125333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(access_list), access_list); 125433fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 125533fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 125633fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 125733fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported formats */ 125833fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 125933fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz ARRAY_NELEMS(format_list), format_list); 126033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 126133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 126233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 126333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz /* supported channels */ 12648fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_channel_mode) 12658fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz a2dp->sbc_capabilities.channel_mode = cfg->channel_mode; 12668fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz 12678fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & 12688fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_A2DP_CHANNEL_MODE_MONO) 1269d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 1; 1270d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1271d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels = 2; 127233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 12738fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.channel_mode & 12748fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz (~BT_A2DP_CHANNEL_MODE_MONO)) 1275d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 2; 1276d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 1277d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz max_channels = 1; 1278d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1279d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1280d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz min_channels, max_channels); 128133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz if (err < 0) 128233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz return err; 128333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1284db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported buffer sizes 1285db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg * (can be used as 3*8192, 6*4096, 12*2048, ...) */ 1286cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg err = snd_pcm_ioplug_set_param_minmax(io, 1287cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg SND_PCM_IOPLUG_HW_BUFFER_BYTES, 1288cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg 8192*3, 8192*3); 128983a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg if (err < 0) 129083a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg return err; 129183a8b201c5316ef297f4630ac8ece0f3dd198ff0Johan Hedberg 1292db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg /* supported block sizes: */ 1293db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 1294db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg ARRAY_NELEMS(period_list), period_list); 1295b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1296b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 1297b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1298d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz /* supported rates */ 1299d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count = 0; 13008fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (cfg->has_rate) { 13018fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = cfg->rate; 1302d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz rate_count++; 13038fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } else { 13048fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13058fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_16000) { 13068fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 16000; 13078fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13088fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1309ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 13108fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13118fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_32000) { 13128fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 32000; 13138fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13148fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1315ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 13168fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13178fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_44100) { 13188fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 44100; 13198fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13208fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 132100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 13228fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (a2dp->sbc_capabilities.frequency & 13238fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz BT_SBC_SAMPLING_FREQ_48000) { 13248fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_list[rate_count] = 48000; 13258fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz rate_count++; 13268fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz } 1327d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 132800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1329d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_RATE, 1330db90b606bb8b3ecd2a84a97a4a557ab026287d54Johan Hedberg rate_count, rate_list); 1331d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1332d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1333e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 13346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 13356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 13366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1337d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int bluetooth_parse_config(snd_config_t *conf, 1338d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *bt_config) 13396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 134092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_iterator_t i, next; 134192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1342d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz memset(bt_config, 0, sizeof(struct bluetooth_alsa_config)); 1343ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg 13449fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg /* Set defaults */ 13459fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg bt_config->autoconnect = 1; 13469fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 134792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_for_each(i, next, conf) { 134892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann snd_config_t *n = snd_config_iterator_entry(i); 1349d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg const char *id, *value; 135092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 135192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (snd_config_get_id(n, &id) < 0) 135292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 135392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 135492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0) 135592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 135692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 13579fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (strcmp(id, "autoconnect") == 0) { 1358a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg int b; 1359a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg 1360a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg b = snd_config_get_bool(n); 1361a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg if (b < 0) { 13629fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg SNDERR("Invalid type for %s", id); 13639fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg return -EINVAL; 13649fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 13659fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1366a104e5ff05aa758b5499b316d1923f1c83915e55Johan Hedberg bt_config->autoconnect = b; 13679fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg continue; 13689fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg } 13699fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg 1370b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "device") == 0 || strcmp(id, "bdaddr") == 0) { 1371d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 137292f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 137392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 137492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1375b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1376d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_device = 1; 1377d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strncpy(bt_config->device, value, 18); 137892f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 137992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 138092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 1381b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann if (strcmp(id, "profile") == 0) { 1382d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 138392f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Invalid type for %s", id); 138492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 138592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 1386b70de842824ccc09bdf1a0d406bbe1d5cfbed355Marcel Holtmann 1387d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (strcmp(value, "auto") == 0) { 1388d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1389d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1390d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "voice") == 0 || 1391d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "hfp") == 0) { 1392d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_SCO; 1393d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1394d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "hifi") == 0 || 1395d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg strcmp(value, "a2dp") == 0) { 1396d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 1397d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_transport = 1; 1398d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 139992f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann continue; 140092f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 140192f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14025402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "rate") == 0) { 1403d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14045402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14055402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14065402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14075402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1408d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->rate = atoi(value); 1409d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_rate = 1; 14105402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14115402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14125402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 141341b71b230e0aa4b495c091e7d17c6b939ddbce79Luiz Augusto von Dentz if (strcmp(id, "mode") == 0) { 1414d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14155402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14165402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14175402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14185402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14198fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "mono") == 0) { 1420d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 1421d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1422d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "dual") == 0) { 1423d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 1424d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1425d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "stereo") == 0) { 1426d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 1427d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1428d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "joint") == 0) { 1429d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 1430d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_channel_mode = 1; 1431d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14325402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14335402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14345402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14355402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "allocation") == 0) { 1436d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14375402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14385402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14395402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14405402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14418fbc804e08629e5450d2641b4ba660f111dedbb2Luiz Augusto von Dentz if (strcmp(value, "loudness") == 0) { 1442d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 1443d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1444d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg } else if (strcmp(value, "snr") == 0) { 1445d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->allocation_method = BT_A2DP_ALLOCATION_SNR; 1446d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_allocation_method = 1; 1447d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 14485402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14495402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14505402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14515402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "subbands") == 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 1457d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->subbands = atoi(value); 1458d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_subbands = 1; 14595402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14605402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14615402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14625402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "blocks") == 0) { 1463d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg if (snd_config_get_string(n, &value) < 0) { 14645402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz SNDERR("Invalid type for %s", id); 14655402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return -EINVAL; 14665402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14675402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1468d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->block_length = atoi(value); 1469d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_block_length = 1; 14705402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14715402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14725402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 14735402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz if (strcmp(id, "bitpool") == 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 1479d1c580e150dc4982c9e91b70842aab5ba71325ebJohan Hedberg bt_config->bitpool = atoi(value); 1480d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_config->has_bitpool = 1; 14815402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz continue; 14825402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz } 14835402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 148492f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann SNDERR("Unknown field %s", id); 148592f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann return -EINVAL; 148692f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann } 148792f94938b981fe6a892e365670d5fa4d58c94283Marcel Holtmann 14885402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz return 0; 14895402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz} 14905402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz 1491d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_send(int sk, const bt_audio_msg_header_t *msg) 14925402a5058f463efd3bc84d43b1af10ff253b9a1eLuiz Augusto von Dentz{ 1493d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 14941c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 14951c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 14961c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE; 14976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1498d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("sending %s", bt_audio_strmsg(msg->msg_type)); 14991c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg if (send(sk, msg, length, 0) > 0) 1500d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1501d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else { 1502d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1503d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error sending data to audio service: %s(%d)", 1504d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 15058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1506b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1507d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1508d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 15096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1510d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzstatic int audioservice_recv(int sk, bt_audio_msg_header_t *inmsg) 1511d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 1512d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz int err; 15131c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz const char *type, *name; 15141c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg uint16_t length; 15151c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg 15161c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg length = inmsg->length ? inmsg->length : BT_SUGGESTED_BUFFER_SIZE; 1517d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1518d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz DBG("trying to receive msg from audio service..."); 15191c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg if (recv(sk, inmsg, length, 0) > 0) { 15201c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz type = bt_audio_strtype(inmsg->type); 15211c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz name = bt_audio_strname(inmsg->name); 15221c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (type && name) { 15231c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz DBG("Received %s - %s", type, name); 1524d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = 0; 1525d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1526d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -EINVAL; 15271c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message type %d - name %d" 1528d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz "received from audio service", 15291c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz inmsg->type, inmsg->name); 1530d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1531d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } else { 1532d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1533d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz SNDERR("Error receiving data from audio service: %s(%d)", 1534d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz strerror(errno), errno); 15356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 15368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1537d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1538d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz} 1539dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg 15401c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int audioservice_expect(int sk, bt_audio_msg_header_t *rsp, 15411c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int expected_name) 1542d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz{ 15431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_error_t *error; 15441c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int err = audioservice_recv(sk, rsp); 15451c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15461c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (err != 0) 15471c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return err; 15481c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15491c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->name != expected_name) { 15501c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz err = -EINVAL; 15511c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("Bogus message %s received while %s was expected", 15521c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 15531c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(expected_name)); 15541c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 15551c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15561c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (rsp->type == BT_ERROR) { 15571c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error = (void *) rsp; 15581c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz SNDERR("%s failed : %s(%d)", 15591c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bt_audio_strname(rsp->name), 15601c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz strerror(error->posix_errno), 15611c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz error->posix_errno); 15621c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -error->posix_errno; 1563f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 15641c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1565d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 15668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 15678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 15681c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentzstatic int bluetooth_parse_capabilities(struct bluetooth_data *data, 15691c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz struct bt_get_capabilities_rsp *rsp) 15701c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz{ 15711c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz int bytes_left = rsp->h.length - sizeof(*rsp); 15721c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec_capabilities_t *codec = (void *) rsp->data; 15731c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15741c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz data->transport = codec->transport; 15751c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15761c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (codec->transport != BT_CAPABILITIES_TRANSPORT_A2DP) 15771c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 15781c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15791c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz while (bytes_left > 0) { 15801c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (codec->type == BT_A2DP_CODEC_SBC) 15811c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz break; 15821c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15831c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz bytes_left -= codec->length; 15841c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec = (void *) codec + codec->length; 15851c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz } 15861c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15871c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz if (bytes_left <= 0 || 15881c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz codec->length != sizeof(data->a2dp.sbc_capabilities)) 15891c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return -EINVAL; 15901c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15911c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz memcpy(&data->a2dp.sbc_capabilities, codec, codec->length); 15921c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 15931c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz return 0; 15941c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz} 15951c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 1596ec384afacde8614306abe32cf40c55b795783f0eJohan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_pcm_stream_t stream, 1597ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg snd_config_t *conf) 15988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 15996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int sk, err; 1600d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz struct bluetooth_alsa_config *alsa_conf = &data->alsa_config; 16011c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz char buf[BT_SUGGESTED_BUFFER_SIZE]; 1602cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_req *req = (void *) buf; 1603cc49c31ccedcd31dd09be2a9cc32e653573c7d4bJohan Hedberg struct bt_get_capabilities_rsp *rsp = (void *) buf; 1604f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 160500c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 160600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1607d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = bluetooth_parse_config(conf, alsa_conf); 1608d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1609d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 1610d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1611e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = -1; 1612dc6a67eda727b063558e9ae95b05ed16110a3108Johan Hedberg data->stream.fd = -1; 161300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1614d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz sk = bt_audio_service_open(); 1615e65858be07f86fe12756c67a20a5f45debfcc250Brad Midgley if (sk <= 0) { 1616d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1617d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1618b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1619b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1620e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.fd = sk; 1621e4b3ec84ce3680ca33ae88b76e1ce138756c0427Luiz Augusto von Dentz data->server.events = POLLIN; 1622b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1623892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[0] = -1; 1624892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz data->pipefd[1] = -1; 1625892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1626d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (pipe(data->pipefd) < 0) { 1627d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1628d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1629d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1630d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[0], F_SETFL, O_NONBLOCK) < 0) { 1631d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1632d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1633d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1634d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (fcntl(data->pipefd[1], F_SETFL, O_NONBLOCK) < 0) { 1635d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz err = -errno; 1636d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1637d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz } 1638d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 16391c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg memset(req, 0, BT_SUGGESTED_BUFFER_SIZE); 16401c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.type = BT_REQUEST; 16411c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.name = BT_GET_CAPABILITIES; 16421c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->h.length = sizeof(*req); 16431c01d240ba6ac475dba2fb39dbb208343fb78eedLuiz Augusto von Dentz 16449fa2613525721908ec43189794fe99828b8a4f51Johan Hedberg if (alsa_conf->autoconnect) 16451c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->flags |= BT_FLAG_AUTOCONNECT; 16461c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg strncpy(req->device, alsa_conf->device, 18); 1647d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (alsa_conf->has_transport) 16481c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = alsa_conf->transport; 1649d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz else 16501c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg req->transport = BT_CAPABILITIES_TRANSPORT_ANY; 1651721d249e314b0591274436594be56805bf5a2822Luiz Augusto von Dentz 16521c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_send(data->server.fd, &req->h); 1653d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1654d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1655d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 16561c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg rsp->h.length = 0; 16571c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg err = audioservice_expect(data->server.fd, &rsp->h, 16581c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg BT_GET_CAPABILITIES); 1659d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (err < 0) 1660d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz goto failed; 1661d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 16621c7291138ae3d25d7f34803e4f354a90d012f6a1Johan Hedberg bluetooth_parse_capabilities(data, rsp); 1663892a1edab753356dba7c0b5373e414ea71fcf6faLuiz Augusto von Dentz 1664d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return 0; 1665d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz 1666d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentzfailed: 1667d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz bt_audio_service_close(sk); 1668d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz return err; 16698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 16708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1671ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel HoltmannSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth); 1672ba4bcf3dfe11e739f4968e16c72c7a27a3a74cd9Marcel Holtmann 16738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 16748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1675f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 16768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 16778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 167800c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 16798742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 16808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1681d595791da3d0ce8a20e638f3d0648ccdf78bb55aJohan Hedberg data = malloc(sizeof(struct bluetooth_data)); 168200c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 168300c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 168400c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 168500c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 168600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 1687ec384afacde8614306abe32cf40c55b795783f0eJohan Hedberg err = bluetooth_init(data, stream, conf); 16888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 16898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 16908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1691f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 1692f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 169300c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 1694f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 1695b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1696d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 16976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 16986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_playback : 16996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_capture; 17006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 17016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 17026763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_playback : 17036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_capture; 17046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1705f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 1706b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1707b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 1708b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1709d4e24bf6a3d8af6479abce92fbbf1869a59669aaLuiz Augusto von Dentz if (data->transport == BT_CAPABILITIES_TRANSPORT_A2DP) 171033fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_a2dp_hw_constraint(&data->io); 171133fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz else 171233fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz err = bluetooth_hsp_hw_constraint(&data->io); 171333fcbce4ce2c8b409fd242c64e45c664098e66b9Luiz Augusto von Dentz 1714b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 1715f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 17168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 1717b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1718b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1719f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 1720b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1721b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 1722b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1723b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 17245ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 17255ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 1726b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 17275ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 17285ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 17295ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 1730