pcm_bluetooth.c revision cae1e4ecd14d380252b0e00f71bc6cf2887ebd31
1e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann/* 2e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 3e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * BlueZ - Bluetooth protocol stack for Linux 4e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 5e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org> 6e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 7e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 8e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * This library is free software; you can redistribute it and/or 9e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * modify it under the terms of the GNU Lesser General Public 10e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * License as published by the Free Software Foundation; either 11e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * version 2.1 of the License, or (at your option) any later version. 12e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 13e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * This library is distributed in the hope that it will be useful, 14e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * but WITHOUT ANY WARRANTY; without even the implied warranty of 15e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Lesser General Public License for more details. 17e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 18e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * You should have received a copy of the GNU Lesser General Public 19e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * License along with this library; if not, write to the Free Software 20e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann * 22e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann */ 23e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann 24e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#ifdef HAVE_CONFIG_H 25e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#include <config.h> 26e7bd84e89e0af0cd2c2390bf7a173f90a473fc62Marcel Holtmann#endif 275ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 28b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/socket.h> 29b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include <sys/un.h> 306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <sys/time.h> 31e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg#include <pthread.h> 326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include <netinet/in.h> 34b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 355ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h> 365ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h> 375ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/bluetooth.h> 398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/sco.h> 408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 41b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h" 426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#include "sbc.h" 436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 44cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg// #define ENABLE_DEBUG 456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 46d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz#define BUFFER_SIZE 2048 47b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 48f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#ifdef ENABLE_DEBUG 49b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...) printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg) 50f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#else 51f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#define DBG(fmt, arg...) 52f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz#endif 53b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS 558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03 568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS 598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04 608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct rtp_header { 636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t cc:4; 646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t x:1; 656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t p:1; 666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t v:2; 676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t pt:7; 696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t m:1; 706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint16_t sequence_number; 726763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint32_t timestamp; 736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint32_t ssrc; 746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint32_t csrc[0]; 756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} __attribute__ ((packed)); 766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct rtp_payload { 786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t frame_count:4; 796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t rfa0:1; 806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t is_last_fragment:1; 816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t is_first_fragment:1; 826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t is_fragmented:1; 836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} __attribute__ ((packed)); 846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstruct bluetooth_a2dp { 866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg sbc_t sbc; /* Codec data */ 876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int samples; /* Number of encoded samples */ 886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg time_t timestamp; /* Codec samples timestamp */ 896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t buffer[BUFFER_SIZE]; /* Codec transfer buffer */ 906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int count; /* Codec transfer buffer counter */ 916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int nsamples; /* Cumulative number of codec samples */ 936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct timeval ntimestamp; /* Cumulative timeval */ 946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint16_t seq_num; /* */ 956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int frame_count; /* */ 966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 97e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pthread_t hw_thread; /* Makes virtual hw pointer move */ 98e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int pipefd[2]; /* Inter thread communication */ 996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 1006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 101b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data { 102b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_ioplug_t io; 103e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg volatile snd_pcm_sframes_t hw_ptr; 1048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg; /* Bluetooth device config */ 1059494c146cec1df466c2f331957748beeac8d745aJohan Hedberg int stream_fd; /* Audio stream filedescriptor */ 1068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int sock; /* Daemon unix socket */ 1076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t buffer[BUFFER_SIZE]; /* Encoded transfer buffer */ 1086763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int count; /* Transfer buffer counter */ 1096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp a2dp; /* a2dp data */ 110b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 111b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1126763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergvoid memcpy_changeendian(void *dst, const void *src, int size) 1136763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 1146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int i; 1156763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg const uint16_t *ptrsrc = src; 1166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint16_t *ptrdst = dst; 117e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 118e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg for (i = 0; i < size / 2; i++) 1196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg *ptrdst++ = htons(*ptrsrc++); 1206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 1216763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 122b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io) 123b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1249217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_start %p", io); 125b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 126b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 127b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 128b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 129b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io) 130b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 1319217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_stop %p", io); 132b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 133b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 134b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 135b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 136e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic void *a2dp_playback_hw_thread(void *param) 137e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 138e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = param; 139e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int prev_periods; 140e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg double period_time; 141e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct timeval start; 142e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 143e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg prev_periods = 0; 144e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg period_time = 1000000.0 * data->io.period_size / data->io.rate; 145e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 146e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg gettimeofday(&start, 0); 147e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 148e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg while (1) { 149e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned long long dtime; 150e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int periods; 151e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct timeval cur, delta; 152e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 153e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg gettimeofday(&cur, 0); 154e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 155e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg timersub(&cur, &start, &delta); 156e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 157e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg dtime = delta.tv_sec * 1000000 + delta.tv_usec; 158e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg periods = 1.0 * dtime / period_time; 159e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 160e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (periods > prev_periods) { 161e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 162e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 163e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data->hw_ptr += (periods - prev_periods) * 164e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data->io.period_size; 165e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data->hw_ptr %= data->io.buffer_size; 166e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 167e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("pointer = %ld", data->hw_ptr); 168e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 169e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Notify user that hardware pointer has moved */ 170e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (write(data->a2dp.pipefd[1], &c, 1) < 0) 171e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pthread_testcancel(); 172e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 173e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg prev_periods = periods; 174e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 175e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 176e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg usleep(period_time); 177e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 178e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Offer opportunity to be canceled by main thread */ 179e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pthread_testcancel(); 180e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 181e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 182e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_a2dp_playback_start(snd_pcm_ioplug_t *io) 183e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 184e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 185e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_a2dp *a2dp_data = &data->a2dp; 186e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int err; 187e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 188e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 189e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 190e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(a2dp_data->hw_thread == 0); 191e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 192e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg err = pthread_create(&a2dp_data->hw_thread, 0, 193e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg a2dp_playback_hw_thread, data); 194e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 195e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(" - return %d", -err); 196e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 197e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -err; 198e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 199e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 200e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_a2dp_playback_stop(snd_pcm_ioplug_t *io) 201e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 202e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 203e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_a2dp *a2dp_data = &data->a2dp; 204e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int err; 205e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 206e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("%p", io); 207e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 208e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Beware - We can be called more than once */ 209e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (a2dp_data->hw_thread == 0) 210e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 211e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 212e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg err = pthread_cancel(a2dp_data->hw_thread); 213e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (err != 0) 214e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg goto failed; 215e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 216e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg err = pthread_join(a2dp_data->hw_thread, 0); 217e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (err != 0) 218e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg goto failed; 219e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 220e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg a2dp_data->hw_thread = 0; 221e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 222e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergfailed: 223e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(" - return %d", -err); 224e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -err; 225e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 226e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 227b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io) 228b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 229b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 230b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#if 0 2326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("bluetooth_pointer %p, hw_ptr=%lu", io, data->hw_ptr); 2336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg#endif 234b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 235b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return data->hw_ptr; 236b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 237b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2385ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentzstatic void bluetooth_exit(struct bluetooth_data *data) 2395ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz{ 2405ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz if (data->sock >= 0) 2415ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz close(data->sock); 2425ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 2439494c146cec1df466c2f331957748beeac8d745aJohan Hedberg if (data->stream_fd >= 0) 2449494c146cec1df466c2f331957748beeac8d745aJohan Hedberg close(data->stream_fd); 2452a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz 246d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz if (data->cfg.codec == CFG_CODEC_SBC) 247d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz sbc_finish(&data->a2dp.sbc); 248d661010f0da37d072e9f3e0adcc94964fea6a054Luiz Augusto von Dentz 249cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (data->a2dp.pipefd[0] > 0) 250e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg close(data->a2dp.pipefd[0]); 251e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 252cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (data->a2dp.pipefd[1] > 0) 253e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg close(data->a2dp.pipefd[1]); 254e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 2555ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz free(data); 2565ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz} 2575ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz 258b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io) 259b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 260b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 261b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("%p", io); 263b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2645ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 265b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 266b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 267b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 268b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 2698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 2708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 2718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 272e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg char c = 'w'; 2738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 27400c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Preparing with io->period_size = %lu, io->buffer_size = %lu", 27500c71248e732de0230c12df4240087a6b2747179Johan Hedberg io->period_size, io->buffer_size); 2768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2779217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg if (io->stream == SND_PCM_STREAM_PLAYBACK) 27800c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* If not null for playback, xmms doesn't display time 27900c71248e732de0230c12df4240087a6b2747179Johan Hedberg * correctly */ 2808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 2819217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg else 28200c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* ALSA library is really picky on the fact hw_ptr is not null. 28300c71248e732de0230c12df4240087a6b2747179Johan Hedberg * If it is, capture won't start */ 2848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 2859217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 286e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* a2dp : wake up any client polling at us */ 287e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return write(data->a2dp.pipefd[1], &c, 1); 2888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 2898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 290afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_hsp_hw_params(snd_pcm_ioplug_t *io, 291afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 2928742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 2938742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 2948742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 295c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz int opt_name, err; 2969217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 2976e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann DBG("fd = %d, period_count = %d", data->stream_fd, period_count); 298ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 29900c71248e732de0230c12df4240087a6b2747179Johan Hedberg opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 30000c71248e732de0230c12df4240087a6b2747179Johan Hedberg SCO_TXBUFS : SCO_RXBUFS; 3018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3029494c146cec1df466c2f331957748beeac8d745aJohan Hedberg if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count, 3039217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg sizeof(period_count)) == 0) 3048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 3059217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 30600c71248e732de0230c12df4240087a6b2747179Johan Hedberg opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 3076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg SO_SNDBUF : SO_RCVBUF; 30800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 3099494c146cec1df466c2f331957748beeac8d745aJohan Hedberg if (setsockopt(data->stream_fd, SOL_SCO, opt_name, &period_count, 31000c71248e732de0230c12df4240087a6b2747179Johan Hedberg sizeof(period_count)) == 0) 3119217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg return 0; 31200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 313c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = errno; 314c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz SNDERR("%s (%d)", strerror(err), err); 31500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 316c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz return -err; 3178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 3188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 319afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentzstatic int bluetooth_a2dp_hw_params(snd_pcm_ioplug_t *io, 320afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz snd_pcm_hw_params_t *params) 321afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz{ 322afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 323afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 324afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz int opt_name, err; 325afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz struct timeval t = { 0, period_count }; 326afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 327afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz DBG("fd = %d, period_count = %d", data->stream_fd, period_count); 328afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 329afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 330afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz SO_SNDTIMEO : SO_RCVTIMEO; 331afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 332afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz if (setsockopt(data->stream_fd, SOL_SOCKET, opt_name, &t, 333afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz sizeof(t)) == 0) 334afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz return 0; 335afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 336afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz err = errno; 337e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 338afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz SNDERR("%s (%d)", strerror(err), err); 339afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 340afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz return -err; 341afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz} 342afc2f9e31b18b2572e90902c86d6b75368e1e9c6Luiz Augusto von Dentz 343e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_descriptors(snd_pcm_ioplug_t *io, 344e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfd, 345e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int space) 346e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 347e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 348e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 349e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(io); 350e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 351e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 352e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 353e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 354e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].fd = data->stream_fd; 355e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 356e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 357e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 358e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 359e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 360e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 361e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED, 362e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, unsigned int nfds, 363e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned short *revents) 364e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 365e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds && nfds == 1 && revents); 366e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 367e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = pfds[0].revents; 368e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 369e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 370e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 371e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 372e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_a2dp_playback_poll_descriptors(snd_pcm_ioplug_t *io, 373e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfd, 374e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int space) 375e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 376e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct bluetooth_data *data = io->private_data; 377e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 378e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 379e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 380e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(data->a2dp.pipefd[0] >= 0); 381e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 382e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (space < 1) 383e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 384e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 385e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].fd = data->a2dp.pipefd[0]; 386e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].events = POLLIN; 387e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg pfd[0].revents = 0; 388e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 389e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 1; 390e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 391e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 392e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int bluetooth_a2dp_playback_poll_revents(snd_pcm_ioplug_t *io, 393e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg struct pollfd *pfds, 394e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned int nfds, 395e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg unsigned short *revents) 396e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg{ 397e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg static char buf[1]; 398e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret; 399e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 400e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 401e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 402e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds); 403e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(nfds == 1); 404e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(revents); 405e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(pfds[0].fd >= 0); 406e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 407e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg if (io->state != SND_PCM_STATE_PREPARED) 408e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = read(pfds[0].fd, buf, 1); 409e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 410e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg *revents = (pfds[0].revents & ~POLLIN) | POLLOUT; 411e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 412e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return 0; 413e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg} 414e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 415e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 4166763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_read(snd_pcm_ioplug_t *io, 4176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg const snd_pcm_channel_area_t *areas, 4186763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t offset, 4196763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t size) 4208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 4218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 4228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 42300c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 42400c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 425f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int nrecv, frame_size = 0; 4268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu," 4286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg "io->nonblock=%u", areas->step, areas->first, offset, size, 4296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg io->nonblock); 4308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 43100c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 43200c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 43300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 434f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 435f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz 4369494c146cec1df466c2f331957748beeac8d745aJohan Hedberg nrecv = recv(data->stream_fd, data->buffer, cfg.pkt_len, 43700c71248e732de0230c12df4240087a6b2747179Johan Hedberg MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0)); 43800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 43900c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 44000c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 44100c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 4428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 44300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 44400c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv != cfg.pkt_len) { 44500c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 44600c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 44700c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 4488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 4498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 45000c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 4516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) % 4526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg io->buffer_size; 45300c71248e732de0230c12df4240087a6b2747179Johan Hedberg 45400c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 4556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (unsigned char *) areas->addr + 4566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 45700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 4582a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz if ((data->count + size * frame_size) <= cfg.pkt_len) 45900c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 46000c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 461f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frames_to_write = (cfg.pkt_len - data->count) / frame_size; 46200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 463f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(buff, data->buffer + data->count, frame_size * frames_to_write); 464f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->count += (frame_size * frames_to_write); 46500c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count %= cfg.pkt_len; 46600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 46700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 46800c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 46900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 47000c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 47100c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 4728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 4738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_hsp_write(snd_pcm_ioplug_t *io, 4766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg const snd_pcm_channel_area_t *areas, 4776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t offset, 4786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t size) 4798742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 4808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 4818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 4828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 4838742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 484c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz uint8_t *buff; 485f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz int rsend, frame_size; 4868742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 48700c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu," 48800c71248e732de0230c12df4240087a6b2747179Johan Hedberg "io->nonblock=%u", areas->step, areas->first, 48900c71248e732de0230c12df4240087a6b2747179Johan Hedberg offset, size, io->nonblock); 4908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 491f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frame_size = areas->step / 8; 492f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz if ((data->count + size * frame_size) <= cfg.pkt_len) 4938742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 4948742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 495f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz frames_to_read = (cfg.pkt_len - data->count) / frame_size; 4968742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 497c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz DBG("count = %d, frames_to_read = %lu", data->count, frames_to_read); 498c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 4998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 5006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 5016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 502f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz memcpy(data->buffer + data->count, buff, frame_size * frames_to_read); 5038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 5046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 5052a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz data->count += frames_to_read * frame_size; 5062a2c204cd0e4bcf0a603ba72be9a50203a817b54Luiz Augusto von Dentz if (data->count != cfg.pkt_len) { 5078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 50800c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 5098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 5108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 5119494c146cec1df466c2f331957748beeac8d745aJohan Hedberg rsend = send(data->stream_fd, data->buffer, cfg.pkt_len, 512c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz io->nonblock ? MSG_DONTWAIT : 0); 51300c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 51400c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 51500c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 51600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 51700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 518f6ca761e65a9318e0173ade27501fb41604ee14cLuiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + cfg.pkt_len / frame_size) 519c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz % io->buffer_size; 52000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 52100c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 52200c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 52300c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 52400c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 52500c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 52600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 52700c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 5286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("returning %lu", ret); 5296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 5306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 5316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 5326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_read(snd_pcm_ioplug_t *io, 5336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg const snd_pcm_channel_area_t *areas, 5346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t offset, 5356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t size) 5366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 5376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t ret = 0; 5386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 5396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 5406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 541e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedbergstatic int avdtp_write(struct bluetooth_data *data) 5426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 543e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg int ret = 0; 5446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_header *header; 5456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct rtp_payload *payload; 5469494c146cec1df466c2f331957748beeac8d745aJohan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 5476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 548e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG(""); 5496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header = (void *) a2dp->buffer; 5506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload = (void *) (a2dp->buffer + sizeof(*header)); 5516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 5526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(a2dp->buffer, 0, sizeof(*header) + sizeof(*payload)); 5536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 5546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg payload->frame_count = a2dp->frame_count; 5556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->v = 2; 5566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->pt = 1; 5576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->sequence_number = htons(a2dp->seq_num); 5586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->timestamp = htonl(a2dp->nsamples); 5596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg header->ssrc = htonl(1); 5606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 561e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = send(data->stream_fd, a2dp->buffer, a2dp->count, 562e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg MSG_DONTWAIT); 563cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret == -1) 564e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -errno; 5658905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 566e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Kernel side l2cap socket layer makes sure either everything 567e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg is buffered for sending, or nothing is buffered. 568e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg This assertion is to remind people of this fact (and be noticed 569e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg the day that changes) 570e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg */ 571e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg assert(ret < 0 || ret == a2dp->count); 5728905b2bad9aebd0911d452b53b9cbe975ad5bdccJohan Hedberg 5736763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reset buffer of data to send */ 5746763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + sizeof(struct rtp_payload); 5756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count = 0; 5766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples = 0; 5776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->seq_num++; 5786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 579f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg return ret; 5806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 5816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 5826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_sframes_t bluetooth_a2dp_write(snd_pcm_ioplug_t *io, 5836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg const snd_pcm_channel_area_t *areas, 5846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t offset, 5856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t size) 5866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 5876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_data *data = io->private_data; 5886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 5896763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_sframes_t ret = 0; 5906763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg snd_pcm_uframes_t frames_to_read; 5916763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int frame_size, encoded; 5926763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg uint8_t *buff; 5936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg static int codesize = 0; 5946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 595e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu" 596e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg , areas->step, areas->first, offset, size); 597e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("hw_ptr = %lu, appl_ptr = %lu" 598e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg , io->hw_ptr, io->appl_ptr); 599e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 600cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->hw_ptr > io->appl_ptr) { 601e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = bluetooth_a2dp_playback_stop(io); 602cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret == 0) 603e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = -EPIPE; 604e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg goto done; 605e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 606e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 607e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg /* Check if we should autostart */ 608cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->state == SND_PCM_STATE_PREPARED) { 609e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_t *swparams; 610e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_uframes_t threshold; 611e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 612e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_malloc(&swparams); 613cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (!snd_pcm_sw_params_current(io->pcm, swparams) 614e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg && !snd_pcm_sw_params_get_start_threshold(swparams, 615e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg &threshold) ) { 616cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (io->appl_ptr >= threshold) { 617e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = snd_pcm_start(io->pcm); 618cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (ret != 0) 619e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg goto done; 620e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 621e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 622e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg snd_pcm_sw_params_free(swparams); 623e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg } 6246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (codesize == 0) { 6266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* How much data can be encoded by sbc at a time? */ 6276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg codesize = a2dp->sbc.subbands * a2dp->sbc.blocks * 6286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.channels * 2; 6296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Reserv header space in outgoing buffer */ 6306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count = sizeof(struct rtp_header) + 6316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg sizeof(struct rtp_payload); 6326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg gettimeofday(&a2dp->ntimestamp, NULL); 6336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 6346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg frame_size = areas->step / 8; 6366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if ((data->count + size * frame_size) <= codesize) 6376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg frames_to_read = size; 6386763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 6396763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg frames_to_read = (codesize - data->count) / frame_size; 6406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("count = %d, frames_to_read = %lu", data->count, frames_to_read); 6426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("a2dp.count = %d cfg.pkt_len = %d", a2dp->count, 6436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->cfg.pkt_len); 6446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* FIXME: If state is not streaming then return */ 6466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Ready for more data */ 6486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg buff = (uint8_t *) areas->addr + 6496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg (areas->first + areas->step * offset) / 8; 6506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memcpy_changeendian(data->buffer + data->count, buff, 6516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg frame_size * frames_to_read); 6526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Remember we have some frames in the pipe now */ 6546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->count += frames_to_read * frame_size; 6556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (data->count != codesize) { 6566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = frames_to_read; 6576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg goto done; 6586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 6596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* Enough data to encode (sbc wants 1k blocks) */ 6616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg encoded = sbc_encode(&(a2dp->sbc), data->buffer, codesize); 6626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (encoded <= 0) { 6636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("Encoding error %d", encoded); 6646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg goto done; 6656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 6666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6676763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->count -= encoded; 6686763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("encoded = %d a2dp.sbc.len= %d", encoded, a2dp->sbc.len); 6706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 671f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg if (a2dp->count + a2dp->sbc.len >= data->cfg.pkt_len) { 672e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg ret = avdtp_write(data); 673f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg if (ret < 0) { 674f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg if (-ret == EPIPE) 675f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg ret = -EIO; 676f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg goto done; 677f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 678f802c1c270aadd8e6c019cce1ee6a89f5c784a65Johan Hedberg } 6796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memcpy(a2dp->buffer + a2dp->count, a2dp->sbc.data, a2dp->sbc.len); 6816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->count += a2dp->sbc.len; 6826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->frame_count++; 6836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->samples += encoded / frame_size; 6846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->nsamples += encoded / frame_size; 6856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = frames_to_read; 6876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 6886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 689e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg DBG("returning %ld", ret); 6908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 6918742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 6928742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 6936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_playback = { 694e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 695e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 696e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 697e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 698e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_hsp_hw_params, 699e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 700e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_write, 701e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 702e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 7036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 7046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 7056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_hsp_capture = { 706e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 707e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 708e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 709e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 710e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_hsp_hw_params, 711e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 712e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_hsp_read, 713e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 714e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 715b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 716b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 7176763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_playback = { 718e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_a2dp_playback_start, 719e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_a2dp_playback_stop, 720e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 721e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 722e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 723e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 724e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_write, 725e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_a2dp_playback_poll_descriptors, 726e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_a2dp_playback_poll_revents, 7276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg}; 7286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 7296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic snd_pcm_ioplug_callback_t bluetooth_a2dp_capture = { 730e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .start = bluetooth_start, 731e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .stop = bluetooth_stop, 732e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .pointer = bluetooth_pointer, 733e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .close = bluetooth_close, 734e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .hw_params = bluetooth_a2dp_hw_params, 735e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .prepare = bluetooth_prepare, 736e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .transfer = bluetooth_a2dp_read, 737e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_descriptors = bluetooth_poll_descriptors, 738e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .poll_revents = bluetooth_poll_revents, 739b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 740b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 741b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 742b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 743b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_hw_constraint(snd_pcm_ioplug_t *io) 744b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 745c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 746c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 747b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 748b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 749b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 750b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 751b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 752b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 753b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 754b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 755b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_FORMAT_S16_LE 756b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 757b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann int err; 758b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 759c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* access type */ 760b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 761b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 762b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 763b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 764b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 765c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported formats */ 766b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 767b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 768b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 769b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 770b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 771c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz /* supported channels */ 772c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 773c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz cfg.channels, cfg.channels); 774b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 775b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 776b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 77735b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported rate */ 778c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 779c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz cfg.rate, cfg.rate); 780b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 781b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 782b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 78335b7eb29eebf1a85fce60aa0b946ff2e04ebf684Luiz Augusto von Dentz /* supported block size */ 784c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 785c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz cfg.pkt_len, cfg.pkt_len); 786b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 787b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 788b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 789c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 790e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 2, 50); 791b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 792b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 793b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 794b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 795b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 796b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 797ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentzstatic int bluetooth_recvmsg_fd(struct bluetooth_data *data) 798ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz{ 799ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz char cmsg_b[CMSG_SPACE(sizeof(int))]; 800ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz struct ipc_packet pkt; 801ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz int err, ret; 802ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz struct iovec iov = { 803ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz .iov_base = &pkt, 804ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz .iov_len = sizeof(pkt) 805ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz }; 806ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz struct msghdr msgh = { 807e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_name = 0, 808e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_namelen = 0, 809e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_iov = &iov, 810e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_iovlen = 1, 811e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_control = &cmsg_b, 812e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_controllen = CMSG_LEN(sizeof(int)), 813e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg .msg_flags = 0 814ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz }; 815ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 816ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz ret = recvmsg(data->sock, &msgh, 0); 817ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz if (ret < 0) { 818ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz err = errno; 819ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz SNDERR("Unable to receive fd: %s (%d)", strerror(err), err); 820ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz return -err; 821ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz } 822ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 823e703434f83af5a41cb2f27604aedc8b2d15024e2Johan Hedberg if (pkt.type == PKT_TYPE_CFG_RSP) { 824ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz struct cmsghdr *cmsg; 825ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz /* Receive auxiliary data in msgh */ 826ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL; 827e703434f83af5a41cb2f27604aedc8b2d15024e2Johan Hedberg cmsg = CMSG_NXTHDR(&msgh,cmsg)) { 828ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz if (cmsg->cmsg_level == SOL_SOCKET 829ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz && cmsg->cmsg_type == SCM_RIGHTS) 8309494c146cec1df466c2f331957748beeac8d745aJohan Hedberg data->stream_fd = (*(int *) CMSG_DATA(cmsg)); 8319494c146cec1df466c2f331957748beeac8d745aJohan Hedberg DBG("stream_fd = %d", data->stream_fd); 832ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz return 0; 833ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz } 834ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz } 835ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz else 836ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz SNDERR("Unexpected packet type received: type = %d", pkt.type); 837ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 838ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz return -EINVAL; 839ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz} 840ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz 8416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_a2dp_init(struct bluetooth_data *data, 8426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct ipc_codec_sbc *sbc) 8435ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann{ 8446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 8456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct ipc_data_cfg *cfg = &data->cfg; 8468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 8476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (cfg == NULL) { 8486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg SNDERR("Error getting codec parameters"); 8496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -1; 8506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 85100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 8526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (cfg->codec != CFG_CODEC_SBC) 8536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -1; 8546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 8556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg /* FIXME: init using flags? */ 8566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg sbc_init(&a2dp->sbc, 0); 8576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.rate = cfg->rate; 8586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.channels = cfg->channels; 8596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (cfg->channel_mode == CFG_CHANNEL_MODE_MONO || 8606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg cfg->channel_mode == CFG_CHANNEL_MODE_JOINT_STEREO) 8616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.joint = 1; 8626763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.allocation = sbc->allocation; 8636763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.subbands = sbc->subbands; 8646763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.blocks = sbc->blocks; 8656763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.bitpool = sbc->bitpool; 86600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 867e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 868cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (pipe(a2dp->pipefd) != 0) 869e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -errno; 870cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (fcntl(a2dp->pipefd[0], F_SETFL, O_NONBLOCK) != 0) 871e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -errno; 872cae1e4ecd14d380252b0e00f71bc6cf2887ebd31Johan Hedberg if (fcntl(a2dp->pipefd[1], F_SETFL, O_NONBLOCK) != 0) 873e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg return -errno; 874e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg 8756763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 8766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg} 8776763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 8786763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_cfg(struct bluetooth_data *data, snd_config_t *conf) 8796763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg{ 8806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int ret, total; 8816763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg char buf[IPC_MTU]; 8826763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct ipc_packet *pkt = (void *) buf; 8836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct ipc_data_cfg *cfg = (void *) pkt->data; 8846763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct ipc_codec_sbc *sbc = (void *) cfg->data; 8856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 8866763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("Sending PKT_TYPE_CFG_REQ..."); 8876763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 8886763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(buf, 0, sizeof(buf)); 889f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->type = PKT_TYPE_CFG_REQ; 890f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->role = PKT_ROLE_NONE; 891f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->error = PKT_ERROR_NONE; 89200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 8936763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = send(data->sock, pkt, sizeof(struct ipc_packet), 0); 8946763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (ret < 0) 8956763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -errno; 8966763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else if (ret == 0) 8976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EIO; 89800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 8996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("OK - %d bytes sent. Waiting for response...", ret); 9008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memset(buf, 0, sizeof(buf)); 9028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9036763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = recv(data->sock, buf, sizeof(*pkt) + sizeof(*cfg), 0); 9046763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (ret < 0) 9056763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -errno; 9066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else if (ret == 0) 9076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EIO; 90800c71248e732de0230c12df4240087a6b2747179Johan Hedberg 9096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg total = ret; 910b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 911f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->type != PKT_TYPE_CFG_RSP) { 91200c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR("Unexpected packet type received: type = %d", 91300c71248e732de0230c12df4240087a6b2747179Johan Hedberg pkt->type); 9146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EINVAL; 9158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 916b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 917f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->error != PKT_ERROR_NONE) { 91800c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR("Error while configuring device: error = %d", 91900c71248e732de0230c12df4240087a6b2747179Johan Hedberg pkt->error); 9206763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return pkt->error; 9218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 922b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 9236763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (cfg->codec != CFG_CODEC_SBC) 9246763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg goto done; 9256763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9266763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = recv(data->sock, sbc, sizeof(*sbc), 0); 9276763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (ret < 0) 9286763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -errno; 9296763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else if (ret == 0) 9306763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EIO; 9316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9326763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg total += ret; 9336763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9346763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergdone: 9356763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("OK - %d bytes received", total); 9366763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9376763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (pkt->length != (total - sizeof(struct ipc_packet))) { 938019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SNDERR("Error while configuring device: packet size doesn't " 93900c71248e732de0230c12df4240087a6b2747179Johan Hedberg "match"); 9406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EINVAL; 9418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 942b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 9436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg memcpy(&data->cfg, cfg, sizeof(*cfg)); 944b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 9458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Device configuration:"); 946f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 9476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg DBG("\n\tfd=%d\n\tfd_opt=%u\n\tchannels=%u\n\tpkt_len=%u\n" 9486e1dd6ef0f595cf51204545e2aa5d6b90225fee4Marcel Holtmann "\tsample_size=%u\n\trate=%u", data->stream_fd, 9496763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->cfg.fd_opt, data->cfg.channels, data->cfg.pkt_len, 9506763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->cfg.sample_size, data->cfg.rate); 9516763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 9526763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (data->cfg.codec == CFG_CODEC_SBC) { 9536763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg struct bluetooth_a2dp *a2dp = &data->a2dp; 9546763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = bluetooth_a2dp_init(data, sbc); 9556763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (ret < 0) 9566763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 9576763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg printf("\tallocation=%u\n\tsubbands=%u\n\tblocks=%u\n\t" 9586763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg "bitpool=%u\n", a2dp->sbc.allocation, 9596763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.subbands, a2dp->sbc.blocks, 9606763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg a2dp->sbc.bitpool); 9616763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg } 9628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9639494c146cec1df466c2f331957748beeac8d745aJohan Hedberg if (data->stream_fd == -1) { 964019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SNDERR("Error while configuring device: could not acquire " 96500c71248e732de0230c12df4240087a6b2747179Johan Hedberg "audio socket"); 9666763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -EINVAL; 967f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 968f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 9696763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg ret = bluetooth_recvmsg_fd(data); 9706763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (ret < 0) 9716763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return ret; 972c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 973ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz /* It is possible there is some outstanding 974ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz data in the pipe - we have to empty it */ 9759494c146cec1df466c2f331957748beeac8d745aJohan Hedberg while (recv(data->stream_fd, data->buffer, data->cfg.pkt_len, 9766763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg MSG_DONTWAIT) > 0); 97700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 978c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz memset(data->buffer, 0, data->cfg.pkt_len); 979c6136c57053db24e9c4e2448f25bd46f6a90b053Luiz Augusto von Dentz 9806763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return 0; 9818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 9828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9836763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedbergstatic int bluetooth_init(struct bluetooth_data *data, snd_config_t *conf) 9848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 9856763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg int sk, err; 986ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz struct sockaddr_un addr = { 987ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz AF_UNIX, IPC_SOCKET_NAME 988ddf8edc54d666f9b6f75f28b6db5375e2f0982a8Luiz Augusto von Dentz }; 9898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 990f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (!data) 991f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz return -EINVAL; 992f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 99300c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 99400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 99500c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->sock = -1; 99600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 9976763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg sk = socket(PF_LOCAL, SOCK_STREAM, 0); 9986763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (sk < 0) { 9996763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg err = errno; 10006763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg SNDERR("Cannot open socket: %s (%d)", strerror(err), err); 10016763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -err; 1002b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1003b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 10048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Connecting to address: %s", addr.sun_path + 1); 1005b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 10066763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg err = errno; 10076763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg SNDERR("Connection fail", strerror(err), err); 1008b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann close(sk); 10096763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return -err; 1010b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1011b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1012b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann data->sock = sk; 1013b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 10146763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg return bluetooth_cfg(data, conf); 10158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 10168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 10178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 10188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1019f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 10208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 10218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 102200c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 10238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 10248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1025e7407648f54c18f4995eff0dc4c809b33a306fcdJohan Hedberg data = calloc(1, sizeof(struct bluetooth_data)); 102600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 102700c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 102800c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 102900c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 103000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 10316763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg err = bluetooth_init(data, conf); 10328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 10338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 10348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1035f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 1036f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 103700c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 1038f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 1039b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 10406763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg if (data->cfg.codec == CFG_CODEC_SBC) 10416763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 10426763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_playback : 10436763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_a2dp_capture; 10446763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg else 10456763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 10466763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_playback : 10476763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg &bluetooth_hsp_capture; 10486763ebb3c231740c66a235f94d56e8d8cc213d90Johan Hedberg 1049f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 1050b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 1051b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 1052b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1053f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = bluetooth_hw_constraint(&data->io); 1054b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 1055f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 10568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 1057b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 1058b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1059f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 1060b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1061b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 1062b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 1063b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 10645ed2a3ba745856206c66d8ecb98afb8a1f9ec7b5Luiz Augusto von Dentz bluetooth_exit(data); 10655ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 1066b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 10675ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 10685ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 10695ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 1070