Home | History | Annotate | Download | only in audio
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2006-2007  Nokia Corporation
      6  *  Copyright (C) 2004-2009  Marcel Holtmann <marcel (at) holtmann.org>
      7  *  Copyright (C) 2008-2009  Leonid Movshovich <event.riga (at) gmail.org>
      8  *
      9  *
     10  *  This program is free software; you can redistribute it and/or modify
     11  *  it under the terms of the GNU General Public License as published by
     12  *  the Free Software Foundation; either version 2 of the License, or
     13  *  (at your option) any later version.
     14  *
     15  *  This program is distributed in the hope that it will be useful,
     16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18  *  GNU General Public License for more details.
     19  *
     20  *  You should have received a copy of the GNU General Public License
     21  *  along with this program; if not, write to the Free Software
     22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     23  *
     24  */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 #include <config.h>
     28 #endif
     29 
     30 #include <stdint.h>
     31 #include <stdlib.h>
     32 #include <string.h>
     33 #include <fcntl.h>
     34 #include <errno.h>
     35 
     36 #include <glib.h>
     37 #include <dbus/dbus.h>
     38 #include <gdbus.h>
     39 
     40 #include <bluetooth/bluetooth.h>
     41 #include <bluetooth/hci.h>
     42 #include <bluetooth/hci_lib.h>
     43 #include <bluetooth/sco.h>
     44 #include <bluetooth/sdp.h>
     45 #include <bluetooth/sdp_lib.h>
     46 
     47 #include "glib-helper.h"
     48 #include "device.h"
     49 #include "gateway.h"
     50 #include "logging.h"
     51 #include "error.h"
     52 #include "btio.h"
     53 #include "dbus-common.h"
     54 
     55 #define RFCOMM_BUF_SIZE 256
     56 /* not-more-then-16 defined by GSM + 1 for NULL + padding */
     57 #define AG_INDICATOR_DESCR_SIZE 20
     58 #define AG_CALLER_NUM_SIZE 64	/* size of number + type */
     59 
     60 /* commands */
     61 #define AG_FEATURES "AT+BRSF=26\r"     /* = 0x7F = All features supported */
     62 #define AG_INDICATORS_SUPP "AT+CIND=?\r"
     63 #define AG_INDICATORS_VAL "AT+CIND?\r"
     64 #define AG_INDICATORS_ENABLE "AT+CMER=3,0,0,1\r"
     65 #define AG_HOLD_MPTY_SUPP "AT+CHLD=?\r"
     66 #define AG_CALLER_IDENT_ENABLE "AT+CLIP=1\r"
     67 #define AG_CARRIER_FORMAT "AT+COPS=3,0\r"
     68 #define AG_EXTENDED_RESULT_CODE "AT+CMEE=1\r"
     69 
     70 #define AG_FEATURE_3WAY 0x1
     71 #define AG_FEATURE_EXTENDED_RES_CODE 0x100
     72 /* Hold and multipary AG features.
     73  * Comments below are copied from hands-free spec for reference */
     74 /* Releases all held calls or sets User Determined User Busy (UDUB)
     75  * for a waiting call */
     76 #define AG_CHLD_0 0x01
     77 /* Releases all active calls (if any exist) and accepts the other
     78  * (held or waiting) call */
     79 #define AG_CHLD_1 0x02
     80 /* Releases specified active call only <x> */
     81 #define AG_CHLD_1x 0x04
     82 /* Places all active calls (if any exist) on hold and accepts the other
     83  * (held or waiting) call */
     84 #define AG_CHLD_2 0x08
     85 /* Request private consultation mode with specified call <x> (Place all
     86  * calls on hold EXCEPT the call <x>) */
     87 #define AG_CHLD_2x 0x10
     88 /* Adds a held call to the conversation */
     89 #define AG_CHLD_3 0x20
     90 /* Connects the two calls and disconnects the subscriber from both calls
     91  * (Explicit Call Transfer). Support for this value and its associated
     92  * functionality is optional for the HF. */
     93 #define AG_CHLD_4 0x40
     94 
     95 #define OK_RESPONSE "\r\nOK\r\n"
     96 #define ERROR_RESPONSE "\r\nERROR\r\n"
     97 
     98 struct indicator {
     99 	gchar descr[AG_INDICATOR_DESCR_SIZE];
    100 	gint value;
    101 };
    102 
    103 struct gateway {
    104 	gateway_state_t state;
    105 	GIOChannel *rfcomm;
    106 	guint rfcomm_watch_id;
    107 	GIOChannel *sco;
    108 	gateway_stream_cb_t sco_start_cb;
    109 	void *sco_start_cb_data;
    110 	DBusMessage *connect_message;
    111 	guint ag_features;
    112 	guint hold_multiparty_features;
    113 	GSList *indies;
    114 	gboolean is_dialing;
    115 	gboolean call_active;
    116 
    117 	int sp_gain;
    118 	int mic_gain;
    119 };
    120 
    121 static gboolean rfcomm_ag_data_cb(GIOChannel *chan, GIOCondition cond,
    122 					struct audio_device *device);
    123 
    124 int gateway_close(struct audio_device *device);
    125 
    126 static void rfcomm_start_watch(struct audio_device *dev)
    127 {
    128 	struct gateway *gw = dev->gateway;
    129 
    130 	gw->rfcomm_watch_id = g_io_add_watch(gw->rfcomm,
    131 			G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
    132 			(GIOFunc) rfcomm_ag_data_cb, dev);
    133 }
    134 
    135 static void rfcomm_stop_watch(struct audio_device *dev)
    136 {
    137 	struct gateway *gw = dev->gateway;
    138 
    139 	g_source_remove(gw->rfcomm_watch_id);
    140 }
    141 
    142 static gboolean io_channel_write_all(GIOChannel *io, gchar *data,
    143 					gsize count)
    144 {
    145 	gsize written = 0;
    146 	GIOStatus status;
    147 
    148 	while (count > 0) {
    149 		status = g_io_channel_write_chars(io, data, count, &written,
    150 						NULL);
    151 		if (status != G_IO_STATUS_NORMAL)
    152 			return FALSE;
    153 
    154 		data += written;
    155 		count -= written;
    156 	}
    157 	return TRUE;
    158 }
    159 
    160 /* it's worth to mention that data and response could be the same pointers */
    161 static gboolean rfcomm_send_and_read(struct gateway *gw, gchar *data,
    162                                     gchar *response, gsize count)
    163 {
    164 	GIOChannel *rfcomm = gw->rfcomm;
    165 	gsize read = 0;
    166 	gboolean got_ok = FALSE;
    167 	gboolean got_error = FALSE;
    168 	gchar *resp_buf = response;
    169 	gsize toread = RFCOMM_BUF_SIZE - 1;
    170 	GIOStatus status;
    171 
    172 	if (!io_channel_write_all(rfcomm, data, count))
    173 		return FALSE;
    174 
    175 	while (!(got_ok || got_error)) {
    176 		status = g_io_channel_read_chars(rfcomm, resp_buf, toread,
    177 						&read, NULL);
    178 		if (status == G_IO_STATUS_NORMAL)
    179 			resp_buf[read] = '\0';
    180 		else {
    181 			debug("rfcomm_send_and_read(): %m");
    182 			return FALSE;
    183 		}
    184 		got_ok = NULL != strstr(resp_buf, OK_RESPONSE);
    185 		got_error = NULL != strstr(resp_buf, ERROR_RESPONSE);
    186 		resp_buf += read;
    187 		toread -= read;
    188 	}
    189 	return TRUE;
    190 }
    191 
    192 /* get <descr> from the names: (<descr>, (<values>)), (<descr>, (<values>))
    193  * ... */
    194 static GSList *parse_indicator_names(gchar *names, GSList *indies)
    195 {
    196 	gchar *current = names - 1;
    197 	GSList *result = indies;
    198 	gchar *next;
    199 	struct indicator *ind;
    200 
    201 	while (current != NULL) {
    202 		current += 2;
    203 		next = strstr(current, ",(");
    204 		ind = g_slice_new(struct indicator);
    205 		strncpy(ind->descr, current, 20);
    206 		ind->descr[(intptr_t) next - (intptr_t) current] = '\0';
    207 		result = g_slist_append(result, (gpointer) ind);
    208 		current = strstr(next + 1, ",(");
    209 	}
    210 	return result;
    211 }
    212 
    213 /* get values from <val0>,<val1>,... */
    214 static GSList *parse_indicator_values(gchar *values, GSList *indies)
    215 {
    216 	gint val;
    217 	gchar *current = values - 1;
    218 	GSList *runner = indies;
    219 	struct indicator *ind;
    220 
    221 	while (current != NULL) {
    222 		current += 1;
    223 		sscanf(current, "%d", &val);
    224 		current = strchr(current, ',');
    225 		ind = g_slist_nth_data(runner, 0);
    226 		ind->value = val;
    227 		runner = g_slist_next(runner);
    228 	}
    229 	return indies;
    230 }
    231 
    232 /* get values from <val0>,<val1>,... */
    233 static guint get_hold_mpty_features(gchar *features)
    234 {
    235 	guint result = 0;
    236 
    237 	if (strstr(features, "0"))
    238 		result |= AG_CHLD_0;
    239 
    240 	if (strstr(features, "1"))
    241 		result |= AG_CHLD_1;
    242 
    243 	if (strstr(features, "1x"))
    244 		result |= AG_CHLD_1x;
    245 
    246 	if (strstr(features, "2"))
    247 		result |= AG_CHLD_2;
    248 
    249 	if (strstr(features, "2x"))
    250 		result |= AG_CHLD_2x;
    251 
    252 	if (strstr(features, "3"))
    253 		result |= AG_CHLD_3;
    254 
    255 	if (strstr(features, "4"))
    256 		result |= AG_CHLD_4;
    257 
    258 	return result;
    259 }
    260 
    261 static gboolean establish_service_level_conn(struct gateway *gw)
    262 {
    263 	gchar buf[RFCOMM_BUF_SIZE];
    264 	gboolean res;
    265 
    266 	debug("at the begin of establish_service_level_conn()");
    267 	res = rfcomm_send_and_read(gw, AG_FEATURES, buf,
    268 				sizeof(AG_FEATURES) - 1);
    269 	if (!res || sscanf(buf, "\r\n+BRSF:%d", &gw->ag_features) != 1)
    270 		return FALSE;
    271 
    272 	debug("features are 0x%X", gw->ag_features);
    273 	res = rfcomm_send_and_read(gw, AG_INDICATORS_SUPP, buf,
    274 				sizeof(AG_INDICATORS_SUPP) - 1);
    275 	if (!res || !strstr(buf, "+CIND:"))
    276 		return FALSE;
    277 
    278 	gw->indies = parse_indicator_names(strchr(buf, '('), NULL);
    279 
    280 	res = rfcomm_send_and_read(gw, AG_INDICATORS_VAL, buf,
    281 		sizeof(AG_INDICATORS_VAL) - 1);
    282 	if (!res || !strstr(buf, "+CIND:"))
    283 		return FALSE;
    284 
    285 	gw->indies = parse_indicator_values(strchr(buf, ':') + 1, gw->indies);
    286 
    287 	res = rfcomm_send_and_read(gw, AG_INDICATORS_ENABLE, buf,
    288 				sizeof(AG_INDICATORS_ENABLE) - 1);
    289 	if (!res || !strstr(buf, "OK"))
    290 		return FALSE;
    291 
    292 	if ((gw->ag_features & AG_FEATURE_3WAY) != 0) {
    293 		res = rfcomm_send_and_read(gw, AG_HOLD_MPTY_SUPP, buf,
    294 				sizeof(AG_HOLD_MPTY_SUPP) - 1);
    295 		if (!res || !strstr(buf, "+CHLD:")) {
    296 			g_slice_free1(RFCOMM_BUF_SIZE, buf);
    297 			return FALSE;
    298 		}
    299 		gw->hold_multiparty_features = get_hold_mpty_features(
    300 							strchr(buf, '('));
    301 
    302 	} else
    303 		gw->hold_multiparty_features = 0;
    304 
    305 	debug("Service layer connection successfully established!");
    306 	rfcomm_send_and_read(gw, AG_CALLER_IDENT_ENABLE, buf,
    307 			sizeof(AG_CALLER_IDENT_ENABLE) - 1);
    308 	rfcomm_send_and_read(gw, AG_CARRIER_FORMAT, buf,
    309 			sizeof(AG_CARRIER_FORMAT) - 1);
    310 	if ((gw->ag_features & AG_FEATURE_EXTENDED_RES_CODE) != 0)
    311 		rfcomm_send_and_read(gw, AG_EXTENDED_RESULT_CODE, buf,
    312 			sizeof(AG_EXTENDED_RESULT_CODE) - 1);
    313 
    314 	return TRUE;
    315 }
    316 
    317 static void process_ind_change(struct audio_device *dev, guint index,
    318 							gint value)
    319 {
    320 	struct gateway *gw = dev->gateway;
    321 	struct indicator *ind = g_slist_nth_data(gw->indies, index - 1);
    322 	gchar *name = ind->descr;
    323 
    324 	ind->value = value;
    325 
    326 	debug("at the begin of process_ind_change, name is %s", name);
    327 	if (!strcmp(name, "\"call\"")) {
    328 		if (value > 0) {
    329 			g_dbus_emit_signal(dev->conn, dev->path,
    330 					AUDIO_GATEWAY_INTERFACE,
    331 					"CallStarted", DBUS_TYPE_INVALID);
    332 			gw->is_dialing = FALSE;
    333 			gw->call_active = TRUE;
    334 		} else {
    335 			g_dbus_emit_signal(dev->conn, dev->path,
    336 					AUDIO_GATEWAY_INTERFACE,
    337 					"CallEnded", DBUS_TYPE_INVALID);
    338 			gw->call_active = FALSE;
    339 		}
    340 
    341 	} else if (!strcmp(name, "\"callsetup\"")) {
    342 		if (value == 0 && gw->is_dialing) {
    343 			g_dbus_emit_signal(dev->conn, dev->path,
    344 					AUDIO_GATEWAY_INTERFACE,
    345 					"CallTerminated",
    346 					DBUS_TYPE_INVALID);
    347 			gw->is_dialing = FALSE;
    348 		} else if (!gw->is_dialing && value > 0)
    349 			gw->is_dialing = TRUE;
    350 
    351 	} else if (!strcmp(name, "\"callheld\"")) {
    352 		/* FIXME: The following code is based on assumptions only.
    353 		 * Has to be tested for interoperability
    354 		 * I assume that callheld=2 would be sent when dial from HF
    355 		 * failed in case of 3-way call
    356 		 * Unfortunately this path is not covered by the HF spec so
    357 		 * the code has to be tested for interop
    358 		*/
    359 		/* '2' means: all calls held, no active calls */
    360 		if (value == 2) {
    361 			if (gw->is_dialing) {
    362 				g_dbus_emit_signal(dev->conn, dev->path,
    363 					AUDIO_GATEWAY_INTERFACE,
    364 					"CallTerminated",
    365 					DBUS_TYPE_INVALID);
    366 				gw->is_dialing = FALSE;
    367 			}
    368 		}
    369 	} else if (!strcmp(name, "\"service\""))
    370 		emit_property_changed(dev->conn, dev->path,
    371 				AUDIO_GATEWAY_INTERFACE, "RegistrationStatus",
    372 				DBUS_TYPE_UINT16, &value);
    373 	else if (!strcmp(name, "\"signal\""))
    374 		emit_property_changed(dev->conn, dev->path,
    375 				AUDIO_GATEWAY_INTERFACE, "SignalStrength",
    376 				DBUS_TYPE_UINT16, &value);
    377 	else if (!strcmp(name, "\"roam\""))
    378 		emit_property_changed(dev->conn, dev->path,
    379 				AUDIO_GATEWAY_INTERFACE, "RoamingStatus",
    380 				DBUS_TYPE_UINT16, &value);
    381 	else if (!strcmp(name, "\"battchg\""))
    382 		emit_property_changed(dev->conn, dev->path,
    383 				AUDIO_GATEWAY_INTERFACE, "BatteryCharge",
    384 				DBUS_TYPE_UINT16, &value);
    385 }
    386 
    387 static void process_ring(struct audio_device *device, GIOChannel *chan,
    388 			gchar *buf)
    389 {
    390 	gchar number[AG_CALLER_NUM_SIZE];
    391 	gchar *cli;
    392 	gchar *sep;
    393 	gsize read;
    394 	GIOStatus status;
    395 
    396 	rfcomm_stop_watch(device);
    397 	status = g_io_channel_read_chars(chan, buf, RFCOMM_BUF_SIZE - 1, &read, NULL);
    398 	if (status != G_IO_STATUS_NORMAL)
    399 		return;
    400 
    401 	debug("at the begin of process_ring");
    402 	if (strlen(buf) > AG_CALLER_NUM_SIZE + 10)
    403 		error("process_ring(): buf is too long '%s'", buf);
    404 	else if ((cli = strstr(buf, "\r\n+CLIP"))) {
    405 		if (sscanf(cli, "\r\n+CLIP: \"%s", number) == 1) {
    406 			sep = strchr(number, '"');
    407 			sep[0] = '\0';
    408 
    409 			/* FIXME:signal will be emitted on each RING+CLIP.
    410 			 * That's bad */
    411 			cli = number;
    412 			g_dbus_emit_signal(device->conn, device->path,
    413 					AUDIO_GATEWAY_INTERFACE, "Ring",
    414 					DBUS_TYPE_STRING, &cli,
    415 					DBUS_TYPE_INVALID);
    416 			device->gateway->is_dialing = TRUE;
    417 		} else
    418 			error("process_ring(): '%s' in place of +CLIP after RING", buf);
    419 
    420 	}
    421 
    422 	rfcomm_start_watch(device);
    423 }
    424 
    425 static gboolean rfcomm_ag_data_cb(GIOChannel *chan, GIOCondition cond,
    426 					struct audio_device *device)
    427 {
    428 	gchar buf[RFCOMM_BUF_SIZE];
    429 	struct gateway *gw;
    430 	gsize read;
    431 	/* some space for value */
    432 	gchar indicator[AG_INDICATOR_DESCR_SIZE + 4];
    433 	gint value;
    434 	guint index;
    435 	gchar *sep;
    436 
    437 	debug("at the begin of rfcomm_ag_data_cb()");
    438 	if (cond & G_IO_NVAL)
    439 		return FALSE;
    440 
    441 	gw = device->gateway;
    442 
    443 	if (cond & (G_IO_ERR | G_IO_HUP)) {
    444 		debug("connection with remote BT is closed");
    445 		gateway_close(device);
    446 		return FALSE;
    447 	}
    448 
    449 	if (g_io_channel_read_chars(chan, buf, sizeof(buf) - 1, &read, NULL)
    450 			!= G_IO_STATUS_NORMAL)
    451 		return TRUE;
    452 	buf[read] = '\0';
    453 
    454 	if (strlen(buf) > AG_INDICATOR_DESCR_SIZE + 14)
    455 		error("rfcomm_ag_data_cb(): buf is too long '%s'", buf);
    456 	else if (sscanf(buf, "\r\n+CIEV:%s\r\n", indicator) == 1) {
    457 		sep = strchr(indicator, ',');
    458 		sep[0] = '\0';
    459 		sep += 1;
    460 		index = atoi(indicator);
    461 		value = atoi(sep);
    462 		process_ind_change(device, index, value);
    463 	} else if (strstr(buf, "RING"))
    464 		process_ring(device, chan, buf);
    465 	else if (sscanf(buf, "\r\n+BVRA:%d\r\n", &value) == 1) {
    466 		if (value == 0)
    467 			g_dbus_emit_signal(device->conn, device->path,
    468 					AUDIO_GATEWAY_INTERFACE,
    469 					"VoiceRecognitionActive",
    470 					DBUS_TYPE_INVALID);
    471 		else
    472 			g_dbus_emit_signal(device->conn, device->path,
    473 					AUDIO_GATEWAY_INTERFACE,
    474 					"VoiceRecognitionInactive",
    475 					DBUS_TYPE_INVALID);
    476 	} else if (sscanf(buf, "\r\n+VGS:%d\r\n", &value) == 1) {
    477 		gw->sp_gain = value;
    478 		emit_property_changed(device->conn, device->path,
    479 				AUDIO_GATEWAY_INTERFACE, "SpeakerGain",
    480 				DBUS_TYPE_UINT16, &value);
    481 	} else if (sscanf(buf, "\r\n+VGM:%d\r\n", &value) == 1) {
    482 		gw->mic_gain = value;
    483 		emit_property_changed(device->conn, device->path,
    484 				AUDIO_GATEWAY_INTERFACE, "MicrophoneGain",
    485 				DBUS_TYPE_UINT16, &value);
    486 	} else
    487 		error("rfcomm_ag_data_cb(): read wrong data '%s'", buf);
    488 
    489 	return TRUE;
    490 }
    491 
    492 static gboolean sco_io_cb(GIOChannel *chan, GIOCondition cond,
    493 			struct audio_device *dev)
    494 {
    495 	struct gateway *gw = dev->gateway;
    496 
    497 	if (cond & G_IO_NVAL)
    498 		return FALSE;
    499 
    500 	if (cond & (G_IO_ERR | G_IO_HUP)) {
    501 		debug("sco connection is released");
    502 		g_io_channel_shutdown(gw->sco, TRUE, NULL);
    503 		g_io_channel_unref(gw->sco);
    504 		gw->sco = NULL;
    505 		return FALSE;
    506 	}
    507 
    508 	return TRUE;
    509 }
    510 
    511 static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
    512 {
    513 	struct audio_device *dev = (struct audio_device *) user_data;
    514 	struct gateway *gw = dev->gateway;
    515 
    516 	debug("at the begin of sco_connect_cb() in gateway.c");
    517 
    518 	if (err) {
    519 		error("sco_connect_cb(): %s", err->message);
    520 		/* not sure, but from other point of view,
    521 		 * what is the reason to have headset which
    522 		 * cannot play audio? */
    523 		if (gw->sco_start_cb)
    524 			gw->sco_start_cb(NULL, gw->sco_start_cb_data);
    525 		gateway_close(dev);
    526 		return;
    527 	}
    528 
    529 	gw->sco = g_io_channel_ref(chan);
    530 	if (gw->sco_start_cb)
    531 		gw->sco_start_cb(dev, gw->sco_start_cb_data);
    532 
    533 	/* why is this here? */
    534 	fcntl(g_io_channel_unix_get_fd(chan), F_SETFL, 0);
    535 	g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
    536 				(GIOFunc) sco_io_cb, dev);
    537 }
    538 
    539 static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
    540 				gpointer user_data)
    541 {
    542 	struct audio_device *dev = user_data;
    543 	struct gateway *gw = dev->gateway;
    544 	DBusMessage *conn_mes = gw->connect_message;
    545 	gchar gw_addr[18];
    546 	GIOFlags flags;
    547 
    548 	if (err) {
    549 		error("connect(): %s", err->message);
    550 		if (gw->sco_start_cb)
    551 			gw->sco_start_cb(NULL, gw->sco_start_cb_data);
    552 		return;
    553 	}
    554 
    555 	ba2str(&dev->dst, gw_addr);
    556 	/* Blocking mode should be default, but just in case: */
    557 	flags = g_io_channel_get_flags(chan);
    558 	flags &= ~G_IO_FLAG_NONBLOCK;
    559 	flags &= G_IO_FLAG_MASK;
    560 	g_io_channel_set_flags(chan, flags, NULL);
    561 	g_io_channel_set_encoding(chan, NULL, NULL);
    562 	g_io_channel_set_buffered(chan, FALSE);
    563 	if (!gw->rfcomm)
    564 		gw->rfcomm = g_io_channel_ref(chan);
    565 
    566 	if (establish_service_level_conn(dev->gateway)) {
    567 		gboolean value = TRUE;
    568 
    569 		debug("%s: Connected to %s", dev->path, gw_addr);
    570 		rfcomm_start_watch(dev);
    571 		if (conn_mes) {
    572 			DBusMessage *reply =
    573 				dbus_message_new_method_return(conn_mes);
    574 			dbus_connection_send(dev->conn, reply, NULL);
    575 			dbus_message_unref(reply);
    576 			dbus_message_unref(conn_mes);
    577 			gw->connect_message = NULL;
    578 		}
    579 
    580 		gw->state = GATEWAY_STATE_CONNECTED;
    581 		emit_property_changed(dev->conn, dev->path,
    582 				AUDIO_GATEWAY_INTERFACE,
    583 				"Connected", DBUS_TYPE_BOOLEAN,	&value);
    584 		return;
    585 	} else
    586 		error("%s: Failed to establish service layer connection to %s",
    587 			dev->path, gw_addr);
    588 
    589 	if (NULL != gw->sco_start_cb)
    590 		gw->sco_start_cb(NULL, gw->sco_start_cb_data);
    591 
    592 	gateway_close(dev);
    593 }
    594 
    595 static void get_record_cb(sdp_list_t *recs, int perr, gpointer user_data)
    596 {
    597 	struct audio_device *dev = user_data;
    598 	DBusMessage *msg = dev->gateway->connect_message;
    599 	int ch = -1;
    600 	sdp_list_t *protos, *classes;
    601 	uuid_t uuid;
    602 	gateway_stream_cb_t sco_cb;
    603 	GIOChannel *io;
    604 	GError *err = NULL;
    605 
    606 	if (perr < 0) {
    607 		error("Unable to get service record: %s (%d)", strerror(-perr),
    608 					-perr);
    609 		goto fail;
    610 	}
    611 
    612 	if (!recs || !recs->data) {
    613 		error("No records found");
    614 		goto fail;
    615 	}
    616 
    617 	if (sdp_get_service_classes(recs->data, &classes) < 0) {
    618 		error("Unable to get service classes from record");
    619 		goto fail;
    620 	}
    621 
    622 	if (sdp_get_access_protos(recs->data, &protos) < 0) {
    623 		error("Unable to get access protocols from record");
    624 		goto fail;
    625 	}
    626 
    627 	memcpy(&uuid, classes->data, sizeof(uuid));
    628 	sdp_list_free(classes, free);
    629 
    630 	if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
    631 			uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
    632 		sdp_list_free(protos, NULL);
    633 		error("Invalid service record or not HFP");
    634 		goto fail;
    635 	}
    636 
    637 	ch = sdp_get_proto_port(protos, RFCOMM_UUID);
    638 	sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
    639 	sdp_list_free(protos, NULL);
    640 	if (ch <= 0) {
    641 		error("Unable to extract RFCOMM channel from service record");
    642 		goto fail;
    643 	}
    644 
    645 	io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, dev, NULL, &err,
    646 				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
    647 				BT_IO_OPT_DEST_BDADDR, &dev->dst,
    648 				BT_IO_OPT_CHANNEL, ch,
    649 				BT_IO_OPT_INVALID);
    650 	if (!io) {
    651 		error("Unable to connect: %s", err->message);
    652 		if (msg) {
    653 			error_common_reply(dev->conn, msg, ERROR_INTERFACE
    654 						".ConnectionAttemptFailed",
    655 						err->message);
    656 			msg = NULL;
    657 		}
    658 		g_error_free(err);
    659 		gateway_close(dev);
    660 	}
    661 
    662 	g_io_channel_unref(io);
    663 	return;
    664 
    665 fail:
    666 	if (msg)
    667 		error_common_reply(dev->conn, msg, ERROR_INTERFACE
    668 					".NotSupported", "Not supported");
    669 
    670 	dev->gateway->connect_message = NULL;
    671 
    672 	sco_cb = dev->gateway->sco_start_cb;
    673 	if (sco_cb)
    674 		sco_cb(NULL, dev->gateway->sco_start_cb_data);
    675 }
    676 
    677 static int get_records(struct audio_device *device)
    678 {
    679 	uuid_t uuid;
    680 
    681 	sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
    682 	return bt_search_service(&device->src, &device->dst, &uuid,
    683 				get_record_cb, device, NULL);
    684 }
    685 
    686 static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
    687 				void *data)
    688 {
    689 	struct audio_device *au_dev = (struct audio_device *) data;
    690 	struct gateway *gw = au_dev->gateway;
    691 
    692 	debug("at the begin of ag_connect()");
    693 	if (gw->rfcomm)
    694 		return g_dbus_create_error(msg, ERROR_INTERFACE
    695 					".AlreadyConnected",
    696 					"Already Connected");
    697 
    698 	gw->connect_message = dbus_message_ref(msg);
    699 	if (get_records(au_dev) < 0) {
    700 		dbus_message_unref(gw->connect_message);
    701 		return g_dbus_create_error(msg, ERROR_INTERFACE
    702 					".ConnectAttemptFailed",
    703 					"Connect Attempt Failed");
    704 	}
    705 	debug("at the end of ag_connect()");
    706 	return NULL;
    707 }
    708 
    709 static DBusMessage *ag_disconnect(DBusConnection *conn, DBusMessage *msg,
    710 					void *data)
    711 {
    712 	struct audio_device *device = data;
    713 	struct gateway *gw = device->gateway;
    714 	DBusMessage *reply = NULL;
    715 	char gw_addr[18];
    716 
    717 	reply = dbus_message_new_method_return(msg);
    718 	if (!reply)
    719 		return NULL;
    720 
    721 	if (!gw->rfcomm)
    722 		return g_dbus_create_error(msg, ERROR_INTERFACE
    723 						".NotConnected",
    724 						"Device not Connected");
    725 
    726 	gateway_close(device);
    727 	ba2str(&device->dst, gw_addr);
    728 	debug("Disconnected from %s, %s", gw_addr, device->path);
    729 
    730 	return reply;
    731 }
    732 
    733 static DBusMessage *process_ag_reponse(DBusMessage *msg, gchar *response)
    734 {
    735 	DBusMessage *reply;
    736 
    737 
    738 	debug("in process_ag_reponse, response is %s", response);
    739 	if (strstr(response, OK_RESPONSE))
    740 		reply = dbus_message_new_method_return(msg);
    741 	else {
    742 		/* FIXME: some code should be here to processes errors
    743 		 *  in better fasion */
    744 		debug("AG responded with '%s' to %s method call", response,
    745 				dbus_message_get_member(msg));
    746 		reply = dbus_message_new_error(msg, ERROR_INTERFACE
    747 					".OperationFailed",
    748 					"Operation failed.See log for details");
    749 	}
    750 	return reply;
    751 }
    752 
    753 static DBusMessage *process_simple(DBusMessage *msg, struct audio_device *dev,
    754 					gchar *data)
    755 {
    756 	struct gateway *gw = dev->gateway;
    757 	gchar buf[RFCOMM_BUF_SIZE];
    758 
    759 	rfcomm_stop_watch(dev);
    760 	rfcomm_send_and_read(gw, data, buf, strlen(data));
    761 	rfcomm_start_watch(dev);
    762 	return process_ag_reponse(msg, buf);
    763 }
    764 
    765 #define AG_ANSWER "ATA\r"
    766 
    767 static DBusMessage *ag_answer(DBusConnection *conn, DBusMessage *msg,
    768 				void *data)
    769 {
    770 	struct audio_device *dev = data;
    771 	struct gateway *gw = dev->gateway;
    772 
    773 	if (!gw->rfcomm)
    774 		return g_dbus_create_error(msg, ERROR_INTERFACE
    775 					".NotConnected",
    776 					"Not Connected");
    777 
    778 	if (gw->call_active)
    779 		return g_dbus_create_error(msg, ERROR_INTERFACE
    780 					".CallAlreadyAnswered",
    781 					"Call AlreadyAnswered");
    782 
    783 	return process_simple(msg, dev, AG_ANSWER);
    784 }
    785 
    786 #define AG_HANGUP "AT+CHUP\r"
    787 
    788 static DBusMessage *ag_terminate_call(DBusConnection *conn, DBusMessage *msg,
    789 				void *data)
    790 {
    791 	struct audio_device *dev = data;
    792 	struct gateway *gw = dev->gateway;
    793 
    794 	if (!gw->rfcomm)
    795 		return g_dbus_create_error(msg, ERROR_INTERFACE
    796 					".NotConnected",
    797 					"Not Connected");
    798 
    799 	return process_simple(msg, dev, AG_HANGUP);
    800 }
    801 
    802 /* according to GSM spec */
    803 #define ALLOWED_NUMBER_SYMBOLS "1234567890*#ABCD"
    804 #define AG_PLACE_CALL "ATD%s;\r"
    805 /* dialing from memory is not supported as headset spec doesn't define a way
    806  * to retreive phone memory entries.
    807  */
    808 static DBusMessage *ag_call(DBusConnection *conn, DBusMessage *msg,
    809 				void *data)
    810 {
    811 	struct audio_device *device = data;
    812 	struct gateway *gw = device->gateway;
    813 	gchar buf[RFCOMM_BUF_SIZE];
    814 	gchar *number;
    815 	gint atd_len;
    816 	DBusMessage *result;
    817 
    818 	debug("at the begin of ag_call()");
    819 	if (!gw->rfcomm)
    820 		return g_dbus_create_error(msg, ERROR_INTERFACE
    821 					".NotConnected",
    822 					"Not Connected");
    823 
    824 	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &number,
    825 				DBUS_TYPE_INVALID);
    826 	if (strlen(number) != strspn(number, ALLOWED_NUMBER_SYMBOLS))
    827 		return dbus_message_new_error(msg,
    828 			ERROR_INTERFACE ".BadNumber",
    829 			"Number contains characters which are not allowed");
    830 
    831 	atd_len = sprintf(buf, AG_PLACE_CALL, number);
    832 	rfcomm_stop_watch(device);
    833 	rfcomm_send_and_read(gw, buf, buf, atd_len);
    834 	rfcomm_start_watch(device);
    835 
    836 	result = process_ag_reponse(msg, buf);
    837 	return result;
    838 }
    839 
    840 #define AG_GET_CARRIER "AT+COPS?\r"
    841 
    842 static DBusMessage *ag_get_operator(DBusConnection *conn, DBusMessage *msg,
    843 					void *data)
    844 {
    845 	struct audio_device *dev = (struct audio_device *) data;
    846 	struct gateway *gw = dev->gateway;
    847 	gchar buf[RFCOMM_BUF_SIZE];
    848 	GIOChannel *rfcomm = gw->rfcomm;
    849 	gsize read;
    850 	gchar *result, *sep;
    851 	DBusMessage *reply;
    852 	GIOStatus status;
    853 
    854 	if (!gw->rfcomm)
    855 		return g_dbus_create_error(msg, ERROR_INTERFACE
    856 					".NotConnected",
    857 					"Not Connected");
    858 
    859 	rfcomm_stop_watch(dev);
    860 	io_channel_write_all(rfcomm, AG_GET_CARRIER, strlen(AG_GET_CARRIER));
    861 
    862 	status = g_io_channel_read_chars(rfcomm, buf, RFCOMM_BUF_SIZE - 1,
    863 						&read, NULL);
    864 	rfcomm_start_watch(dev);
    865 	if (G_IO_STATUS_NORMAL == status) {
    866 		buf[read] = '\0';
    867 		if (strstr(buf, "+COPS")) {
    868 			if (!strrchr(buf, ','))
    869 				result = "0";
    870 			else {
    871 				result = strchr(buf, '\"') + 1;
    872 				sep = strchr(result, '\"');
    873 				sep[0] = '\0';
    874 			}
    875 
    876 			reply = dbus_message_new_method_return(msg);
    877 			dbus_message_append_args(reply, DBUS_TYPE_STRING,
    878 						&result, DBUS_TYPE_INVALID);
    879 		} else {
    880 			info("ag_get_operator(): '+COPS' expected but"
    881 				" '%s' received", buf);
    882 			reply = dbus_message_new_error(msg, ERROR_INTERFACE
    883 						".Failed",
    884 						"Unexpected response from AG");
    885 		}
    886 	} else {
    887 		error("ag_get_operator(): %m");
    888 		reply = dbus_message_new_error(msg, ERROR_INTERFACE
    889 					".ConnectionFailed",
    890 					"Failed to receive response from AG");
    891 	}
    892 
    893 	return reply;
    894 }
    895 
    896 #define AG_SEND_DTMF "AT+VTS=%c\r"
    897 static DBusMessage *ag_send_dtmf(DBusConnection *conn, DBusMessage *msg,
    898 				void *data)
    899 {
    900 	struct audio_device *device = data;
    901 	struct gateway *gw = device->gateway;
    902 	gchar buf[RFCOMM_BUF_SIZE];
    903 	gchar *number;
    904 	gint com_len;
    905 	gboolean got_ok = TRUE;
    906 	gint num_len;
    907 	gint i = 0;
    908 
    909 	if (!gw->rfcomm)
    910 		return g_dbus_create_error(msg, ERROR_INTERFACE
    911 					".NotConnected",
    912 					"Not Connected");
    913 
    914 	dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &number,
    915 				DBUS_TYPE_INVALID);
    916 	if (strlen(number) != strspn(number, ALLOWED_NUMBER_SYMBOLS))
    917 		return dbus_message_new_error(msg,
    918 			ERROR_INTERFACE ".BadNumber",
    919 			"Number contains characters which are not allowed");
    920 
    921 	num_len = strlen(number);
    922 	rfcomm_stop_watch(device);
    923 	while (i < num_len && got_ok) {
    924 		com_len = sprintf(buf, AG_SEND_DTMF, number[i]);
    925 		rfcomm_send_and_read(gw, buf, buf, com_len);
    926 		got_ok = NULL != strstr(buf, OK_RESPONSE);
    927 		i += 1;
    928 	}
    929 	rfcomm_start_watch(device);
    930 	return process_ag_reponse(msg, buf);
    931 }
    932 
    933 #define AG_GET_SUBSCRIBER_NUMS "AT+CNUM\r"
    934 #define CNUM_LEN 5             /* length of "+CNUM" string */
    935 #define MAX_NUMBER_CNT 16
    936 static DBusMessage *ag_get_subscriber_num(DBusConnection *conn,
    937 					DBusMessage *msg, void *data)
    938 {
    939 	struct audio_device *device = data;
    940 	struct gateway *gw = device->gateway;
    941 	gchar buf[RFCOMM_BUF_SIZE];
    942 	gchar *number, *end;
    943 	DBusMessage *reply = dbus_message_new_method_return(msg);
    944 
    945 	if (!gw->rfcomm)
    946 		return g_dbus_create_error(msg, ERROR_INTERFACE
    947 					".NotConnected",
    948 					"Not Connected");
    949 
    950 	rfcomm_stop_watch(device);
    951 	rfcomm_send_and_read(gw, AG_GET_SUBSCRIBER_NUMS, buf,
    952 			strlen(AG_GET_SUBSCRIBER_NUMS));
    953 	rfcomm_start_watch(device);
    954 
    955 	if (strlen(buf) > AG_CALLER_NUM_SIZE + 21)
    956 		error("ag_get_subscriber_num(): buf is too long '%s'", buf);
    957 	else if (strstr(buf, "+CNUM")) {
    958 		number = strchr(buf, ',');
    959 		number++;
    960 		end = strchr(number, ',');
    961 		if (end) {
    962 			*end = '\0';
    963 			dbus_message_append_args(reply, DBUS_TYPE_STRING,
    964 						&number, DBUS_TYPE_INVALID);
    965 		}
    966 	} else
    967 		error("ag_get_subscriber_num(): read wrong data '%s'", buf);
    968 
    969 	return reply;
    970 }
    971 
    972 static DBusMessage *ag_get_properties(DBusConnection *conn, DBusMessage *msg,
    973 					void *data)
    974 {
    975 	struct audio_device *device = data;
    976 	struct gateway *gw = device->gateway;
    977 	DBusMessage *reply;
    978 	DBusMessageIter iter;
    979 	DBusMessageIter dict;
    980 	gboolean value;
    981 	guint index = 0;
    982 	struct indicator *ind;
    983 
    984 	reply = dbus_message_new_method_return(msg);
    985 	if (!reply)
    986 		return NULL;
    987 
    988 	dbus_message_iter_init_append(reply, &iter);
    989 
    990 	dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
    991 			DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    992 			DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
    993 			DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
    994 
    995 	/* Connected */
    996 	value = gateway_is_connected(device);
    997 	dict_append_entry(&dict, "Connected", DBUS_TYPE_BOOLEAN, &value);
    998 
    999 	if (!value)
   1000 		goto done;
   1001 
   1002 	while ((ind = g_slist_nth_data(gw->indies, index))) {
   1003 		if(!strcmp(ind->descr, "\"service\""))
   1004 			dict_append_entry(&dict, "RegistrationStatus",
   1005 					DBUS_TYPE_UINT16, &ind->value);
   1006 		else if (!strcmp(ind->descr, "\"signal\""))
   1007 			dict_append_entry(&dict, "SignalStrength",
   1008 					DBUS_TYPE_UINT16, &ind->value);
   1009 		else if (!strcmp(ind->descr, "\"roam\""))
   1010 			dict_append_entry(&dict, "RoamingStatus",
   1011 					DBUS_TYPE_UINT16, &ind->value);
   1012 		else if (!strcmp(ind->descr, "\"battchg\""))
   1013 			dict_append_entry(&dict, "BatteryCharge",
   1014 					DBUS_TYPE_UINT16, &ind->value);
   1015 		index++;
   1016 	}
   1017 
   1018 	/* SpeakerGain */
   1019 	dict_append_entry(&dict, "SpeakerGain", DBUS_TYPE_UINT16,
   1020 				&device->gateway->sp_gain);
   1021 
   1022 	/* MicrophoneGain */
   1023 	dict_append_entry(&dict, "MicrophoneGain", DBUS_TYPE_UINT16,
   1024 				&device->gateway->mic_gain);
   1025 done:
   1026 	dbus_message_iter_close_container(&iter, &dict);
   1027 	return reply;
   1028 }
   1029 
   1030 static GDBusMethodTable gateway_methods[] = {
   1031 	{ "Connect", "", "", ag_connect, G_DBUS_METHOD_FLAG_ASYNC },
   1032 	{ "Disconnect", "", "", ag_disconnect },
   1033 	{ "AnswerCall", "", "", ag_answer },
   1034 	{ "TerminateCall", "", "", ag_terminate_call },
   1035 	{ "Call", "s", "", ag_call },
   1036 	{ "GetOperatorName", "", "s", ag_get_operator },
   1037 	{ "SendDTMF", "s", "", ag_send_dtmf },
   1038 	{ "GetSubscriberNumber", "", "s", ag_get_subscriber_num },
   1039 	{ "GetProperties", "", "a{sv}", ag_get_properties },
   1040 	{ NULL, NULL, NULL, NULL }
   1041 };
   1042 
   1043 static GDBusSignalTable gateway_signals[] = {
   1044 	{ "Ring", "s" },
   1045 	{ "CallTerminated", "" },
   1046 	{ "CallStarted", "" },
   1047 	{ "CallEnded", "" },
   1048 	{ "PropertyChanged", "sv" },
   1049 	{ NULL, NULL }
   1050 };
   1051 
   1052 struct gateway *gateway_init(struct audio_device *dev)
   1053 {
   1054 	struct gateway *gw;
   1055 
   1056 	if (!g_dbus_register_interface(dev->conn, dev->path,
   1057 					AUDIO_GATEWAY_INTERFACE,
   1058 					gateway_methods, gateway_signals,
   1059 					NULL, dev, NULL))
   1060 		return NULL;
   1061 
   1062 	debug("in gateway_init, dev is %p", dev);
   1063 	gw = g_new0(struct gateway, 1);
   1064 	gw->indies = NULL;
   1065 	gw->is_dialing = FALSE;
   1066 	gw->call_active = FALSE;
   1067 	gw->state = GATEWAY_STATE_DISCONNECTED;
   1068 	return gw;
   1069 
   1070 }
   1071 
   1072 gboolean gateway_is_connected(struct audio_device *dev)
   1073 {
   1074 	return (dev && dev->gateway &&
   1075 			dev->gateway->state == GATEWAY_STATE_CONNECTED);
   1076 }
   1077 
   1078 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
   1079 {
   1080 	if (!io)
   1081 		return -EINVAL;
   1082 
   1083 	g_io_channel_ref(io);
   1084 	dev->gateway->rfcomm = io;
   1085 
   1086 	return 0;
   1087 }
   1088 
   1089 int gateway_connect_sco(struct audio_device *dev, GIOChannel *io)
   1090 {
   1091 	struct gateway *gw = dev->gateway;
   1092 
   1093 	if (gw->sco)
   1094 		return -EISCONN;
   1095 
   1096 	gw->sco = g_io_channel_ref(io);
   1097 
   1098 	g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
   1099                                 (GIOFunc) sco_io_cb, dev);
   1100 	return 0;
   1101 }
   1102 
   1103 void gateway_start_service(struct audio_device *device)
   1104 {
   1105 	rfcomm_connect_cb(device->gateway->rfcomm, NULL, device);
   1106 }
   1107 
   1108 static void indicator_slice_free(gpointer mem)
   1109 {
   1110 	g_slice_free(struct indicator, mem);
   1111 }
   1112 
   1113 int gateway_close(struct audio_device *device)
   1114 {
   1115 	struct gateway *gw = device->gateway;
   1116 	GIOChannel *rfcomm = gw->rfcomm;
   1117 	GIOChannel *sco = gw->sco;
   1118 	gboolean value = FALSE;
   1119 
   1120 	g_slist_foreach(gw->indies, (GFunc) indicator_slice_free, NULL);
   1121 	g_slist_free(gw->indies);
   1122 	if (rfcomm) {
   1123 		g_io_channel_shutdown(rfcomm, TRUE, NULL);
   1124 		g_io_channel_unref(rfcomm);
   1125 		gw->rfcomm = NULL;
   1126 	}
   1127 
   1128 	if (sco) {
   1129 		g_io_channel_shutdown(sco, TRUE, NULL);
   1130 		g_io_channel_unref(sco);
   1131 		gw->sco = NULL;
   1132 		gw->sco_start_cb = NULL;
   1133 		gw->sco_start_cb_data = NULL;
   1134 	}
   1135 
   1136 	gw->state = GATEWAY_STATE_DISCONNECTED;
   1137 
   1138 	emit_property_changed(device->conn, device->path,
   1139 				AUDIO_GATEWAY_INTERFACE,
   1140 				"Connected", DBUS_TYPE_BOOLEAN, &value);
   1141 	return 0;
   1142 }
   1143 
   1144 /* These are functions to be called from unix.c for audio system
   1145  * ifaces (alsa, gstreamer, etc.) */
   1146 gboolean gateway_request_stream(struct audio_device *dev,
   1147 				gateway_stream_cb_t cb, void *user_data)
   1148 {
   1149 	struct gateway *gw = dev->gateway;
   1150 	GError *err = NULL;
   1151 	GIOChannel *io;
   1152 
   1153 	if (!gw->rfcomm) {
   1154 		gw->sco_start_cb = cb;
   1155 		gw->sco_start_cb_data = user_data;
   1156 		get_records(dev);
   1157 	} else if (!gw->sco) {
   1158 		gw->sco_start_cb = cb;
   1159 		gw->sco_start_cb_data = user_data;
   1160 		io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
   1161 				BT_IO_OPT_SOURCE_BDADDR, &dev->src,
   1162 				BT_IO_OPT_DEST_BDADDR, &dev->dst,
   1163 				BT_IO_OPT_INVALID);
   1164 		if (!io) {
   1165 			error("%s", err->message);
   1166 			g_error_free(err);
   1167 			return FALSE;
   1168 		}
   1169 	} else {
   1170 		if (cb)
   1171 			cb(dev, user_data);
   1172 	}
   1173 
   1174 	return TRUE;
   1175 }
   1176 
   1177 int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t sco_cb,
   1178 				void *user_data)
   1179 {
   1180 	struct gateway *gw = dev->gateway;
   1181 
   1182 	if (!gw->rfcomm) {
   1183 		gw->sco_start_cb = sco_cb;
   1184 		gw->sco_start_cb_data = user_data;
   1185 		return get_records(dev);
   1186 	}
   1187 
   1188 	if (sco_cb)
   1189 		sco_cb(dev, user_data);
   1190 
   1191 	return 0;
   1192 }
   1193 
   1194 gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
   1195 {
   1196 	gateway_close(dev);
   1197 	return TRUE;
   1198 }
   1199 
   1200 int gateway_get_sco_fd(struct audio_device *dev)
   1201 {
   1202 	struct gateway *gw = dev->gateway;
   1203 
   1204 	if (!gw || !gw->sco)
   1205 		return -1;
   1206 
   1207 	return g_io_channel_unix_get_fd(gw->sco);
   1208 }
   1209 
   1210 void gateway_suspend_stream(struct audio_device *dev)
   1211 {
   1212 	struct gateway *gw = dev->gateway;
   1213 
   1214 	if (!gw || !gw->sco)
   1215 		return;
   1216 
   1217 	g_io_channel_shutdown(gw->sco, TRUE, NULL);
   1218 	g_io_channel_unref(gw->sco);
   1219 	gw->sco = NULL;
   1220 	gw->sco_start_cb = NULL;
   1221 	gw->sco_start_cb_data = NULL;
   1222 }
   1223 
   1224