pcm_bluetooth.c revision 9217b7d4f85216946943ab588e06b6bcd2f1b5bc
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{ 609217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_start %p", io); 61b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 62b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 63b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 64b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 65b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_stop(snd_pcm_ioplug_t *io) 66b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 679217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_stop %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 769217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_pointer %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 879217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("bluetooth_close %p", io); 88b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 89b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann free(data); 90b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 91b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 92b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 93b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 948742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_prepare(snd_pcm_ioplug_t *io) 958742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 968742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 978742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 9800c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Preparing with io->period_size = %lu, io->buffer_size = %lu", 9900c71248e732de0230c12df4240087a6b2747179Johan Hedberg io->period_size, io->buffer_size); 1008742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1019217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg if (io->stream == SND_PCM_STREAM_PLAYBACK) 10200c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* If not null for playback, xmms doesn't display time 10300c71248e732de0230c12df4240087a6b2747179Johan Hedberg * correctly */ 1048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = 0; 1059217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg else 10600c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* ALSA library is really picky on the fact hw_ptr is not null. 10700c71248e732de0230c12df4240087a6b2747179Johan Hedberg * If it is, capture won't start */ 1088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->hw_ptr = io->period_size; 1099217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 1108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 1118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 1128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_hw_params(snd_pcm_ioplug_t *io, snd_pcm_hw_params_t *params) 1148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1158742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 1178742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz uint32_t period_count = io->buffer_size / io->period_size; 11800c71248e732de0230c12df4240087a6b2747179Johan Hedberg int opt_name; 1199217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 1209217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg DBG("fd = %d, period_count = %d", cfg.fd, period_count); 12100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 12200c71248e732de0230c12df4240087a6b2747179Johan Hedberg opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 12300c71248e732de0230c12df4240087a6b2747179Johan Hedberg SCO_TXBUFS : SCO_RXBUFS; 1248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 12500c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (setsockopt(cfg.fd, SOL_SCO, opt_name, &period_count, 1269217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg sizeof(period_count)) == 0) 1278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 1289217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg 12900c71248e732de0230c12df4240087a6b2747179Johan Hedberg opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 1309217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg SO_SNDBUF : SO_RCVBUF; 13100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 13200c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (setsockopt(cfg.fd, SOL_SCO, opt_name, &period_count, 13300c71248e732de0230c12df4240087a6b2747179Johan Hedberg sizeof(period_count)) == 0) 1349217b7d4f85216946943ab588e06b6bcd2f1b5bcJohan Hedberg return 0; 13500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 136019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley /* backward compatible to the old patch */ 137019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley 138019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley opt_name = (io->stream == SND_PCM_STREAM_PLAYBACK) ? 139019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SCO_TXBUFS : SCO_RXBUFS; 140019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley 141019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley if (setsockopt(cfg.fd, SOL_SCO, opt_name, &period_count, 142019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley sizeof(period_count)) == 0) 143019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley return 0; 144019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley 145019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SNDERR("Unable to set number of SCO buffers: please upgrade your " 14600c71248e732de0230c12df4240087a6b2747179Johan Hedberg "kernel!"); 14700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 14800c71248e732de0230c12df4240087a6b2747179Johan Hedberg return -EINVAL; 1498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 1508742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1518742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic snd_pcm_sframes_t bluetooth_read(snd_pcm_ioplug_t *io, 1528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz const snd_pcm_channel_area_t *areas, 1538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t offset, 1548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t size) 1558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 1568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 1578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 15800c71248e732de0230c12df4240087a6b2747179Johan Hedberg snd_pcm_uframes_t frames_to_write, ret; 15900c71248e732de0230c12df4240087a6b2747179Johan Hedberg unsigned char *buff; 16000c71248e732de0230c12df4240087a6b2747179Johan Hedberg int nrecv; 1618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 1628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu, io->nonblock=%u", 1638742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz areas->step, areas->first, offset, size, io->nonblock); 1648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 16500c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->count > 0) 16600c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto proceed; 16700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 16800c71248e732de0230c12df4240087a6b2747179Johan Hedberg nrecv = recv(cfg.fd, data->buffer, cfg.pkt_len, 16900c71248e732de0230c12df4240087a6b2747179Johan Hedberg MSG_WAITALL | (io->nonblock ? MSG_DONTWAIT : 0)); 17000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 17100c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv < 0) { 17200c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 17300c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 1748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 17500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 17600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (nrecv != cfg.pkt_len) { 17700c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 17800c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR(strerror(-ret)); 17900c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 1808742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 1818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 18200c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 18300c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) % io->buffer_size; 18400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 18500c71248e732de0230c12df4240087a6b2747179Johan Hedbergproceed: 18600c71248e732de0230c12df4240087a6b2747179Johan Hedberg buff = (unsigned char *) areas->addr + (areas->first + areas->step * offset) / 8; 18700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 18800c71248e732de0230c12df4240087a6b2747179Johan Hedberg if ((data->count + cfg.sample_size * size) <= cfg.pkt_len) 18900c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = size; 19000c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 19100c71248e732de0230c12df4240087a6b2747179Johan Hedberg frames_to_write = (cfg.pkt_len - data->count) / cfg.sample_size; 19200c71248e732de0230c12df4240087a6b2747179Johan Hedberg 19300c71248e732de0230c12df4240087a6b2747179Johan Hedberg memcpy(buff, data->buffer + data->count, areas->step / 8 * frames_to_write); 19400c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count += (areas->step / 8 * frames_to_write); 19500c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count %= cfg.pkt_len; 19600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 19700c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Return written frames count */ 19800c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_write; 19900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 20000c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 20100c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("returning %lu", ret); 2028742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 2038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 2048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic snd_pcm_sframes_t bluetooth_write(snd_pcm_ioplug_t *io, 2068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz const snd_pcm_channel_area_t *areas, 2078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t offset, 2088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t size) 2098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 2108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct bluetooth_data *data = io->private_data; 2118742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct ipc_data_cfg cfg = data->cfg; 2128742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_sframes_t ret = 0; 2138742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz snd_pcm_uframes_t frames_to_read; 2148742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz unsigned char *buff; 21500c71248e732de0230c12df4240087a6b2747179Johan Hedberg int rsend; 2168742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 21700c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("areas->step=%u, areas->first=%u, offset=%lu, size=%lu," 21800c71248e732de0230c12df4240087a6b2747179Johan Hedberg "io->nonblock=%u", areas->step, areas->first, 21900c71248e732de0230c12df4240087a6b2747179Johan Hedberg offset, size, io->nonblock); 2208742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if ((data->count + cfg.sample_size * size) <= cfg.pkt_len) 2228742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = size; 2238742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz else 2248742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz frames_to_read = (cfg.pkt_len - data->count) / cfg.sample_size; 2258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 2268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Ready for more data */ 2278742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz buff = (unsigned char *) areas->addr + (areas->first + areas->step * offset) / 8; 2288742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz memcpy(data->buffer + data->count, buff, areas->step / 8 * frames_to_read); 2298742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 23000c71248e732de0230c12df4240087a6b2747179Johan Hedberg if ((data->count + areas->step / 8 * frames_to_read) != cfg.pkt_len) { 2318742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz /* Remember we have some frame in the pipe now */ 2328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->count += areas->step / 8 * frames_to_read; 2338742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz ret = frames_to_read; 23400c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto done; 2358742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 2368742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 23700c71248e732de0230c12df4240087a6b2747179Johan Hedberg rsend = send(cfg.fd, data->buffer, cfg.pkt_len, io->nonblock ? MSG_DONTWAIT : 0); 23800c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (rsend > 0) { 23900c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Reset count pointer */ 24000c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->count = 0; 24100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 24200c71248e732de0230c12df4240087a6b2747179Johan Hedberg /* Increment hardware transmition pointer */ 24300c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->hw_ptr = (data->hw_ptr + cfg.pkt_len / cfg.sample_size) % io->buffer_size; 24400c71248e732de0230c12df4240087a6b2747179Johan Hedberg 24500c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = frames_to_read; 24600c71248e732de0230c12df4240087a6b2747179Johan Hedberg } else if (rsend < 0) 24700c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = (errno == EPIPE) ? -EIO : -errno; 24800c71248e732de0230c12df4240087a6b2747179Johan Hedberg else 24900c71248e732de0230c12df4240087a6b2747179Johan Hedberg ret = -EIO; 25000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 25100c71248e732de0230c12df4240087a6b2747179Johan Hedbergdone: 2528742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("returning %d", (int)ret); 2538742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return ret; 2548742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 2558742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 256b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_ioplug_callback_t bluetooth_playback_callback = { 257b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .start = bluetooth_start, 258b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .stop = bluetooth_stop, 259b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .pointer = bluetooth_pointer, 260b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .close = bluetooth_close, 261b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .hw_params = bluetooth_hw_params, 262b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .prepare = bluetooth_prepare, 263b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .transfer = bluetooth_write, 264b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 265b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 266b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic snd_pcm_ioplug_callback_t bluetooth_capture_callback = { 267b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .start = bluetooth_start, 268b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .stop = bluetooth_stop, 269b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .pointer = bluetooth_pointer, 270b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .close = bluetooth_close, 271b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .hw_params = bluetooth_hw_params, 272b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .prepare = bluetooth_prepare, 273b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann .transfer = bluetooth_read, 274b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann}; 275b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 276b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann#define ARRAY_NELEMS(a) (sizeof((a)) / sizeof((a)[0])) 277b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 278b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannstatic int bluetooth_hw_constraint(snd_pcm_ioplug_t *io) 279b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann{ 280b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann snd_pcm_access_t access_list[] = { 281b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_RW_INTERLEAVED, 282b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann /* Mmap access is really useless fo this driver, but we 283b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * support it because some pieces of software out there 284b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann * insist on using it */ 285b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_ACCESS_MMAP_INTERLEAVED 286b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 287b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann unsigned int format_list[] = { 288b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SND_PCM_FORMAT_S16_LE 289b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann }; 290b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann int err; 291b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 292b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS, 293b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(access_list), access_list); 294b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 295b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 296b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 297b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT, 298b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann ARRAY_NELEMS(format_list), format_list); 299b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 300b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 301b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 302b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS, 1, 1); 303b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 304b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 305b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 306b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE, 8000, 8000); 307b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 308b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 309b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 310b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIOD_BYTES, 48, 48); 311b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 312b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 313b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 314b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS, 2, 200); 315b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 316b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 317b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 318b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 319b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann} 320b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3218742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_cfg(struct bluetooth_data *data) 3225ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann{ 323d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg int ret, len = sizeof(struct ipc_packet) + sizeof(struct ipc_data_cfg); 324f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct ipc_packet *pkt; 3258742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3268742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Sending PKT_TYPE_CFG_REQ..."); 32700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 328f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt = malloc(len); 32900c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!pkt) 33000c71248e732de0230c12df4240087a6b2747179Johan Hedberg return -ENOMEM; 33100c71248e732de0230c12df4240087a6b2747179Johan Hedberg 332f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memset(pkt, 0, len); 333f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->type = PKT_TYPE_CFG_REQ; 334f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->role = PKT_ROLE_NONE; 335f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz pkt->error = PKT_ERROR_NONE; 33600c71248e732de0230c12df4240087a6b2747179Johan Hedberg 337d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = send(data->sock, pkt, len, 0); 338d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg if (ret < 0) { 339d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -errno; 340d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 341d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg } else if (ret == 0) { 342d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -EIO; 343d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 344d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg } 34500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 346d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg DBG("OK - %d bytes sent", ret); 3478742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 3488742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Waiting for response..."); 3498742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 350f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memset(pkt, 0, len); 351d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = recv(data->sock, pkt, len, 0); 352d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg if (ret < 0) { 353d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -errno; 354d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 355d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg } else if (ret == 0) { 356d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -EIO; 357d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 358d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg } 35900c71248e732de0230c12df4240087a6b2747179Johan Hedberg 360d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg DBG("OK - %d bytes received", ret); 361b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 362f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->type != PKT_TYPE_CFG_RSP) { 36300c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR("Unexpected packet type received: type = %d", 36400c71248e732de0230c12df4240087a6b2747179Johan Hedberg pkt->type); 365d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -EINVAL; 366d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 3678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 368b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 369f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->error != PKT_ERROR_NONE) { 37000c71248e732de0230c12df4240087a6b2747179Johan Hedberg SNDERR("Error while configuring device: error = %d", 37100c71248e732de0230c12df4240087a6b2747179Johan Hedberg pkt->error); 372d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = pkt->error; 373d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 3748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 375b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 376f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (pkt->length != sizeof(struct ipc_data_cfg)) { 377019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SNDERR("Error while configuring device: packet size doesn't " 37800c71248e732de0230c12df4240087a6b2747179Johan Hedberg "match"); 379d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -EINVAL; 380d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 3818742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz } 382b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 383f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz memcpy(&data->cfg, pkt->data, sizeof(struct ipc_data_cfg)); 384b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 3858742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Device configuration:"); 386f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 38700c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("fd=%d, fd_opt=%u, channels=%u, pkt_len=%u, sample_size=%u," 38800c71248e732de0230c12df4240087a6b2747179Johan Hedberg "rate=%u", data->cfg.fd, data->cfg.fd_opt, 38900c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->cfg.channels, data->cfg.pkt_len, 39000c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->cfg.sample_size, data->cfg.rate); 3918742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 392f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (data->cfg.fd == -1) { 393019dd58ff876fcdaae5a7cd257822955d28b5b96Brad Midgley SNDERR("Error while configuring device: could not acquire " 39400c71248e732de0230c12df4240087a6b2747179Johan Hedberg "audio socket"); 395d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = -EINVAL; 396d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg goto done; 397f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz } 398f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 399d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg ret = 0; 40000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 401d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedbergdone: 402d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg free(pkt); 403d95acb81523269d5e00485bc1350f8b3e6ee0050Johan Hedberg return ret; 4048742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4058742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4068742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentzstatic int bluetooth_init(struct bluetooth_data *data) 4078742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 4088742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int sk, err, id; 4098742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz struct sockaddr_un addr; 4108742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 411f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz if (!data) 412f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz return -EINVAL; 413f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz 41400c71248e732de0230c12df4240087a6b2747179Johan Hedberg memset(data, 0, sizeof(struct bluetooth_data)); 41500c71248e732de0230c12df4240087a6b2747179Johan Hedberg 41600c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->sock = -1; 41700c71248e732de0230c12df4240087a6b2747179Johan Hedberg 418b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann id = abs(getpid() * rand()); 419b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 420b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann sk = socket(PF_LOCAL, SOCK_DGRAM, 0); 421b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (sk < 0) { 42200c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -errno; 423b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't open socket"); 424b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return -errno; 425b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 426b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 427b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann memset(&addr, 0, sizeof(addr)); 428b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann addr.sun_family = AF_UNIX; 429e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s/%d", 430e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg IPC_SOCKET_NAME, id); 431b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 4328742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Binding address: %s", addr.sun_path + 1); 433b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 43400c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -errno; 435b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't bind socket"); 436b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann close(sk); 43700c71248e732de0230c12df4240087a6b2747179Johan Hedberg return err; 438b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 439b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 440b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann memset(&addr, 0, sizeof(addr)); 441b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann addr.sun_family = AF_UNIX; 442e343f2b21a2209d5713e20ad38bbcc862897380bJohan Hedberg snprintf(addr.sun_path + 1, UNIX_PATH_MAX - 2, "%s", IPC_SOCKET_NAME); 443b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 4448742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz DBG("Connecting to address: %s", addr.sun_path + 1); 445b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) { 44600c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -errno; 447b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann SNDERR("Can't connect socket"); 448b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann close(sk); 44900c71248e732de0230c12df4240087a6b2747179Johan Hedberg return err; 450b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 451b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 452b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann data->sock = sk; 453b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 45400c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = bluetooth_cfg(data); 45500c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (err < 0) 4568742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return err; 4578742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4588742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz data->buffer = malloc(data->cfg.pkt_len); 45900c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data->buffer) 46000c71248e732de0230c12df4240087a6b2747179Johan Hedberg return -ENOMEM; 4618742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4628742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz memset(data->buffer, 0, data->cfg.pkt_len); 463b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 4648742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz return 0; 4658742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz} 4668742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 4678742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von DentzSND_PCM_PLUGIN_DEFINE_FUNC(bluetooth) 4688742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz{ 469f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz struct bluetooth_data *data; 4708742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz int err; 4718742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 47200c71248e732de0230c12df4240087a6b2747179Johan Hedberg DBG("Bluetooth PCM plugin (%s)", 4738742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz stream == SND_PCM_STREAM_PLAYBACK ? "Playback" : "Capture"); 4748742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 475f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data = malloc(sizeof(struct bluetooth_data)); 47600c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (!data) { 47700c71248e732de0230c12df4240087a6b2747179Johan Hedberg err = -ENOMEM; 47800c71248e732de0230c12df4240087a6b2747179Johan Hedberg goto error; 47900c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 48000c71248e732de0230c12df4240087a6b2747179Johan Hedberg 481f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = bluetooth_init(data); 4828742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz if (err < 0) 4838742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 4848742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 485f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.version = SND_PCM_IOPLUG_VERSION; 486f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.name = "Bluetooth Audio Device"; 48700c71248e732de0230c12df4240087a6b2747179Johan Hedberg data->io.mmap_rw = 0; /* No direct mmap communication */ 4888742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz 489f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.callback = stream == SND_PCM_STREAM_PLAYBACK ? 490b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann &bluetooth_playback_callback : &bluetooth_capture_callback; 491f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.poll_fd = data->cfg.fd; 492f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.poll_events = stream == SND_PCM_STREAM_PLAYBACK ? 49300c71248e732de0230c12df4240087a6b2747179Johan Hedberg POLLOUT : POLLIN; 494f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz data->io.private_data = data; 495b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 496f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = snd_pcm_ioplug_create(&data->io, name, stream, mode); 497b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) 498b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann goto error; 499b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 500f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz err = bluetooth_hw_constraint(&data->io); 501b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann if (err < 0) { 502f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz snd_pcm_ioplug_delete(&data->io); 5038742ce7c3e92a57cde47481281a4928f8d41a771Luiz Augusto von Dentz goto error; 504b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann } 505b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 506f1a8e719f5687bb32f2f5ed59f26a3203ad43efbLuiz Augusto von Dentz *pcmp = data->io.pcm; 507b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 508b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return 0; 509b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann 510b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmannerror: 51100c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data) { 51200c71248e732de0230c12df4240087a6b2747179Johan Hedberg if (data->sock >= 0) 51300c71248e732de0230c12df4240087a6b2747179Johan Hedberg close(data->sock); 51400c71248e732de0230c12df4240087a6b2747179Johan Hedberg free(data); 51500c71248e732de0230c12df4240087a6b2747179Johan Hedberg } 5165ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 517b8a407aa8470ad8d92d9142edb41c17548b0cb2cMarcel Holtmann return err; 5185ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann} 5195ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel Holtmann 5205ad9e0ec87dd078dc2a4e70967f1e9ace1ebf43fMarcel HoltmannSND_PCM_PLUGIN_SYMBOL(bluetooth); 521