1b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau/* 2b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 3b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * BlueZ - Bluetooth protocol stack for Linux 4b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 55592142cb9383df0556b27ac59e96547b380310bJohan Hedberg * Copyright (C) 2006-2010 Nokia Corporation 69184e2eeb7b97371c6b83b747c8984e2340d2b47Marcel Holtmann * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> 7563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau * Copyright (C) 2009 Lennart Poettering 8563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau * Copyright (C) 2008 Joao Paulo Rechi Vita 9b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 10b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 11b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * This library is free software; you can redistribute it and/or 12b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * modify it under the terms of the GNU Lesser General Public 13b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * License as published by the Free Software Foundation; either 14b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * version 2.1 of the License, or (at your option) any later version. 15b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 16b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * This library is distributed in the hope that it will be useful, 17b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * but WITHOUT ANY WARRANTY; without even the implied warranty of 18b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * Lesser General Public License for more details. 20b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 21b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * You should have received a copy of the GNU Lesser General Public 22b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * License along with this library; if not, write to the Free Software 23b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 24b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * 25b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau */ 26b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 27b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#ifdef HAVE_CONFIG_H 28b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <config.h> 29b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#endif 30b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 31b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <stdlib.h> 32b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <stdio.h> 33b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <errno.h> 34b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <string.h> 35b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <assert.h> 36b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <libgen.h> 37b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#include <unistd.h> 38b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#include <fcntl.h> 39a8eb557ae742f829c641682520b0e6e341caf18cJohan Hedberg#include <signal.h> 40b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 41b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include <glib.h> 42b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 43b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include "ipc.h" 44b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#include "sbc.h" 45b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 46b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#define DBG(fmt, arg...) \ 47b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau printf("debug %s: " fmt "\n" , __FUNCTION__ , ## arg) 48b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#define ERR(fmt, arg...) \ 49b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau fprintf(stderr, "ERROR %s: " fmt "\n" , __FUNCTION__ , ## arg) 50b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 51b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 52b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 53b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#ifndef MIN 54b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau# define MIN(x, y) ((x) < (y) ? (x) : (y)) 55b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#endif 56b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 57b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#ifndef MAX 58b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau# define MAX(x, y) ((x) > (y) ? (x) : (y)) 59b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#endif 60b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 61b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#ifndef TRUE 62b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau# define TRUE (1) 63b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#endif 64b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 65b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#ifndef FALSE 66b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau# define FALSE (0) 67b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#endif 68b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 69b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#define YES_NO(t) ((t) ? "yes" : "no") 70b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 71b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#define BUFFER_SIZE 2048 72b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#define MAX_BITPOOL 64 73b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#define MIN_BITPOOL 2 74b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 75b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustruct a2dp_info { 76b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_capabilities_t sbc_capabilities; 77b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_t sbc; /* Codec data */ 78b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int sbc_initialized; /* Keep track if the encoder is initialized */ 79b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau size_t codesize; /* SBC codesize */ 80b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 81b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau void* buffer; /* Codec transfer buffer */ 82b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau size_t buffer_size; /* Size of the buffer */ 83b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 84b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint16_t seq_num; /* Cumulative packet sequence */ 85b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau}; 86b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 87b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustruct hsp_info { 88b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau pcm_capabilities_t pcm_capabilities; 89b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau}; 90b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 91b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustruct userdata { 92b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int service_fd; 93b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int stream_fd; 94b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau GIOChannel *stream_channel; 95b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau guint stream_watch; 96563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau GIOChannel *gin; /* dude, I am thirsty now */ 97563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau guint gin_watch; 98b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int transport; 99b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint32_t rate; 100b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int channels; 10164989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau char *address; 102b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct a2dp_info a2dp; 103b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct hsp_info hsp; 104b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau size_t link_mtu; 105b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau size_t block_size; 106454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau gboolean debug_stream_read : 1; 107454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau gboolean debug_stream_write : 1; 108b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau}; 109b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 110b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic struct userdata data = { 111b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .service_fd = -1, 112b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .stream_fd = -1, 113b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .transport = BT_CAPABILITIES_TRANSPORT_A2DP, 114b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .rate = 48000, 115b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .channels = 2, 116b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau .address = NULL 117b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau}; 118b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 119b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int start_stream(struct userdata *u); 120b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int stop_stream(struct userdata *u); 121563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureaustatic gboolean input_cb(GIOChannel *gin, GIOCondition condition, gpointer data); 122b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 123b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic GMainLoop *main_loop; 124b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 125b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic int service_send(struct userdata *u, const bt_audio_msg_header_t *msg) 126b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 127b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int err; 128b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint16_t length; 129b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 130b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 131b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 132b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau length = msg->length ? msg->length : BT_SUGGESTED_BUFFER_SIZE; 133b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 134b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("sending %s:%s", bt_audio_strtype(msg->type), 135b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_strname(msg->name)); 136b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 137b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (send(u->service_fd, msg, length, 0) > 0) 138b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau err = 0; 139b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else { 140b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau err = -errno; 141b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Error sending data to audio service: %s(%d)", 142b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau strerror(errno), errno); 143b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 144b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 145b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return err; 146b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 147b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 148e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentzstatic int service_recv(struct userdata *u, bt_audio_msg_header_t *rsp) 149b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 150b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int err; 151b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau const char *type, *name; 152b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint16_t length; 153b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 154b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 155b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 156e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz length = rsp->length ? : BT_SUGGESTED_BUFFER_SIZE; 157b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 158b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("trying to receive msg from audio service..."); 159b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (recv(u->service_fd, rsp, length, 0) > 0) { 160b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau type = bt_audio_strtype(rsp->type); 161b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau name = bt_audio_strname(rsp->name); 162b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (type && name) { 163b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Received %s - %s", type, name); 164b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau err = 0; 165b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 166b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau err = -EINVAL; 167b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Bogus message type %d - name %d" 168b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau "received from audio service", 169b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau rsp->type, rsp->name); 170b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 171b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 172b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau err = -errno; 173b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Error receiving data from audio service: %s(%d)", 174b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau strerror(errno), errno); 175b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 176b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 177b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return err; 178b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 179b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 180e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentzstatic ssize_t service_expect(struct userdata *u, bt_audio_msg_header_t *rsp, 181e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz uint8_t expected_name) 182b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 183b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int r; 184b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 185b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 186b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u->service_fd >= 0); 187b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(rsp); 188b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 189e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if ((r = service_recv(u, rsp)) < 0) 190b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return r; 191b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 192b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if ((rsp->type != BT_INDICATION && rsp->type != BT_RESPONSE) || 193e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz (rsp->name != expected_name)) { 194b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (rsp->type == BT_ERROR && rsp->length == sizeof(bt_audio_error_t)) 195b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Received error condition: %s", 196b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau strerror(((bt_audio_error_t*) rsp)->posix_errno)); 197b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else 198b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Bogus message %s received while %s was expected", 199b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_strname(rsp->name), 200b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_strname(expected_name)); 201b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 202b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 203b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 204b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 205b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 206b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 207b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int init_bt(struct userdata *u) 208b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 209b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 210b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 211b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->service_fd != -1) 212b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 213b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 214b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("bt_audio_service_open"); 215b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 216b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->service_fd = bt_audio_service_open(); 217b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->service_fd <= 0) { 218b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau perror(strerror(errno)); 219b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return errno; 220b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 221b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 222b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 223b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 224b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 225b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int parse_caps(struct userdata *u, const struct bt_get_capabilities_rsp *rsp) 226b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 227fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann unsigned char *ptr; 228b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint16_t bytes_left; 229fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann codec_capabilities_t codec; 230b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 231b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 232b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(rsp); 233b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 234b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bytes_left = rsp->h.length - sizeof(*rsp); 235b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 236b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (bytes_left < sizeof(codec_capabilities_t)) { 237b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Packet too small to store codec information."); 238b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 239b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 240b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 241fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann ptr = ((void *) rsp) + sizeof(*rsp); 242fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann 243fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann memcpy(&codec, ptr, sizeof(codec)); /** ALIGNMENT? **/ 244b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 245b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Payload size is %lu %lu", 246fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann (unsigned long) bytes_left, (unsigned long) sizeof(codec)); 247b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 248fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann if (u->transport != codec.transport) { 249b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau ERR("Got capabilities for wrong codec."); 250b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 251b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 252b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 253b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->transport == BT_CAPABILITIES_TRANSPORT_SCO) { 254b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 255b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (bytes_left <= 0 || 256fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann codec.length != sizeof(u->hsp.pcm_capabilities)) 257b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 258b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 259fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann assert(codec.type == BT_HFP_CODEC_PCM); 260b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 261b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau memcpy(&u->hsp.pcm_capabilities, 262fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann &codec, sizeof(u->hsp.pcm_capabilities)); 263b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 264b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Has NREC: %s", 265b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau YES_NO(u->hsp.pcm_capabilities.flags & BT_PCM_FLAG_NREC)); 266b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 267b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 268b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 269b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau while (bytes_left > 0) { 270fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann if (codec.type == BT_A2DP_SBC_SINK && 271fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann !(codec.lock & BT_WRITE_LOCK)) 272b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 273b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 274fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann bytes_left -= codec.length; 275fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann ptr += codec.length; 276fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann memcpy(&codec, ptr, sizeof(codec)); 277b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 278b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 279fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann DBG("bytes_left = %d, codec.length = %d", 280fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann bytes_left, codec.length); 281e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 282b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (bytes_left <= 0 || 283fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann codec.length != sizeof(u->a2dp.sbc_capabilities)) 284b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 285b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 286fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann assert(codec.type == BT_A2DP_SBC_SINK); 287b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 288fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann memcpy(&u->a2dp.sbc_capabilities, &codec, 289fec239062b9126f2092c4d77233ab987ac3b0336Marcel Holtmann sizeof(u->a2dp.sbc_capabilities)); 290b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 291b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 292b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 293b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 294b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 295b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 296b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 297b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic int get_caps(struct userdata *u) 298b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 299b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau union { 300b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct bt_get_capabilities_req getcaps_req; 301b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct bt_get_capabilities_rsp getcaps_rsp; 302b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_error_t error; 303b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint8_t buf[BT_SUGGESTED_BUFFER_SIZE]; 304b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } msg; 305b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 306b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 307b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 308b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau memset(&msg, 0, sizeof(msg)); 309b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.getcaps_req.h.type = BT_REQUEST; 310b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.getcaps_req.h.name = BT_GET_CAPABILITIES; 311b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.getcaps_req.h.length = sizeof(msg.getcaps_req); 312b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 313e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz strncpy(msg.getcaps_req.destination, u->address, 314e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz sizeof(msg.getcaps_req.destination)); 315b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.getcaps_req.transport = u->transport; 316b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.getcaps_req.flags = BT_FLAG_AUTOCONNECT; 317b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 318b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (service_send(u, &msg.getcaps_req.h) < 0) 319b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 320b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 321e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.getcaps_rsp.h.length = 0; 322e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.getcaps_rsp.h, BT_GET_CAPABILITIES) < 0) 323b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 324b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 325b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return parse_caps(u, &msg.getcaps_rsp); 326b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 327b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 328b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic uint8_t a2dp_default_bitpool(uint8_t freq, uint8_t mode) 329b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 330b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (freq) { 331b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_16000: 332b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_32000: 333b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 53; 334b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 335b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_44100: 336b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 337b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (mode) { 338b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_MONO: 339b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 340b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 31; 341b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 342b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_STEREO: 343b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 344b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 53; 345b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 346b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 347b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Invalid channel mode %u", mode); 348b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 53; 349b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 350b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 351b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_48000: 352b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 353b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (mode) { 354b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_MONO: 355b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 356b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 29; 357b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 358b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_STEREO: 359b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 360b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 51; 361b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 362b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 363b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Invalid channel mode %u", mode); 364b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 51; 365b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 366b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 367b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 368b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Invalid sampling freq %u", freq); 369b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 53; 370b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 371b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 372b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 373b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int setup_a2dp(struct userdata *u) 374b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 375b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_capabilities_t *cap; 376b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int i; 377b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 378b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau static const struct { 379b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint32_t rate; 380b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint8_t cap; 381b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } freq_table[] = { 382b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau { 16000U, BT_SBC_SAMPLING_FREQ_16000 }, 383b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau { 32000U, BT_SBC_SAMPLING_FREQ_32000 }, 384b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau { 44100U, BT_SBC_SAMPLING_FREQ_44100 }, 385b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau { 48000U, BT_SBC_SAMPLING_FREQ_48000 } 386b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau }; 387b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 388b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 389b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u->transport == BT_CAPABILITIES_TRANSPORT_A2DP); 390b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 391b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap = &u->a2dp.sbc_capabilities; 392b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 393b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau /* Find the lowest freq that is at least as high as the requested 394b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau * sampling rate */ 395b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau for (i = 0; (unsigned) i < ARRAY_SIZE(freq_table); i++) 396b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (freq_table[i].rate >= u->rate && 397b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau (cap->frequency & freq_table[i].cap)) { 398b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->rate = freq_table[i].rate; 399b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->frequency = freq_table[i].cap; 400b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 401b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 402b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 403b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if ((unsigned) i >= ARRAY_SIZE(freq_table)) { 404b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau for (; i >= 0; i--) { 405b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->frequency & freq_table[i].cap) { 406b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->rate = freq_table[i].rate; 407b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->frequency = freq_table[i].cap; 408b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 409b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 410b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 411b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 412b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (i < 0) { 413b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Not suitable sample rate"); 414b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 415b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 416b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 417b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 418b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->channels <= 1) { 419b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) { 420b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 421b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->channels = 1; 422b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else 423b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->channels = 2; 424b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 425b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 426b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->channels >= 2) { 427b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->channels = 2; 428b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 429b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_JOINT_STEREO) 430b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->channel_mode = BT_A2DP_CHANNEL_MODE_JOINT_STEREO; 431b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_STEREO) 432b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->channel_mode = BT_A2DP_CHANNEL_MODE_STEREO; 433b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL) 434b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->channel_mode = BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL; 435b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->channel_mode & BT_A2DP_CHANNEL_MODE_MONO) { 436b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->channel_mode = BT_A2DP_CHANNEL_MODE_MONO; 437b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->channels = 1; 438b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 439b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("No supported channel modes"); 440b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 441b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 442b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 443b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 444b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->block_length & BT_A2DP_BLOCK_LENGTH_16) 445b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->block_length = BT_A2DP_BLOCK_LENGTH_16; 446b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_12) 447b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->block_length = BT_A2DP_BLOCK_LENGTH_12; 448b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_8) 449b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->block_length = BT_A2DP_BLOCK_LENGTH_8; 450b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->block_length & BT_A2DP_BLOCK_LENGTH_4) 451b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->block_length = BT_A2DP_BLOCK_LENGTH_4; 452b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else { 453b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("No supported block lengths"); 454b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 455b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 456b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 457b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->subbands & BT_A2DP_SUBBANDS_8) 458b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->subbands = BT_A2DP_SUBBANDS_8; 459b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->subbands & BT_A2DP_SUBBANDS_4) 460b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->subbands = BT_A2DP_SUBBANDS_4; 461b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else { 462b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("No supported subbands"); 463b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 464b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 465b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 466b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (cap->allocation_method & BT_A2DP_ALLOCATION_LOUDNESS) 467b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->allocation_method = BT_A2DP_ALLOCATION_LOUDNESS; 468b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else if (cap->allocation_method & BT_A2DP_ALLOCATION_SNR) 469b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->allocation_method = BT_A2DP_ALLOCATION_SNR; 470b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 471b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau cap->min_bitpool = (uint8_t) MAX(MIN_BITPOOL, cap->min_bitpool); 472b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau cap->max_bitpool = (uint8_t) MIN( 473b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau a2dp_default_bitpool(cap->frequency, cap->channel_mode), 474b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau cap->max_bitpool); 475b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 476b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 477b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 478b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 479b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic void setup_sbc(struct a2dp_info *a2dp) 480b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 481b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_capabilities_t *active_capabilities; 482b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 483b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(a2dp); 484b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 485b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau active_capabilities = &a2dp->sbc_capabilities; 486b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 487b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (a2dp->sbc_initialized) 488b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_reinit(&a2dp->sbc, 0); 489b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau else 490b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sbc_init(&a2dp->sbc, 0); 491b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc_initialized = TRUE; 492b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 493b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (active_capabilities->frequency) { 494b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_16000: 495b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.frequency = SBC_FREQ_16000; 496b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 497b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_32000: 498b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.frequency = SBC_FREQ_32000; 499b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 500b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_44100: 501b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.frequency = SBC_FREQ_44100; 502b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 503b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_SBC_SAMPLING_FREQ_48000: 504b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.frequency = SBC_FREQ_48000; 505b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 506b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 507b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 508b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 509b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 510b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (active_capabilities->channel_mode) { 511b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_MONO: 512b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.mode = SBC_MODE_MONO; 513b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 514b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_DUAL_CHANNEL: 515b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.mode = SBC_MODE_DUAL_CHANNEL; 516b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 517b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_STEREO: 518b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.mode = SBC_MODE_STEREO; 519b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 520b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_CHANNEL_MODE_JOINT_STEREO: 521b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.mode = SBC_MODE_JOINT_STEREO; 522b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 523b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 524b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 525b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 526b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 527b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (active_capabilities->allocation_method) { 528b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_ALLOCATION_SNR: 529b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.allocation = SBC_AM_SNR; 530b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 531b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_ALLOCATION_LOUDNESS: 532b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.allocation = SBC_AM_LOUDNESS; 533b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 534b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 535b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 536b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 537b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 538b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (active_capabilities->subbands) { 539b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_SUBBANDS_4: 540b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.subbands = SBC_SB_4; 541b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 542b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_SUBBANDS_8: 543b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.subbands = SBC_SB_8; 544b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 545b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 546b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 547b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 548b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 549b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau switch (active_capabilities->block_length) { 550b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_BLOCK_LENGTH_4: 551b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.blocks = SBC_BLK_4; 552b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 553b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_BLOCK_LENGTH_8: 554b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.blocks = SBC_BLK_8; 555b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 556b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_BLOCK_LENGTH_12: 557b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.blocks = SBC_BLK_12; 558b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 559b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau case BT_A2DP_BLOCK_LENGTH_16: 560b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.blocks = SBC_BLK_16; 561b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau break; 562b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau default: 563b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(0); 564b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 565b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 566b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->sbc.bitpool = active_capabilities->max_bitpool; 567b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau a2dp->codesize = (uint16_t) sbc_get_codesize(&a2dp->sbc); 568b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 569b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 570e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentzstatic int bt_open(struct userdata *u) 571e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz{ 572e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz union { 573e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz struct bt_open_req open_req; 574e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz struct bt_open_rsp open_rsp; 575e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz bt_audio_error_t error; 576e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz uint8_t buf[BT_SUGGESTED_BUFFER_SIZE]; 577e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz } msg; 578e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 579e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz memset(&msg, 0, sizeof(msg)); 580e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_req.h.type = BT_REQUEST; 581e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_req.h.name = BT_OPEN; 582e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_req.h.length = sizeof(msg.open_req); 583e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 584e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz strncpy(msg.open_req.destination, u->address, 585e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz sizeof(msg.open_req.destination)); 586e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_req.seid = u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ? 587e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz u->a2dp.sbc_capabilities.capability.seid : 588e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz BT_A2DP_SEID_RANGE + 1; 589e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_req.lock = u->transport == BT_CAPABILITIES_TRANSPORT_A2DP ? 590e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz BT_WRITE_LOCK : BT_READ_LOCK | BT_WRITE_LOCK; 591e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 592e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_send(u, &msg.open_req.h) < 0) 593e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz return -1; 594e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 595e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.open_rsp.h.length = sizeof(msg.open_rsp); 596e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.open_rsp.h, BT_OPEN) < 0) 597e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz return -1; 598e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 599e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz return 0; 600e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz} 601e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 602b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic int set_conf(struct userdata *u) 603b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 604b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau union { 605b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct bt_set_configuration_req setconf_req; 606b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct bt_set_configuration_rsp setconf_rsp; 607b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_error_t error; 608b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau uint8_t buf[BT_SUGGESTED_BUFFER_SIZE]; 609b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } msg; 610b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 611b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 612b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (setup_a2dp(u) < 0) 613b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 614b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 615b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 616b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau memset(&msg, 0, sizeof(msg)); 617b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.setconf_req.h.type = BT_REQUEST; 618b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.setconf_req.h.name = BT_SET_CONFIGURATION; 619b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.setconf_req.h.length = sizeof(msg.setconf_req); 620b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 621b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 622b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau memcpy(&msg.setconf_req.codec, &u->a2dp.sbc_capabilities, 623b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sizeof(u->a2dp.sbc_capabilities)); 624b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau msg.setconf_req.h.length += msg.setconf_req.codec.length - 625b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau sizeof(msg.setconf_req.codec); 626e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz } else { 627e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.setconf_req.codec.transport = BT_CAPABILITIES_TRANSPORT_SCO; 628e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.setconf_req.codec.seid = BT_A2DP_SEID_RANGE + 1; 629e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.setconf_req.codec.length = sizeof(pcm_capabilities_t); 630b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 631b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 632b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (service_send(u, &msg.setconf_req.h) < 0) 633b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 634b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 635e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.setconf_rsp.h.length = sizeof(msg.setconf_rsp); 636e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.setconf_rsp.h, BT_SET_CONFIGURATION) < 0) 637b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 638b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 639b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->link_mtu = msg.setconf_rsp.link_mtu; 640b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 641b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau /* setup SBC encoder now we agree on parameters */ 642b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->transport == BT_CAPABILITIES_TRANSPORT_A2DP) { 643b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau setup_sbc(&u->a2dp); 644b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->block_size = u->a2dp.codesize; 645b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("SBC parameters:\n\tallocation=%u\n" 646b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau "\tsubbands=%u\n\tblocks=%u\n\tbitpool=%u\n", 647b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->a2dp.sbc.allocation, u->a2dp.sbc.subbands, 648b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->a2dp.sbc.blocks, u->a2dp.sbc.bitpool); 649b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else 650b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->block_size = u->link_mtu; 651b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 652b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 653b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 654b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 655b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic int setup_bt(struct userdata *u) 656b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 657b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 658b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 659b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (get_caps(u) < 0) 660b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 661b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 662b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Got device caps"); 663b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 664e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (bt_open(u) < 0) 665e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz return -1; 666e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 667b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (set_conf(u) < 0) 668b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return -1; 669b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 670b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 671b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 672b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 673b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic int init_profile(struct userdata *u) 674b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 675b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 676b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 677b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return setup_bt(u); 678b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 679b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 680b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic void shutdown_bt(struct userdata *u) 681b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 682b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u); 683b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 684b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->stream_fd != -1) { 685482feece91818127ce4e6f39dfa555390a31d8abMarc-André Lureau stop_stream(u); 686b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("close(stream_fd)"); 687b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau close(u->stream_fd); 688b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->stream_fd = -1; 689b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 690b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 691b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (u->service_fd != -1) { 692b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("bt_audio_service_close"); 693b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau bt_audio_service_close(u->service_fd); 694b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->service_fd = -1; 695b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 696b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 697b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 698b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic void make_fd_nonblock(int fd) 699b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 700b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau int v; 701b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 702b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(fd >= 0); 703b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert((v = fcntl(fd, F_GETFL)) >= 0); 704b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 705b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (!(v & O_NONBLOCK)) 706b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(fcntl(fd, F_SETFL, v|O_NONBLOCK) >= 0); 707b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 708b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 709b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic void make_socket_low_delay(int fd) 710b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 711b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau/* FIXME: is this widely supported? */ 712b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#ifdef SO_PRIORITY 713b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau int priority; 714b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(fd >= 0); 715b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 716b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau priority = 6; 717b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (setsockopt(fd, SOL_SOCKET, SO_PRIORITY, (void*)&priority, 718b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau sizeof(priority)) < 0) 719b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ERR("SO_PRIORITY failed: %s", strerror(errno)); 720b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau#endif 721b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 722b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 723b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int read_stream(struct userdata *u) 724b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 725b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau int ret = 0; 726b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ssize_t l; 727b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau char *buf; 728b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 729b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u); 730b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u->stream_fd >= 0); 731b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 732b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau buf = alloca(u->link_mtu); 733b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 734b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau for (;;) { 735b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau l = read(u->stream_fd, buf, u->link_mtu); 736454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau if (u->debug_stream_read) 737454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau DBG("read from socket: %lli bytes", (long long) l); 738b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (l <= 0) { 739b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (l < 0 && errno == EINTR) 740b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau continue; 741b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau else { 742b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ERR("Failed to read date from stream_fd: %s", 743b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ret < 0 ? strerror(errno) : "EOF"); 7442addc4bdcd68bd26280751f1d1c2dd21d39b1488Luiz Augusto von Dentz return -1; 745b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 746b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } else { 747b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau break; 748b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 749b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 750b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 751b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return ret; 752b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 753b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 754b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau/* It's what PulseAudio is doing, not sure it's necessary for this 755b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau * test */ 756b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic ssize_t pa_write(int fd, const void *buf, size_t count) 757b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 758b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ssize_t r; 759b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 760b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0) 761b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return r; 762b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 763b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (errno != ENOTSOCK) 764b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return r; 765b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 766b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return write(fd, buf, count); 767b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 768b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 769b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int write_stream(struct userdata *u) 770b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 771b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau int ret = 0; 772b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ssize_t l; 773b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau char *buf; 774b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 775b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u); 776b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u->stream_fd >= 0); 777b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau buf = alloca(u->link_mtu); 778b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 779b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau for (;;) { 780b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau l = pa_write(u->stream_fd, buf, u->link_mtu); 781454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau if (u->debug_stream_write) 782454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau DBG("written to socket: %lli bytes", (long long) l); 783b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(l != 0); 784b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (l < 0) { 785b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (errno == EINTR) 786b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau continue; 787b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau else { 788b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ERR("Failed to write data: %s", strerror(errno)); 789b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau ret = -1; 790b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau break; 791b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 792b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } else { 793b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert((size_t)l <= u->link_mtu); 794b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau break; 795b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 796b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 797b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 798b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return ret; 799b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 800b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 801b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic gboolean stream_cb(GIOChannel *gin, GIOCondition condition, gpointer data) 802b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 803b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau struct userdata *u; 804b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 805b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u = data); 806b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 807b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (condition & G_IO_IN) { 808b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (read_stream(u) < 0) 809b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau goto fail; 810b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } else if (condition & G_IO_OUT) { 811b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (write_stream(u) < 0) 812b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau goto fail; 813b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } else { 814b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau DBG("Got %d", condition); 815b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_main_loop_quit(main_loop); 816b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return FALSE; 817b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 818b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 819b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return TRUE; 820b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 821b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaufail: 822b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau stop_stream(u); 823b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return FALSE; 824b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 825b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 826b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int start_stream(struct userdata *u) 827b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 828b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau union { 829b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau bt_audio_msg_header_t rsp; 830b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau struct bt_start_stream_req start_req; 831b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau struct bt_start_stream_rsp start_rsp; 832b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau struct bt_new_stream_ind streamfd_ind; 833b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau bt_audio_error_t error; 834b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau uint8_t buf[BT_SUGGESTED_BUFFER_SIZE]; 835b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } msg; 836b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 837b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u); 8389645bf143db975256d3618594282f4ce3778db42Marc-André Lureau 8399645bf143db975256d3618594282f4ce3778db42Marc-André Lureau if (u->stream_fd >= 0) 8409645bf143db975256d3618594282f4ce3778db42Marc-André Lureau return 0; 8419645bf143db975256d3618594282f4ce3778db42Marc-André Lureau if (u->stream_watch != 0) { 8429645bf143db975256d3618594282f4ce3778db42Marc-André Lureau g_source_remove(u->stream_watch); 8439645bf143db975256d3618594282f4ce3778db42Marc-André Lureau u->stream_watch = 0; 8449645bf143db975256d3618594282f4ce3778db42Marc-André Lureau } 8459645bf143db975256d3618594282f4ce3778db42Marc-André Lureau if (u->stream_channel != 0) { 8469645bf143db975256d3618594282f4ce3778db42Marc-André Lureau g_io_channel_unref(u->stream_channel); 8479645bf143db975256d3618594282f4ce3778db42Marc-André Lureau u->stream_channel = NULL; 8489645bf143db975256d3618594282f4ce3778db42Marc-André Lureau } 849b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 850b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE); 851b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau msg.start_req.h.type = BT_REQUEST; 852b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau msg.start_req.h.name = BT_START_STREAM; 853b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau msg.start_req.h.length = sizeof(msg.start_req); 854b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 855b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (service_send(u, &msg.start_req.h) < 0) 856b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return -1; 857b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 858e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.rsp.length = sizeof(msg.start_rsp); 859e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.rsp, BT_START_STREAM) < 0) 860b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return -1; 861b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 862e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.rsp.length = sizeof(msg.streamfd_ind); 863e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.rsp, BT_NEW_STREAM) < 0) 864b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return -1; 865b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 866b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if ((u->stream_fd = bt_audio_service_get_data_fd(u->service_fd)) < 0) { 867b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau DBG("Failed to get stream fd from audio service."); 868b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return -1; 869b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 870b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 871b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau make_fd_nonblock(u->stream_fd); 872b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau make_socket_low_delay(u->stream_fd); 873b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 874b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u->stream_channel = g_io_channel_unix_new(u->stream_fd)); 875b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 876b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau u->stream_watch = g_io_add_watch(u->stream_channel, 877b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau G_IO_IN|G_IO_OUT|G_IO_ERR|G_IO_HUP|G_IO_NVAL, 878b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau stream_cb, u); 879b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 880b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return 0; 881b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 882b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 883b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureaustatic int stop_stream(struct userdata *u) 884b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau{ 885b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau union { 886b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau bt_audio_msg_header_t rsp; 887e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz struct bt_stop_stream_req stop_req; 888e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz struct bt_stop_stream_rsp stop_rsp; 889b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau bt_audio_error_t error; 890b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau uint8_t buf[BT_SUGGESTED_BUFFER_SIZE]; 891b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } msg; 892b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau int r = 0; 893b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 894b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau if (u->stream_fd < 0) 895b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return 0; 896b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 897b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u); 898b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(u->stream_channel); 899b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 900b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_source_remove(u->stream_watch); 901482feece91818127ce4e6f39dfa555390a31d8abMarc-André Lureau u->stream_watch = 0; 902b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_io_channel_unref(u->stream_channel); 903b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau u->stream_channel = NULL; 904b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 905b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE); 906e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.stop_req.h.type = BT_REQUEST; 907e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.stop_req.h.name = BT_STOP_STREAM; 908e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.stop_req.h.length = sizeof(msg.stop_req); 909e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz 910e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_send(u, &msg.stop_req.h) < 0) { 911e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz r = -1; 912e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz goto done; 913e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz } 914b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 915e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz msg.rsp.length = sizeof(msg.stop_rsp); 916e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentz if (service_expect(u, &msg.rsp, BT_STOP_STREAM) < 0) 917b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau r = -1; 918b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 919e6522bd8c03008afa5ed3bf9c71c24702f064badLuiz Augusto von Dentzdone: 920b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau close(u->stream_fd); 921b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau u->stream_fd = -1; 922b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 923b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau return r; 924b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau} 925b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 926563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureaustatic gboolean sleep_cb(gpointer data) 927563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau{ 928563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau struct userdata *u; 929563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau 930563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau assert(u = data); 931563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau 932563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau u->gin_watch = g_io_add_watch(u->gin, 933563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, input_cb, data); 934563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau 935563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau printf(">>> "); 936563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau fflush(stdout); 937563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau 938563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau return FALSE; 939563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau} 940563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau 941b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic gboolean input_cb(GIOChannel *gin, GIOCondition condition, gpointer data) 942b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 943454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau char *line, *tmp; 944b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau gsize term_pos; 945b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau GError *error = NULL; 946b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau struct userdata *u; 947b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau int success; 948b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 949b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(u = data); 950b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (!(condition & G_IO_IN)) { 951b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("Got %d", condition); 952b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau g_main_loop_quit(main_loop); 953b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return FALSE; 954b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 955b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 956b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (g_io_channel_read_line(gin, &line, NULL, &term_pos, &error) != 957b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau G_IO_STATUS_NORMAL) 958b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return FALSE; 959b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 960b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau line[term_pos] = '\0'; 961b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau g_strstrip(line); 962454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau if ((tmp = strchr(line, '#'))) 963454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau *tmp = '\0'; 964b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau success = FALSE; 965b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 966b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau#define IF_CMD(cmd) \ 967b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (!success && (success = (strncmp(line, #cmd, strlen(#cmd)) == 0))) 968b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 969b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(quit) { 970b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau g_main_loop_quit(main_loop); 971b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return FALSE; 972b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 973b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 97464989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau IF_CMD(sleep) { 97564989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau unsigned int seconds; 97664989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau if (sscanf(line, "%*s %d", &seconds) != 1) 97764989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau DBG("sleep SECONDS"); 978563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau else { 979563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau g_source_remove(u->gin_watch); 980563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau g_timeout_add_seconds(seconds, sleep_cb, u); 981563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau return FALSE; 982563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau } 98364989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau } 98464989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau 985454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau IF_CMD(debug) { 986454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau char *what = NULL; 987454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau int enable; 988454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau 989454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau if (sscanf(line, "%*s %as %d", &what, &enable) != 1) 990454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau DBG("debug [stream_read|stream_write] [0|1]"); 991454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau if (strncmp(what, "stream_read", 12) == 0) { 992454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau u->debug_stream_read = enable; 993454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau } else if (strncmp(what, "stream_write", 13) == 0) { 994454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau u->debug_stream_write = enable; 995454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau } else { 996454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau DBG("debug [stream_read|stream_write] [0|1]"); 997454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau } 998454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau } 999454b5e87100311bdee18856f3aa6216dcedfe579Marc-André Lureau 1000b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(init_bt) { 1001b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("%d", init_bt(u)); 1002b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1003b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1004b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(init_profile) { 1005b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("%d", init_profile(u)); 1006b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1007b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1008b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau IF_CMD(start_stream) { 1009b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau DBG("%d", start_stream(u)); 1010b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 1011b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1012b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau IF_CMD(stop_stream) { 1013b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau DBG("%d", stop_stream(u)); 1014b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau } 1015b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1016b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(shutdown_bt) { 1017b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau shutdown_bt(u); 1018b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1019b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1020b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(rate) { 1021b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (sscanf(line, "%*s %d", &u->rate) != 1) 1022b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("set with rate RATE"); 1023b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("rate %d", u->rate); 1024b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1025b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1026c6e7e1139d85342799c47082355cd9b8b5dbe967Marcel Holtmann IF_CMD(bdaddr) { 1027204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz char *address; 1028204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz 1029204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz if (sscanf(line, "%*s %as", &address) != 1) 1030204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz DBG("set with bdaddr BDADDR"); 1031204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz 1032a554d3a656f0b0e3a3d82b68ab61b89f1b876660Gustavo F. Padovan free(u->address); 1033204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz 1034204c8e27e2bf736212afe312afeacea6df58a16fLuiz Augusto von Dentz u->address = address; 1035c6e7e1139d85342799c47082355cd9b8b5dbe967Marcel Holtmann DBG("bdaddr %s", u->address); 1036b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1037b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1038b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau IF_CMD(profile) { 103964989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau char *profile = NULL; 1040b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 104164989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau if (sscanf(line, "%*s %as", &profile) != 1) 1042b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("set with profile [hsp|a2dp]"); 1043b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (strncmp(profile, "hsp", 4) == 0) { 1044b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->transport = BT_CAPABILITIES_TRANSPORT_SCO; 1045b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else if (strncmp(profile, "a2dp", 5) == 0) { 1046b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau u->transport = BT_CAPABILITIES_TRANSPORT_A2DP; 1047b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 1048b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("set with profile [hsp|a2dp]"); 1049b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1050b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1051a554d3a656f0b0e3a3d82b68ab61b89f1b876660Gustavo F. Padovan free(profile); 1052b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("profile %s", u->transport == BT_CAPABILITIES_TRANSPORT_SCO ? 1053b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau "hsp" : "a2dp"); 1054b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1055b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1056b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (!success && strlen(line) != 0) { 1057b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau DBG("%s, unknown command", line); 1058b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1059b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1060b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau printf(">>> "); 1061b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau fflush(stdout); 1062b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return TRUE; 1063b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 1064b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1065b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1066b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic void show_usage(char* prgname) 1067b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 1068c6e7e1139d85342799c47082355cd9b8b5dbe967Marcel Holtmann printf("%s: ipctest [--interactive] BDADDR\n", basename(prgname)); 1069b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 1070b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1071b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureaustatic void sig_term(int sig) 1072b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 1073b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau g_main_loop_quit(main_loop); 1074b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 1075b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1076b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureauint main(int argc, char *argv[]) 1077b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau{ 1078b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (argc < 2) { 1079b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau show_usage(argv[0]); 1080b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau exit(EXIT_FAILURE); 1081b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1082b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1083b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(main_loop = g_main_loop_new(NULL, FALSE)); 1084b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1085b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (strncmp("--interactive", argv[1], 14) == 0) { 1086b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau if (argc < 3) { 1087b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau show_usage(argv[0]); 1088b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau exit(EXIT_FAILURE); 1089b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1090b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 109164989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau data.address = strdup(argv[2]); 1092b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1093b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau signal(SIGTERM, sig_term); 1094b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau signal(SIGINT, sig_term); 1095b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1096563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau assert(data.gin = g_io_channel_unix_new(fileno(stdin))); 1097b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1098563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau data.gin_watch = g_io_add_watch(data.gin, 1099563a7c646d0ab4daed4f0ad17afafd18e5222460Marc-André Lureau G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, input_cb, &data); 1100b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1101b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau printf(">>> "); 1102b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau fflush(stdout); 1103b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1104b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_main_loop_run(main_loop); 1105b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1106b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } else { 110764989ac07ca0085556df4df96caf14ec0e7b086cMarc-André Lureau data.address = strdup(argv[1]); 1108b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1109b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau assert(init_bt(&data) == 0); 1110b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1111b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(init_profile(&data) == 0); 1112b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1113b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(start_stream(&data) == 0); 1114b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1115b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_main_loop_run(main_loop); 1116b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1117b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau assert(stop_stream(&data) == 0); 1118b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1119b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau shutdown_bt(&data); 1120b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau } 1121b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1122b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau g_main_loop_unref(main_loop); 1123b4c0e4acab4b61b4fc97ec27d3c666c273afee19Marc-André Lureau 1124b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau printf("\nExiting\n"); 1125b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1126b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau exit(EXIT_SUCCESS); 1127b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau 1128b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau return 0; 1129b7cad7d51ac8dfc0458dbd42478ae9be237472f8Marc-André Lureau} 1130