pcm_bluetooth.c revision f1a8e719f5687bb32f2f5ed59f26a3203ad43efb
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> 30b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 315ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/asoundlib.h> 325ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann#include <alsa/pcm_external.h> 335ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/bluetooth.h> 358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#include <bluetooth/sco.h> 368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 37b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#include "ipc.h" 38b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 39b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define DBG(fmt, arg...) printf("DEBUG: %s: " fmt "\n" , __FUNCTION__ , ## arg) 40b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_TXBUFS 428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_TXBUFS 0x03 438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#ifndef SCO_RXBUFS 468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#define SCO_RXBUFS 0x04 478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz#endif 488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 49b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstruct bluetooth_data { 50b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_ioplug_t io; 51b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_sframes_t hw_ptr; 528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg; /* Bluetooth device config */ 538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int sock; /* Daemon unix socket */ 548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz uint8_t *buffer; /* Transfer buffer */ 558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz uint8_t count; /* Transfer buffer counter */ 56b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 57b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 58b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_start(snd_pcm_ioplug_t *io) 59b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 60b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann DBG("io %p", io); 61b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 62b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 63b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 64b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 65b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io) 66b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 67b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann DBG("io %p", io); 68b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 69b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 70b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 71b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 72b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_sframes_t bluetooth_pointer(snd_pcm_ioplug_t *io) 73b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 74b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 75b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("io %p", io); 77b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 788742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("hw_ptr=%lu", data->hw_ptr); 79b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 80b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return data->hw_ptr; 81b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 82b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 83b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_close(snd_pcm_ioplug_t *io) 84b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 85b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann struct bluetooth_data *data = io->private_data; 86b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 87b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann DBG("io %p", io); 88b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 89b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann free(data); 90b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 91b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 92b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 93b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 948742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 958742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 968742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Preparing with io->period_size = %lu, io->buffer_size = %lu", io->period_size, io->buffer_size); 1008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (io->stream == SND_PCM_STREAM_PLAYBACK) { 1028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* If not null for playback, xmms doesn't display time correctly */ 1038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 1048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else { 1068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* ALSA library is really picky on the fact hw_ptr is not null. If it is, capture won't start */ 1078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 1088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 1108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 1118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) 1138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 1168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 1178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 118f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz DBG("fd = %d, period_count = %d", cfg.fd, period_count); 1198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if(setsockopt(cfg.fd, SOL_SCO, 1218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz io->stream == SND_PCM_STREAM_PLAYBACK ? SCO_TXBUFS : SCO_RXBUFS, 1228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz &period_count, 1238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz sizeof(period_count)) == 0) { 1248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 1258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } else if(setsockopt(cfg.fd, SOL_SCO, 1268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz io->stream == SND_PCM_STREAM_PLAYBACK ? SO_SNDBUF : SO_RCVBUF, 1278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz &period_count, 1288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz sizeof(period_count)) == 0) { 1298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 1308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } else { 1318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz SNDERR("Unable to set number of SCO buffers : please upgrade your Kernel !"); 1328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return -EINVAL; 1338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 1358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic snd_pcm_sframes_t bluetooth_read(snd_pcm_ioplug_t *io, 1378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz const snd_pcm_channel_area_t *areas, 1388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t offset, 1398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t size) 1408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 1438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 1458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu, io->nonblock=%u", 1478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz areas->step, areas->first, offset, size, io->nonblock); 1488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (data->count == 0) { 1508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int nrecv; 1518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz nrecv = recv(cfg.fd, data->buffer, cfg.pkt_len, 1538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0 )); 1548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (nrecv == cfg.pkt_len) { 1568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = 0; 1578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Increment hardware transmition pointer */ 1588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) % io->buffer_size; 1598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1608742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else if (nrecv > 0) { 1618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = -EIO; 1628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz SNDERR(strerror(-ret)); 1638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else if (nrecv == -1 && errno == EAGAIN) { 1658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = -EAGAIN; 1668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else { /* nrecv < 0 */ 1688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* EPIPE means device underrun in ALSA world. But we mean we lost contact 1698742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz with server, so we have to find another error code */ 1708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = (errno == EPIPE ? -EIO : -errno); 1718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz SYSERR("Lost contact with headsetd"); 1728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if(ret == 0) { /* Still ok, proceed */ 1758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_write; 1768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz unsigned char *buff; 1778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1788742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz buff = (unsigned char *) areas->addr + (areas->first + areas->step * offset) / 8; 1798742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if((data->count + cfg.sample_size * size) <= cfg.pkt_len) 1818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_write = size; 1828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 1838742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_write = (cfg.pkt_len - data->count) / cfg.sample_size; 1848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz memcpy(buff, data->buffer + data->count, areas->step / 8 * frames_to_write); 1868742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->count += (areas->step / 8 * frames_to_write); 1878742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->count %= cfg.pkt_len; 1888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Return written frames count */ 1898742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_write; 1908742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1918742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1928742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("returning %d", (int)ret); 1938742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 1948742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 1958742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1968742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic snd_pcm_sframes_t bluetooth_write(snd_pcm_ioplug_t *io, 1978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz const snd_pcm_channel_area_t *areas, 1988742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t offset, 1998742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t size) 2008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 2018742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 2028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 2038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 2048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 2058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz unsigned char *buff; 2068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu, io->nonblock=%u", 2088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz areas->step, areas->first, offset, size, io->nonblock); 2098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if ((data->count + cfg.sample_size * size) <= cfg.pkt_len) 2118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 2128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 2138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = (cfg.pkt_len - data->count) / cfg.sample_size; 2148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 2168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz buff = (unsigned char *) areas->addr + (areas->first + areas->step * offset) / 8; 2178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz memcpy(data->buffer + data->count, buff, areas->step / 8 * frames_to_read); 2188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if ((data->count + areas->step / 8 * frames_to_read) == cfg.pkt_len) { 2208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int rsend; 2218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Actually send packet */ 2228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz rsend = send(cfg.fd, data->buffer, cfg.pkt_len, io->nonblock ? MSG_DONTWAIT : 0); 2238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (rsend > 0) { 2248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Reset count pointer */ 2258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->count = 0; 2268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Increment hardware transmition pointer */ 2288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) % io->buffer_size; 2298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 2318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 2328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else { 2338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* EPIPE means device underrun in ALSA world. But we mean we lost contact 2348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz with server, so we have to find another error code */ 2358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = (errno == EPIPE ? -EIO : -errno); 2368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if(errno == EPIPE) 2378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz SYSERR("Lost contact with headsetd"); 2388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 2398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 2408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else { 2418742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Remember we have some frame in the pipe now */ 2428742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->count += areas->step / 8 * frames_to_read; 2438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ask for more */ 2448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 2458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 2468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("returning %d", (int)ret); 2488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 2498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 2508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 251b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_ioplug_callback_t bluetooth_playback_callback = { 252b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .start = bluetooth_start, 253b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .stop = bluetooth_stop, 254b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .pointer = bluetooth_pointer, 255b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .close = bluetooth_close, 256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .hw_params = bluetooth_hw_params, 257b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .prepare = bluetooth_prepare, 258b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .transfer = bluetooth_write, 259b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 260b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 261b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_ioplug_callback_t bluetooth_capture_callback = { 262b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .start = bluetooth_start, 263b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .stop = bluetooth_stop, 264b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .pointer = bluetooth_pointer, 265b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .close = bluetooth_close, 266b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .hw_params = bluetooth_hw_params, 267b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .prepare = bluetooth_prepare, 268b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .transfer = bluetooth_read, 269b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 270b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 271b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 272b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 273b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_hw_constraint(snd_pcm_ioplug_t *io) 274b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 275b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 276b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 277b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 278b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 279b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 280b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 281b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 282b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 283b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_FORMAT_S16_LE 284b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 285b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann int err; 286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 293b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 294b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 295b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 296b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 297b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1, 1); 298b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 299b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 300b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 301b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 8000, 8000); 302b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 303b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 304b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 305b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 48, 48); 306b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 307b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 308b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 309b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 200); 310b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 311b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 312b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 313b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 314b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 315b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_cfg(struct bluetooth_data *data) 3175ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann{ 3188742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int res; 319f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz int len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_cfg); 320f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct ipc_packet *pkt; 3218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Sending PKT_TYPE_CFG_REQ..."); 323f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt = malloc(len); 324f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memset(pkt, 0, len); 325f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->type = PKT_TYPE_CFG_REQ; 326f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->role = PKT_ROLE_NONE; 327f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->error = PKT_ERROR_NONE; 328f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz res = send(data->sock, pkt, len, 0); 3298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (res < 0) 3308742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return errno; 3318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("OK - %d bytes sent", res); 3328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Waiting for response..."); 3348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 335f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memset(pkt, 0, len); 336f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz res = recv(data->sock, pkt, len, 0); 337f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 3388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (res < 0) 3398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return -errno; 3408742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("OK - %d bytes received", res); 341b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 342f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->type != PKT_TYPE_CFG_RSP) { 343f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz SNDERR("Unexpected packet type received: type = %d", pkt->type); 3448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return -EINVAL; 3458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 346b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 347f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->error != PKT_ERROR_NONE) { 348f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz SNDERR("Error while configuring device: error = %d", pkt->error); 349f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz return pkt->error; 3508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 351b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 352f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->length != sizeof(struct ipc_data_cfg)) { 3538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz SNDERR("Error while configuring device: packet size doesn't match"); 3548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return -EINVAL; 3558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 356b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 357f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memcpy(&data->cfg, pkt->data, sizeof(struct ipc_data_cfg)); 358b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3598742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Device configuration:"); 360f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 3618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u, sample_size=%u, rate=%u", 3628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->cfg.fd, data->cfg.fd_opt, data->cfg.channels, 3638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->cfg.pkt_len, data->cfg.sample_size, data->cfg.rate); 3648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 365f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (data->cfg.fd == -1) { 366f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz SNDERR("Error while configuring device: could not acquire audio socket"); 367f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz return -EINVAL; 368f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 369f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 370f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz free(pkt); 3718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 3728742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 3738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_init(struct bluetooth_data *data) 3758742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 3768742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int sk, err, id; 3778742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct sockaddr_un addr; 3788742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 379f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (!data) 380f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz return -EINVAL; 381f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 382b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann id = abs(getpid() * rand()); 383b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 384b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann sk = socket(PF_LOCAL, SOCK_DGRAM, 0); 385b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (sk < 0) { 386b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't open socket"); 387b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return -errno; 388b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 389b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 390b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann memset(&addr, 0, sizeof(addr)); 391b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann addr.sun_family = AF_UNIX; 392e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s/%d", 393e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg IPC_SOCKET_NAME, id); 394b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3958742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Binding address: %s", addr.sun_path + 1); 396b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 397b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't bind socket"); 398b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann close(sk); 399b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return -errno; 400b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 401b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 402b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann memset(&addr, 0, sizeof(addr)); 403b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann addr.sun_family = AF_UNIX; 404e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s", IPC_SOCKET_NAME); 405b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 4068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Connecting to address: %s", addr.sun_path + 1); 407b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 408b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't connect socket"); 409b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann close(sk); 410b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return -errno; 411b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 412b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 413b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann data->sock = sk; 414b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 415f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if ((err = bluetooth_cfg(data)) < 0) { 416f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz free(data); 4178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return err; 418f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 4198742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->buffer = malloc(data->cfg.pkt_len); 4218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz memset(data->buffer, 0, data->cfg.pkt_len); 423b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 4248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 4258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 4288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 4298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz// snd_config_iterator_t iter, next; 430f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 4318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 4328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Bluetooth PCM plugin blablabla (%s)", 4348742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 4358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz// snd_config_for_each(iter, next, conf) { 4378742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz// } 4388742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4398742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Initing Bluetooth..."); 440f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data = malloc(sizeof(struct bluetooth_data)); 441f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memset(data, 0, sizeof(struct bluetooth_data)); 442f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = bluetooth_init(data); 4438742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 4448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 4458742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Done"); 4468742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 447f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 448f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 449f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.mmap_rw = 0; /* No direct mmap communication */ 4508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 451f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 452b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann &bluetooth_playback_callback : &bluetooth_capture_callback; 453f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.poll_fd = data->cfg.fd; 454f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.poll_events = stream == SND_PCM_STREAM_PLAYBACK ? 455f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz POLLOUT : POLLIN; 456f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 457b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 458f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 459b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 460b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 461b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 462f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = bluetooth_hw_constraint(&data->io); 463b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 464f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 4658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 466b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 467b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 468f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 469b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 470b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 471b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 472b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 473f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz close(data->sock); 474f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz free(data); 4755ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 476b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 4775ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 4785ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 4795ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 480