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