Home | History | Annotate | Line # | Download | only in bta2dpd
      1 /* $NetBSD: bta2dpd.c,v 1.10 2026/07/30 22:39:02 andvar Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2015 - 2016 Nathanial Sloss <nathanialsloss (at) yahoo.com.au>
      5  * All rights reserved.
      6  *
      7  *		This software is dedicated to the memory of -
      8  *	   Baron James Anlezark (Barry) - 1 Jan 1949 - 13 May 2012.
      9  *
     10  *		Barry was a man who loved his music.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31  * POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 /*-
     35  * Copyright (c) 2006 Itronix Inc.
     36  * All rights reserved.
     37  *
     38  * Written by Iain Hibbert for Itronix Inc.
     39  *
     40  * Redistribution and use in source and binary forms, with or without
     41  * modification, are permitted provided that the following conditions
     42  * are met:
     43  * 1. Redistributions of source code must retain the above copyright
     44  *    notice, this list of conditions and the following disclaimer.
     45  * 2. Redistributions in binary form must reproduce the above copyright
     46  *    notice, this list of conditions and the following disclaimer in the
     47  *    documentation and/or other materials provided with the distribution.
     48  * 3. The name of Itronix Inc. may not be used to endorse
     49  *    or promote products derived from this software without specific
     50  *    prior written permission.
     51  *
     52  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
     53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     54  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     55  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
     56  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     57  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     58  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     59  * ON ANY THEORY OF LIABILITY, WHETHER IN
     60  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     61  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     62  * POSSIBILITY OF SUCH DAMAGE.
     63  */
     64 
     65 /* This was based upon bthset.c */
     66 
     67 #include <sys/cdefs.h>
     68 __COPYRIGHT("@(#) Copyright (c) 2006 Itronix, Inc.  All rights reserved.");
     69 __RCSID("$NetBSD: bta2dpd.c,v 1.10 2026/07/30 22:39:02 andvar Exp $");
     70 
     71 #include <sys/ioctl.h>
     72 #include <sys/types.h>
     73 #include <sys/time.h>
     74 
     75 #include <assert.h>
     76 #include <bluetooth.h>
     77 #include <err.h>
     78 #include <event.h>
     79 #include <fcntl.h>
     80 #include <sdp.h>
     81 #include <stdarg.h>
     82 #include <stdio.h>
     83 #include <stdlib.h>
     84 #include <string.h>
     85 #include <syslog.h>
     86 #include <unistd.h>
     87 #include <util.h>
     88 #include <errno.h>
     89 
     90 #include "avdtp_signal.h"
     91 #include "sbc_encode.h"
     92 
     93 #define A2DP_SINK	0x110b
     94 
     95 /* A2DP Audio Source service record */
     96 static uint8_t source_data[] = {
     97 	0x09, 0x00, 0x00,	//  uint16	ServiceRecordHandle
     98 	0x0a, 0x00, 0x00, 0x00,	//  uint32	0x00000000
     99 	0x00,
    100 
    101 	0x09, 0x00, 0x01,	//  uint16	ServiceClassIDList
    102 	0x35, 0x03,		//  seq8(3)
    103 	0x19, 0x11, 0x0a,	//   uuid16	AudioSource
    104 
    105 	0x09, 0x00, 0x04,	//  uint16	ProtocolDescriptorList
    106 	0x35, 0x10,		//  seq8(16)
    107 	0x35, 0x06,		//   seq8(6)
    108 	0x19, 0x01, 0x00,	//    uuid16	L2CAP
    109 	0x09, 0x00, 0x19,	//    uint16	%src_psm%
    110 	0x35, 0x06,		//   seq8(6)
    111 	0x19, 0x00, 0x19,	//    uuid16	AVDTP
    112 	0x09, 0x01, 0x00,	//    uint16	Ver 1.0
    113 
    114 	0x09, 0x00, 0x05,	//  uint16	BrowseGroupList
    115 	0x35, 0x03,		//  seq8(3)
    116 	0x19, 0x10, 0x02,	//   uuid16	PublicBrowseGroup
    117 
    118 	0x09, 0x00, 0x06,	//  uint16	LanguageBaseAttributeIDList
    119 	0x35, 0x09,		//  seq8(9)
    120 	0x09, 0x65, 0x6e,	//   uint16	0x656e	("en")
    121 	0x09, 0x00, 0x6a,	//   uint16	106	(UTF-8)
    122 	0x09, 0x01, 0x00,	//   uint16	PrimaryLanguageBaseID
    123 
    124 	0x09, 0x00, 0x09,	//  uint16	BluetoothProfileDescriptorList
    125 	0x35, 0x08,		//  seq8(8)
    126 	0x35, 0x06,		//   seq8(6)
    127 	0x19, 0x11, 0x0d,	//    uuid16	A2DP
    128 	0x09, 0x01, 0x02,	//    uint16	v1.2
    129 
    130 	0x09, 0x01, 0x00,	//  uint16	PrimaryLanguageBaseID +
    131 				//		    ServiceNameOffset
    132 	0x25, 0x09,		//  str8(9)	"Audio SRC"
    133 	'A', 'u', 'd', 'i', 'o', ' ', 'S', 'R', 'C',
    134 
    135 	0x09, 0x01, 0x02,	//  uint16	PrimaryLanguageBaseID +
    136 				//		    ProviderName
    137 	0x25, 0x06,		//  str8(6)	"NetBSD"
    138 	'N', 'e', 't', 'B', 'S', 'D',
    139 
    140 	0x09, 0x03, 0x11,	//  uint16	SupportedFeatures
    141 	0x09, 0x01, 0x02	//  uint16	Headphone, Speaker
    142 };
    143 
    144 static sdp_data_t source_record =  { source_data + 0, source_data + 103 };
    145 static sdp_data_t source_psm = { source_data + 26, source_data + 29 };
    146 
    147 
    148 /* A2DP Audio Sink service record */
    149 static uint8_t sink_data[] = {
    150 	0x09, 0x00, 0x00,	//  uint16	ServiceRecordHandle
    151 	0x0a, 0x00, 0x00, 0x00,	//  uint32	0x00000000
    152 	0x00,
    153 
    154 	0x09, 0x00, 0x01,	//  uint16	ServiceClassIDList
    155 	0x35, 0x03,		//  seq8(3)
    156 	0x19, 0x11, 0x0b,	//   uuid16	AudioSink
    157 
    158 	0x09, 0x00, 0x04,	//  uint16	ProtocolDescriptorList
    159 	0x35, 0x10,		//  seq8(16)
    160 	0x35, 0x06,		//   seq8(6)
    161 	0x19, 0x01, 0x00,	//    uuid16	L2CAP
    162 	0x09, 0x00, 0x19,	//    uint16	%sink_psm%
    163 	0x35, 0x06,		//   seq8(6)
    164 	0x19, 0x00, 0x19,	//    uuid16	AVDTP
    165 	0x09, 0x01, 0x00,	//    uint16	Ver 1.0
    166 
    167 	0x09, 0x00, 0x05,	//  uint16	BrowseGroupList
    168 	0x35, 0x03,		//  seq8(3)
    169 	0x19, 0x10, 0x02,	//   uuid16	PublicBrowseGroup
    170 
    171 	0x09, 0x00, 0x06,	//  uint16	LanguageBaseAttributeIDList
    172 	0x35, 0x09,		//  seq8(9)
    173 	0x09, 0x65, 0x6e,	//   uint16	0x656e	("en")
    174 	0x09, 0x00, 0x6a,	//   uint16	106	(UTF-8)
    175 	0x09, 0x01, 0x00,	//   uint16	PrimaryLanguageBaseID
    176 
    177 	0x09, 0x00, 0x09,	//  uint16	BluetoothProfileDescriptorList
    178 	0x35, 0x08,		//  seq8(8)
    179 	0x35, 0x06,		//   seq8(6)
    180 	0x19, 0x11, 0x0d,	//    uuid16	A2DP
    181 	0x09, 0x01, 0x02,	//    uint16	v1.2
    182 
    183 	0x09, 0x01, 0x00,	//  uint16	PrimaryLanguageBaseID +
    184 				//		    ServiceNameOffset
    185 	0x25, 0x09,		//  str8(9)	"Audio SNK"
    186 	'A', 'u', 'd', 'i', 'o', ' ', 'S', 'N', 'K',
    187 
    188 	0x09, 0x01, 0x02,	//  uint16	PrimaryLanguageBaseID +
    189 				//		    ProviderName
    190 	0x25, 0x06,		//  str8(6)	"NetBSD"
    191 	'N', 'e', 't', 'B', 'S', 'D',
    192 
    193 	0x09, 0x03, 0x11,	//  uint16	SupportedFeatures
    194 	0x09, 0x00, 0x03	//  uint16	Headphone, Speaker
    195 };
    196 
    197 static sdp_data_t sink_record =	{ sink_data + 0, sink_data + 103 };
    198 static sdp_data_t sink_psm = { sink_data + 26, sink_data + 29 };
    199 
    200 struct l2cap_info {
    201 	bdaddr_t laddr;
    202 	bdaddr_t raddr;
    203 };
    204 
    205 __dead static void usage(void);
    206 
    207 static int init_server(struct l2cap_info *);
    208 static int init_client(struct l2cap_info *);
    209 static void client_query(void);
    210 static void exit_func(void);
    211 
    212 static int sc;		/* avdtp streaming channel */
    213 static int orighc;	/* avdtp listening socket */
    214 static int hc;		/* avdtp control/command channel */
    215 struct event_base *base;
    216 static struct event interrupt_ev;		/* audio event */
    217 static struct event recv_ev;			/* audio sink event */
    218 static struct event ctl_ev;			/* avdtp ctl event */
    219 
    220 struct l2cap_info	info;
    221 static bool		runasDaemon;
    222 static bool		asSpeaker;
    223 static bool		dontStop;
    224 static bool		initDiscover;	/* initiate avdtp discover */
    225 static bool 		verbose;	/* copy to stdout */
    226 static bool 		test_mode;	/* copy to stdout */
    227 static uint8_t		channel_mode = MODE_STEREO;
    228 static uint8_t		alloc_method = ALLOC_LOUDNESS;
    229 static uint8_t		frequency = FREQ_44_1K;
    230 static int		freqnum = 44100;
    231 static uint8_t		freqs[4];
    232 static uint8_t		blocks_config[4];
    233 static uint8_t		channel_config[4];
    234 static uint8_t		bands_config[2];
    235 static uint8_t		alloc_config[2];
    236 static uint8_t		bitpool = 0;
    237 static uint8_t		bands = BANDS_8;
    238 static uint8_t		blocks = BLOCKS_16;
    239 static int		volume = 0;
    240 static int		state = 0;
    241 static uint16_t		l2cap_psm = 0;
    242 static int		l2cap_mode;
    243 uint16_t mtu;
    244 uint16_t userset_mtu = 1000, service_class = A2DP_SINK;
    245 static const char* service_type = "A2DP";
    246 struct avdtp_sepInfo mySepInfo;
    247 static sdp_session_t ss;	/* SDP server session */
    248 
    249 char *files2open[255];
    250 static int numfiles = 0;
    251 static int startFileInd = 0;
    252 int audfile;
    253 
    254 static void do_interrupt(int, short, void *);
    255 static void do_recv(int, short, void *);
    256 static void do_ctlreq(int, short, void *);
    257 static void bt_exit(int fd);
    258 
    259 #define log_err(st, fmt, args...)	\
    260 	do { syslog(LOG_ERR, fmt, ##args); exit(st); } while (0)
    261 #define log_warn(fmt, args...)	syslog(LOG_WARNING, fmt, ##args)
    262 #define log_info(fmt, args...)	syslog(LOG_INFO, fmt, ##args)
    263 #define log_debug(fmt, args...)	syslog(LOG_DEBUG, fmt, ##args)
    264 
    265 int
    266 main(int ac, char *av[])
    267 {
    268 	int enc, i, n, m, l, j, k, o, ch, blocksnum;
    269 	u_int tmpbitpool;
    270 	bdaddr_copy(&info.laddr, BDADDR_ANY);
    271 
    272 	sc = hc = -1;
    273 	verbose = asSpeaker = test_mode = initDiscover = runasDaemon = false;
    274 	dontStop = false;
    275 	n = m = l = i = j = o = 0;
    276 	freqs[0] = frequency;
    277 	channel_config[0] = channel_mode;
    278 	blocks_config[0] = blocks;
    279 	bands_config[0] = bands;
    280 	alloc_config[0] = alloc_method;
    281 	channel_config[0] = channel_mode;
    282 
    283 	while ((ch = getopt(ac, av, "A:a:B:b:Dd:e:f:IKnM:m:p:r:tV:v")) !=
    284 	    EOF) {
    285 		switch (ch) {
    286 		case 'A':
    287 			for (k = 0; k < (int)strlen(optarg); k++) {
    288 				if (o > 1)
    289 					break;
    290 				switch (optarg[k]) {
    291 				case '0':
    292 					alloc_config[o++] = ALLOC_ANY;
    293 					break;
    294 				case 'S':
    295 					alloc_config[o++] = ALLOC_SNR;
    296 					break;
    297 				case 'L':
    298 					alloc_config[o++] = ALLOC_LOUDNESS;
    299 					break;
    300 				default:
    301 					usage();
    302 				}
    303 			}
    304 			break;
    305 		case 'a':
    306 			if (!bt_aton(optarg, &info.raddr)) {
    307 				struct hostent  *he = NULL;
    308 
    309 				if ((he = bt_gethostbyname(optarg)) == NULL)
    310 					usage();
    311 
    312 				bdaddr_copy(&info.raddr,
    313 				    (bdaddr_t *)he->h_addr);
    314 			}
    315 			break;
    316 		case 'B': /* Max bitpool value */
    317 			bitpool = (uint8_t)atoi(optarg);
    318 			break;
    319 		case 'b':
    320 			if (m > 3)
    321 				break;
    322 			blocksnum = atoi(optarg);
    323 			switch (blocksnum) {
    324 			case 0:
    325 				blocks_config[m++] = BLOCKS_ANY;
    326 				break;
    327 			case 4:
    328 				blocks_config[m++] = BLOCKS_4;
    329 				break;
    330 			case 8:
    331 				blocks_config[m++] = BLOCKS_8;
    332 				break;
    333 			case 12:
    334 				blocks_config[m++] = BLOCKS_12;
    335 				break;
    336 			case 16:
    337 				blocks_config[m++] = BLOCKS_16;
    338 				break;
    339 			default:
    340 				usage();
    341 			}
    342 			break;
    343 		case 'D':
    344 			runasDaemon = true;
    345 			break;
    346 		case 'd': /* local device address */
    347 			if (!bt_devaddr(optarg, &info.laddr))
    348 				usage();
    349 			break;
    350 		case 'e':
    351 			if (l > 1)
    352 				break;
    353 			enc = atoi(optarg);
    354 			switch (enc) {
    355 			case 0:
    356 				bands_config[l++] = BANDS_ANY;
    357 				break;
    358 			case 4:
    359 				bands_config[l++] = BANDS_4;
    360 				break;
    361 			case 8:
    362 				bands_config[l++] = BANDS_8;
    363 				break;
    364 			default:
    365 				usage();
    366 			}
    367 			break;
    368 		case 'f':
    369 			for (k = 0; k < (int)strlen(optarg); k++) {
    370 				if (n > 3)
    371 					break;
    372 				switch (optarg[k]) {
    373 				case '0':
    374 					channel_config[n++] = MODE_ANY;
    375 					break;
    376 				case '2':
    377 					channel_config[n++] = MODE_DUAL;
    378 					break;
    379 				case 'j':
    380 					channel_config[n++] = MODE_JOINT;
    381 					break;
    382 				case 'm':
    383 					channel_config[n++] = MODE_MONO;
    384 					break;
    385 				case 's':
    386 					channel_config[n++] = MODE_STEREO;
    387 					break;
    388 				default:
    389 					usage();
    390 				}
    391 			}
    392 			break;
    393 		case 'I':
    394 			initDiscover = true;
    395 			break;
    396 		case 'K':
    397 			asSpeaker = true;
    398 			break;
    399 		case 'M':
    400 			userset_mtu = (uint16_t)atoi(optarg);
    401 			break;
    402 		case 'm': /* link mode */
    403 			if (strcasecmp(optarg, "auth") == 0)
    404 				l2cap_mode = L2CAP_LM_AUTH;
    405 			else if (strcasecmp(optarg, "encrypt") == 0)
    406 				l2cap_mode = L2CAP_LM_ENCRYPT;
    407 			else if (strcasecmp(optarg, "secure") == 0)
    408 				l2cap_mode = L2CAP_LM_SECURE;
    409 			else if (strcasecmp(optarg, "none"))
    410 				errx(EXIT_FAILURE, "%s: unknown mode", optarg);
    411 
    412 			break;
    413 		case 'n':
    414 			dontStop = true;
    415 			break;
    416 		case 'p':
    417 			l2cap_psm = (uint16_t)atoi(optarg);
    418 			break;
    419 		case 'r':
    420 			if (i > 3)
    421 				break;
    422 			freqnum = atoi(optarg);
    423 			switch (freqnum) {
    424 			case 0:
    425 				freqs[i++] = FREQ_ANY;
    426 				break;
    427 			case 16000:
    428 				freqs[i++] = FREQ_16K;
    429 				break;
    430 			case 32000:
    431 				freqs[i++] = FREQ_32K;
    432 				break;
    433 			case 44100:
    434 				freqs[i++] = FREQ_44_1K;
    435 				break;
    436 			case 48000:
    437 				freqs[i++] = FREQ_48K;
    438 				break;
    439 			default:
    440 				usage();
    441 			}
    442 			break;
    443 		case 't':
    444 			test_mode = true;
    445 			break;
    446 		case 'V': /* Volume Multiplier */
    447 			volume = atoi(optarg);
    448 			break;
    449 		case 'v':
    450 			verbose = true;
    451 			break;
    452 		default:
    453 			usage();
    454 		}
    455 	}
    456 	av += optind;
    457 	ac -= optind;
    458 
    459 	numfiles = ac;
    460 
    461 	for (i = 0; i < numfiles; i++)
    462 		files2open[i] = av[i];
    463 
    464 	if (runasDaemon && test_mode)
    465 		usage();
    466 
    467 	if (bdaddr_any(&info.raddr) && (!asSpeaker && !test_mode))
    468 		usage();
    469 
    470 	if (volume < 0 || volume > 2)
    471 		usage();
    472 
    473 	if (!asSpeaker && l2cap_psm)
    474 		usage();
    475 
    476 	if (asSpeaker) {
    477 		if (l == 0)
    478 			bands = BANDS_ANY;
    479 		if (m == 0)
    480 			blocks = BLOCKS_ANY;
    481 		if (n == 0)
    482 			channel_mode = MODE_ANY;
    483 		if (o == 0)
    484 			alloc_method = ALLOC_ANY;
    485 	}
    486 
    487 	if (i) {
    488 		frequency = 0;
    489 		for (j = 0; j < i; j++)
    490 			frequency |= freqs[j];
    491 	}
    492 	if (m) {
    493 		blocks = 0;
    494 		for (j = 0; j < m; j++)
    495 			blocks |= blocks_config[j];
    496 	}
    497 	if (l) {
    498 		bands = 0;
    499 		for (j = 0; j < l; j++)
    500 			bands |= bands_config[j];
    501 	}
    502 	if (n) {
    503 		channel_mode = 0;
    504 		for (j = 0; j < n; j++)
    505 			channel_mode |= channel_config[j];
    506 	}
    507 	if (o) {
    508 		alloc_method = 0;
    509 		for (j = 0; j < o; j++)
    510 			alloc_method |= alloc_config[j];
    511 	}
    512 
    513 	if (channel_mode == MODE_MONO || channel_mode == MODE_DUAL)
    514 		tmpbitpool = 16;
    515 	else
    516 		tmpbitpool = 32;
    517 
    518 	if (bands == BANDS_8)
    519 		tmpbitpool *= 8;
    520 	else
    521 		tmpbitpool *= 4;
    522 
    523 	if (tmpbitpool > DEFAULT_MAXBPOOL)
    524 		tmpbitpool = DEFAULT_MAXBPOOL;
    525 
    526 	if (bitpool == 0 || tmpbitpool < bitpool)
    527 		bitpool = (uint8_t)tmpbitpool;
    528 
    529 	if (runasDaemon) {
    530 		if (daemon(0, 0) == -1)
    531 			err(EXIT_FAILURE, "daemon");
    532 		pidfile(NULL);
    533 		openlog(getprogname(), LOG_NDELAY | LOG_PID, LOG_DAEMON);
    534 	} else {
    535 		openlog(getprogname(), LOG_NLOG | LOG_PERROR | LOG_PTRIM,
    536 		    LOG_USER);
    537 	}
    538 
    539 again:
    540 	base = event_init();
    541 
    542 	if (asSpeaker == 0) {
    543 		if (init_client(&info) < 0)
    544 			log_err(EXIT_FAILURE, "init client: %m");
    545 	} else {
    546 		if (init_server(&info) < 0)
    547 			log_err(EXIT_FAILURE, "init server: %m");
    548 	}
    549 
    550 	if (verbose) {
    551 		log_info("A2DP:");
    552 		log_info("\tladdr: %s", bt_ntoa(&info.laddr, NULL));
    553 		log_info("\traddr: %s", bt_ntoa(&info.raddr, NULL));
    554 	}
    555 
    556 	event_base_loop(base, 0);
    557 	event_base_free(base);
    558 
    559 	sdp_close(ss);
    560 
    561 	if (audfile != -1 && audfile != STDIN_FILENO && audfile !=
    562 	    STDOUT_FILENO) {
    563 		close(audfile);
    564 		audfile = -1;
    565 	}
    566 
    567 	if (runasDaemon)
    568 		goto again;
    569 
    570 	return EXIT_SUCCESS;
    571 }
    572 
    573 static void
    574 usage(void)
    575 {
    576 	fprintf(stderr,
    577 	    "usage:\t%s [-v] [-D] [-n] [-d device] [-m mode] [-r rate]\n"
    578 	    "\t\t[-M mtu] [-V volume] [-f mode] [-b blocks] [-e bands]\n"
    579 	    "\t\t[-A alloc] [-B bitpool] -a address files...\n"
    580 	    "\t%s [-v] [-D] [-d device] [-m mode] [-p psm] [-B bitpool]\n"
    581 	    "\t\t[-a address] [-M mtu] [-r rate] [-I] -K file\n"
    582 	    "\t%s -t [-v] [-K] [-r rate] [-M mtu] [-V volume] [-f mode]\n"
    583 	    "\t\t[-b blocks] [-e bands] [-A alloc] [-B bitpool] files...\n"
    584 	    "Where:\n"
    585 	    "\t-d device    Local device address\n"
    586 	    "\t-a address   Remote device address\n"
    587 	    "\tfiles...     Files to read from (Defaults to stdin/stdout)\n"
    588 	    "\t-v           Verbose output\n"
    589 	    "\t-D           Run in the background\n"
    590 	    "\t-M mtu       MTU for transmission\n"
    591 	    "\t-B bitpool   Maximum bitpool value for encoding\n"
    592 	    "\t-V volume    Volume multiplier 0,1,2.\n"
    593 	    "\t             WARNING Can be VERY loud\n"
    594 	    "\t-K           Register as audio sink - Listens for incoming\n"
    595 	    "\t             connections.\n"
    596 	    "\t-I           Initiate DISCOVER - Used with audio sink\n"
    597 	    "\t-m mode     L2CAP link mode\n"
    598 	    "\t-p psm       Listens for incoming connections on psm\n"
    599 	    "\t-t           TEST MODE encodes from file to stdout or -K\n"
    600 	    "\t             read from stdin and decode to file/stdout.\n"
    601 	    "\t             Test mode does not communicate with bluetooth\n"
    602 	    "\t             only performs SBC de/encoding.\n"
    603 	    "ENCODING OPTIONS:\n"
    604 	    "\t-f mode\n"
    605 	    "\t\t0  All input modes are accepted (only used with -K)\n"
    606 	    "\t\t2  Input is dual channel\n"
    607 	    "\t\tj  Input is in joint stereo\n"
    608 	    "\t\tm  Input is mono\n"
    609 	    "\t\ts  Input is stereo (this is the default)\n"
    610 	    "\t-r rate\n"
    611 	    "\t\t0      All combinations of frequencies are accepted\n"
    612 	    "\t\t16000  Encode with a rate of 16000Hz\n"
    613 	    "\t\t32000  Encode with a rate of 32000Hz\n"
    614 	    "\t\t44100  Encode with a rate of 44100Hz "
    615 	    "(this is the default)\n"
    616 	    "\t\t48000  Encode with a rate of 48000Hz\n"
    617 	    "\t-b blocks\n"
    618 	    "\t\t0   All combinations of blocks are accepted\n"
    619 	    "\t\t4   Encode with 4 blocks\n"
    620 	    "\t\t8   Encode with 8 blocks\n"
    621 	    "\t\t12  Encode with 12 blocks\n"
    622 	    "\t\t16  Encode with 16 blocks (this is the default)\n"
    623 	    "\t-A alloc\n"
    624 	    "\t\t0  All combinations of allocation methods are accepted\n"
    625 	    "\t\tS  Signal to Noise Ratio (SNR) bit allocation\n"
    626 	    "\t\tL  Loudness bit allocation (this is the default)\n"
    627 	    "\n"
    628 	    "\tWithout specifying any mode rate enoding and allocation\n"
    629 	    "\tthe channel the default is stereo, 16 blocks, 8 subbands,\n"
    630 	    "\tloudness bit allocation, 441000 Hz.\n"
    631 	    , getprogname(), getprogname(), getprogname());
    632 
    633 	exit(EXIT_FAILURE);
    634 }
    635 
    636 static void
    637 bt_exit(int fd)
    638 {
    639 	if (!runasDaemon) {
    640 			close(fd);
    641 			fd = -1;
    642 			exit(1);
    643 	}
    644 	/* Not reached */
    645 }
    646 
    647 static void
    648 do_ctlreq(int fd, short ev, void *arg)
    649 {
    650 	bool isCommand;
    651 	uint8_t sep, signal;
    652 	static struct sockaddr_bt addr;
    653 	size_t bufflen;
    654 	socklen_t len, mtusize;
    655 	static uint8_t trans;
    656 	uint8_t buff[1024];
    657 	static size_t offset = 0;
    658 	int result;
    659 
    660 	if(avdtpCheckResponse(fd, &isCommand, &trans, &signal, NULL, buff,
    661 	    &bufflen, &sep) == ENOMEM) {
    662 		event_del(&ctl_ev);
    663 		close(fd);
    664 
    665 		if (asSpeaker) {
    666 			close(orighc);
    667 			orighc = -1;
    668 			event_del(&recv_ev);
    669 		} else
    670 			event_del(&interrupt_ev);
    671 
    672 		if (sc != -1)
    673 			close(sc);
    674 		sc = hc = -1;
    675 		state = 0;
    676 
    677 		return;
    678 	} else if (isCommand) {
    679 		switch (signal) {
    680 		case AVDTP_ABORT:
    681 		case AVDTP_CLOSE:
    682 			avdtpSendAccept(fd, fd, trans, signal);
    683 			if (asSpeaker) {
    684 				event_del(&recv_ev);
    685 			} else
    686 				event_del(&interrupt_ev);
    687 
    688 			if (sc != -1)
    689 				close(sc);
    690 			sc = -1;
    691 			state = 0;
    692 			break;
    693 		case AVDTP_DISCOVER:
    694 			avdtpSendDiscResponseAudio(fd, fd, trans,
    695 			    (asSpeaker ? SNK_SEP : SRC_SEP), asSpeaker);
    696 			state = 1;
    697 			break;
    698 		case AVDTP_GET_CAPABILITIES:
    699 			avdtpSendCapabilitiesResponseSBC(fd, fd, trans,
    700 			    (asSpeaker ? SNK_SEP : SRC_SEP), bitpool,
    701 			    frequency , channel_mode, bands, blocks,
    702 			    alloc_method);
    703 			state = 2;
    704 			break;
    705 		case AVDTP_SET_CONFIGURATION:
    706 			avdtpSendAccept(fd, fd, trans, signal);
    707 			state = 3;
    708 			break;
    709 		case AVDTP_OPEN:
    710 			avdtpSendAccept(fd, fd, trans, signal);
    711 			if (state < 5)
    712 				state = 5;
    713 			break;
    714 		case AVDTP_SUSPEND:
    715 		case AVDTP_START:
    716 			avdtpSendAccept(fd, fd, trans, signal);
    717 			if (state < 6)
    718 				state = 6;
    719 			break;
    720 		default:
    721 			avdtpSendReject(fd, fd, trans, signal);
    722 		}
    723 		if (verbose)
    724 			log_debug("Received command %d", signal);
    725 	} else {
    726 		switch (signal) {
    727 		case AVDTP_DISCOVER:
    728 			if (offset >= bufflen)
    729 				offset = 0;
    730 			avdtpDiscover(buff + offset, bufflen - offset,
    731 			    &mySepInfo, !asSpeaker);
    732 			avdtpGetCapabilities(fd, fd, mySepInfo.sep);
    733 			break;
    734 		case AVDTP_GET_CAPABILITIES:
    735 			result = avdtpAutoConfigSBC(fd, fd, buff, bufflen,
    736 			    mySepInfo.sep, &frequency, &channel_mode,
    737 			    &alloc_method, &bitpool, &bands, &blocks,
    738 			    (asSpeaker ? SNK_SEP : SRC_SEP));
    739 
    740 			if (result == EINVAL) {
    741 				offset += 2;
    742 				avdtpSendCommand(hc, AVDTP_DISCOVER, 0,
    743 				    NULL, 0);
    744 			}
    745 
    746 			if (!result && verbose)
    747 				log_debug("Bitpool value = %d", bitpool);
    748 			state = 3;
    749 			break;
    750 		case AVDTP_SET_CONFIGURATION:
    751 			if (state == 3 && !asSpeaker)
    752 				avdtpOpen(fd, fd, mySepInfo.sep);
    753 			state = 4;
    754 			break;
    755 		case AVDTP_OPEN:
    756 			if (state == 4)
    757 				state = 5;
    758 			break;
    759 		case AVDTP_SUSPEND:
    760 		case AVDTP_START:
    761 			if (state < 6)
    762 				state = 6;
    763 			break;
    764 		default:
    765 			avdtpSendReject(fd, fd, trans, signal);
    766 		}
    767 		if (verbose)
    768 			log_debug("Responded to command %d", signal);
    769 	}
    770 
    771 
    772 	if (state < 5 || state > 7)
    773 		return;
    774 
    775 	if (asSpeaker && state == 6) {
    776 		len = sizeof(addr);
    777 		if ((sc = accept(orighc,(struct sockaddr*)&addr, &len)) < 0)
    778 			log_err(EXIT_FAILURE, "stream accept: %m");
    779 
    780 	}
    781 	if (state == 6)
    782 		goto opened_connection;
    783 
    784 	memset(&addr, 0, sizeof(addr));
    785 
    786 	addr.bt_len = sizeof(addr);
    787 	addr.bt_family = AF_BLUETOOTH;
    788 	bdaddr_copy(&addr.bt_bdaddr, &info.laddr);
    789 	addr.bt_psm = l2cap_psm;
    790 
    791 	sc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
    792 	if (sc < 0)
    793 		return;
    794 
    795 	if (bind(sc, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    796 		return;
    797 
    798 	if (setsockopt(sc, BTPROTO_L2CAP, SO_L2CAP_LM,
    799 	    &l2cap_mode, sizeof(l2cap_mode)) == -1) {
    800 		log_err(EXIT_FAILURE, "Could not set link mode (0x%4.4x)",
    801 		    l2cap_mode);
    802 	}
    803 
    804 	bdaddr_copy(&addr.bt_bdaddr, &info.raddr);
    805 	if (connect(sc,(struct sockaddr*)&addr, sizeof(addr)) < 0)
    806 		return;
    807 
    808 	if (!asSpeaker)
    809 		avdtpStart(fd, fd, mySepInfo.sep);
    810 
    811 	return;
    812 
    813 opened_connection:
    814 	if (asSpeaker) {
    815 		event_set(&recv_ev, sc, EV_READ | EV_PERSIST, do_recv, NULL);
    816 		if (event_add(&recv_ev, NULL) < 0)
    817 			log_err(EXIT_FAILURE, "recv_ev: %m");
    818 		state = 7;
    819 	} else {
    820 		event_set(&interrupt_ev, audfile, EV_READ | EV_PERSIST,
    821 		    do_interrupt, NULL);
    822 		if (event_add(&interrupt_ev, NULL) < 0)
    823 			log_err(EXIT_FAILURE, "interrupt_ev: %m");
    824 		state = 7;
    825 	}
    826 
    827 	mtusize = sizeof(uint16_t);
    828 	getsockopt(sc, BTPROTO_L2CAP, SO_L2CAP_OMTU, &mtu, &mtusize);
    829 	if (userset_mtu != 0 && userset_mtu > 100 && userset_mtu < mtu)
    830 		mtu = userset_mtu;
    831 	else if (userset_mtu == 0 && mtu >= 500)
    832 		mtu /= 2;
    833 }
    834 
    835 static void
    836 do_recv(int fd, short ev, void *arg)
    837 {
    838 	ssize_t len;
    839 
    840 	len = recvstream(fd, audfile);
    841 
    842 	if (verbose)
    843 		log_debug("Recving %zd bytes", len);
    844 
    845 	if (len < 0) {
    846 		event_del(&recv_ev);
    847 		bt_exit(fd);
    848 	}
    849 }
    850 
    851 
    852 static void
    853 do_interrupt(int fd, short ev, void *arg)
    854 {
    855 	static int currentFileInd = 0;
    856 	ssize_t len;
    857 
    858 	if (currentFileInd == 0)
    859 		currentFileInd = startFileInd;
    860 
    861 	len = stream(fd, sc, channel_mode, frequency, bands, blocks,
    862 	    alloc_method, bitpool, mtu, volume);
    863 
    864 
    865 next_file:
    866 	if (dontStop && len == -1)
    867 		usleep(1);
    868 	else if (len == -1 && currentFileInd >= numfiles -1) {
    869 		event_del(&interrupt_ev);
    870 		bt_exit(fd);
    871 	} else if (len == -1) {
    872 		close(fd);
    873 		currentFileInd++;
    874 		audfile = open(files2open[currentFileInd], O_RDONLY);
    875 		if (audfile < 0) {
    876 			log_warn("error opening file %s: %m",
    877 			    files2open[currentFileInd]);
    878 			goto next_file;
    879 		}
    880 
    881 		event_del(&interrupt_ev);
    882 		event_set(&interrupt_ev, audfile, EV_READ |
    883 		    EV_PERSIST, do_interrupt, NULL);
    884 		if (event_add(&interrupt_ev, NULL) < 0)
    885 			log_err(EXIT_FAILURE, "interrupt_ev: %m");
    886 	}
    887 
    888 	if (verbose)
    889 		log_debug("Streaming %zd bytes", len);
    890 }
    891 
    892 /*
    893  * Initialise as an audio sink
    894  */
    895 static int
    896 init_server(struct l2cap_info *myInfo)
    897 {
    898 	struct sockaddr_bt addr;
    899 	socklen_t len;
    900 	int flags = O_WRONLY | O_CREAT;
    901 	static bool first_time = true;
    902 
    903 	if (atexit(exit_func))
    904 		log_err(EXIT_FAILURE, "atexit failed to initialize: %m");
    905 
    906 	if (numfiles == 0)
    907 		audfile = STDOUT_FILENO;
    908 	else if (numfiles > 1)
    909 		usage();
    910 	else {
    911 		if (first_time)
    912 			flags |= O_TRUNC;
    913 		else
    914 			flags |= O_APPEND;
    915 
    916 		first_time = false;
    917 
    918 		audfile = open(files2open[0], flags, 0600);
    919 		if (audfile < 0) {
    920 			log_err(EXIT_FAILURE, "error opening file %s: %m",
    921 			    files2open[0]);
    922 		}
    923 	}
    924 	if (test_mode)
    925 	    goto just_decode;
    926 
    927 	if (l2cap_psm == 0)
    928 		l2cap_psm = L2CAP_PSM_AVDTP;
    929 
    930 	sdp_set_uint(&sink_psm, l2cap_psm);
    931 
    932 	ss = sdp_open_local(NULL);
    933 	if (ss == NULL)
    934 		return -1;
    935 
    936 	if (!sdp_record_insert(ss, &myInfo->laddr, NULL, &sink_record)) {
    937 		sdp_close(ss);
    938 		return -1;
    939 	}
    940 
    941 	orighc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
    942 	if (orighc < 0)
    943 		return -1;
    944 
    945 	memset(&addr, 0, sizeof(addr));
    946 	addr.bt_len = sizeof(addr);
    947 	addr.bt_family = AF_BLUETOOTH;
    948 	addr.bt_psm = l2cap_psm;
    949 	bdaddr_copy(&addr.bt_bdaddr, &myInfo->laddr);
    950 
    951 	if (bind(orighc, (struct sockaddr *)&addr, sizeof(addr)) < 0)
    952 		return -1;
    953 
    954 	if (setsockopt(orighc, BTPROTO_L2CAP, SO_L2CAP_LM,
    955 	    &l2cap_mode, sizeof(l2cap_mode)) == -1) {
    956 		log_err(EXIT_FAILURE, "Could not set link mode (0x%4.4x)",
    957 		    l2cap_mode);
    958 	}
    959 
    960 	bdaddr_copy(&addr.bt_bdaddr, &myInfo->raddr);
    961 	if (listen(orighc,0) < 0)
    962 		return -1;
    963 
    964 	len = sizeof(addr);
    965 	if ((hc = accept(orighc,(struct sockaddr*)&addr, &len)) < 0)
    966 		return -1;
    967 
    968 	if (initDiscover)
    969 		avdtpSendCommand(hc, AVDTP_DISCOVER, 0, NULL, 0);
    970 
    971 	event_set(&ctl_ev, hc, EV_READ | EV_PERSIST, do_ctlreq, NULL);
    972 	if (event_add(&ctl_ev, NULL) < 0)
    973 		log_err(EXIT_FAILURE, "ctl_ev: %m");
    974 
    975 just_decode:
    976 	if (test_mode) {
    977 		if (userset_mtu)
    978 			mtu = userset_mtu;
    979 		sc = STDIN_FILENO;
    980 
    981 		event_set(&recv_ev, sc, EV_READ | EV_PERSIST, do_recv, NULL);
    982 		if (event_add(&recv_ev, NULL) < 0)
    983 			log_err(EXIT_FAILURE, "recv_ev: %m");
    984 	}
    985 
    986 	return 0;
    987 }
    988 
    989 
    990 /*
    991  * Initialise as an audio source
    992  */
    993 static int
    994 init_client(struct l2cap_info *myInfo)
    995 {
    996 	struct sockaddr_bt addr;
    997 	int i;
    998 
    999 	if (atexit(exit_func))
   1000 		log_err(EXIT_FAILURE, "atexit failed to initialize: %m");
   1001 
   1002 	if (numfiles == 0)
   1003 		audfile = STDIN_FILENO;
   1004 	else {
   1005 		for (i = 0; i < numfiles; i++) {
   1006 			audfile = open(files2open[i], O_RDONLY);
   1007 			if (audfile < 0)
   1008 				log_warn("error opening file %s: %m",
   1009 				    files2open[i]);
   1010 			else
   1011 				break;
   1012 		}
   1013 		startFileInd = i;
   1014 		if (startFileInd > numfiles - 1)
   1015 			log_err(EXIT_FAILURE, "error opening file%s",
   1016 			    (numfiles > 1) ? "s":"");
   1017 	}
   1018 
   1019 	if (test_mode)
   1020 		goto just_encode;
   1021 
   1022 	if (l2cap_psm == 0)
   1023 		l2cap_psm = L2CAP_PSM_AVDTP;
   1024 
   1025 	sdp_set_uint(&source_psm, l2cap_psm);
   1026 
   1027 	ss = sdp_open_local(NULL);
   1028 	if (ss == NULL)
   1029 		return -1;
   1030 
   1031 	if (!sdp_record_insert(ss, &myInfo->laddr, NULL, &source_record)) {
   1032 		sdp_close(ss);
   1033 		return -1;
   1034 	}
   1035 
   1036 	client_query();
   1037 
   1038 	orighc = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);
   1039 	if (orighc < 0)
   1040 		return -1;
   1041 
   1042 	memset(&addr, 0, sizeof(addr));
   1043 	addr.bt_len = sizeof(addr);
   1044 	addr.bt_family = AF_BLUETOOTH;
   1045 	addr.bt_psm = l2cap_psm;
   1046 	bdaddr_copy(&addr.bt_bdaddr, &myInfo->laddr);
   1047 
   1048 	if (bind(orighc, (struct sockaddr *)&addr, sizeof(addr)) < 0)
   1049 		return -1;
   1050 
   1051 	if (setsockopt(orighc, BTPROTO_L2CAP, SO_L2CAP_LM,
   1052 	    &l2cap_mode, sizeof(l2cap_mode)) == -1) {
   1053 		log_err(EXIT_FAILURE, "Could not set link mode (0x%4.4x)",
   1054 		    l2cap_mode);
   1055 	}
   1056 
   1057 	bdaddr_copy(&addr.bt_bdaddr, &myInfo->raddr);
   1058 	if (connect(orighc,(struct sockaddr*)&addr, sizeof(addr)) < 0)
   1059 		return -1;
   1060 
   1061 	hc = orighc;
   1062 	avdtpSendCommand(hc, AVDTP_DISCOVER, 0, NULL, 0);
   1063 
   1064 	event_set(&ctl_ev, hc, EV_READ | EV_PERSIST, do_ctlreq, NULL);
   1065 	if (event_add(&ctl_ev, NULL) < 0)
   1066 		log_err(EXIT_FAILURE, "ctl_ev: %m");
   1067 
   1068 just_encode:
   1069 	if (test_mode) {
   1070 		if (userset_mtu)
   1071 			mtu = userset_mtu;
   1072 		sc = STDOUT_FILENO;
   1073 		event_set(&interrupt_ev, audfile, EV_READ | EV_PERSIST,
   1074 		    do_interrupt, NULL);
   1075 		if (event_add(&interrupt_ev, NULL) < 0)
   1076 			log_err(EXIT_FAILURE, "interrupt_ev: %m");
   1077 	}
   1078 
   1079 	return 0;
   1080 }
   1081 
   1082 static void
   1083 client_query(void)
   1084 {
   1085 	uint8_t buf[12];	/* enough for SSP and AIL both */
   1086 	sdp_session_t myss;
   1087 	sdp_data_t ssp, ail, rsp, rec, value, pdl, seq;
   1088 	uintmax_t psm, ver;
   1089 	uint16_t attr;
   1090 	bool rv;
   1091 
   1092 	myss = sdp_open(&info.laddr, &info.raddr);
   1093 	if (myss == NULL) {
   1094 		log_err(EXIT_FAILURE, "%s: Could not open sdp session",
   1095 		    service_type);
   1096 	}
   1097 
   1098 	log_info("Searching for %s service at %s",
   1099 	    service_type, bt_ntoa(&info.raddr, NULL));
   1100 
   1101 	seq.next = buf;
   1102 	seq.end = buf + sizeof(buf);
   1103 
   1104 	/*
   1105 	 * build ServiceSearchPattern (9 bytes)
   1106 	 *
   1107 	 *	uuid16	"service_class"
   1108 	 *	uuid16	L2CAP
   1109 	 *	uuid16	AVDTP
   1110 	 */
   1111 	ssp.next = seq.next;
   1112 	sdp_put_uuid16(&seq, service_class);
   1113 	sdp_put_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP);
   1114 	sdp_put_uuid16(&seq, SDP_UUID_PROTOCOL_AVDTP);
   1115 	ssp.end = seq.next;
   1116 
   1117 	/*
   1118 	 * build AttributeIDList (3 bytes)
   1119 	 *
   1120 	 *	uint16	ProtocolDescriptorList
   1121 	 */
   1122 	ail.next = seq.next;
   1123 	sdp_put_uint16(&seq, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
   1124 	ail.end = seq.next;
   1125 
   1126 	rv = sdp_service_search_attribute(myss, &ssp, &ail, &rsp);
   1127 	if (!rv) {
   1128 		log_err(EXIT_FAILURE, "%s: Required sdp record not found",
   1129 		    service_type);
   1130 	}
   1131 
   1132 	/*
   1133 	 * we expect the response to contain a list of records
   1134 	 * containing a ProtocolDescriptorList. Find the first
   1135 	 * one containing L2CAP and AVDTP >= 1.0, and extract
   1136 	 * the PSM.
   1137 	 */
   1138 	rv = false;
   1139 	while (!rv && sdp_get_seq(&rsp, &rec)) {
   1140 		if (!sdp_get_attr(&rec, &attr, &value)
   1141 		    || attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST)
   1142 			continue;
   1143 
   1144 		sdp_get_alt(&value, &value);	/* drop any alt header */
   1145 		while (!rv && sdp_get_seq(&value, &pdl)) {
   1146 			if (sdp_get_seq(&pdl, &seq) &&
   1147 			    sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_L2CAP) &&
   1148 			    sdp_get_uint(&seq, &psm) &&
   1149 			    sdp_get_seq(&pdl, &seq) &&
   1150 			    sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_AVDTP) &&
   1151 			    sdp_get_uint(&seq, &ver) && ver >= 0x0100)
   1152 				rv = true;
   1153 		}
   1154 	}
   1155 
   1156 	sdp_close(myss);
   1157 
   1158 	if (!rv) {
   1159 		log_err(EXIT_FAILURE, "%s query failed", service_type);
   1160 	}
   1161 
   1162 	l2cap_psm = (uint16_t)psm;
   1163 	log_info("Found PSM %u for service %s", l2cap_psm, service_type);
   1164 }
   1165 
   1166 static void
   1167 exit_func(void)
   1168 {
   1169 	avdtpAbort(hc, hc, mySepInfo.sep);
   1170 	avdtpClose(hc, hc, mySepInfo.sep);
   1171 	close(sc);
   1172 	close(hc);
   1173 	sc = hc = -1;
   1174 }
   1175 
   1176