Tizen 2.0 Release
[profile/ivi/bluez.git] / audio / gateway.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2006-2010  Nokia Corporation
6  *  Copyright (C) 2004-2010  Marcel Holtmann <marcel@holtmann.org>
7  *  Copyright (C) 2008-2009  Leonid Movshovich <event.riga@gmail.org>
8  *  Copyright (C) 2010  ProFUSION embedded systems
9  *
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
24  *
25  */
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <errno.h>
36
37 #include <glib.h>
38 #include <dbus/dbus.h>
39 #include <gdbus.h>
40
41 #include <bluetooth/bluetooth.h>
42 #include <bluetooth/sdp.h>
43 #include <bluetooth/sdp_lib.h>
44
45 #include "sdp-client.h"
46 #include "device.h"
47 #include "gateway.h"
48 #include "log.h"
49 #include "error.h"
50 #include "btio.h"
51 #include "dbus-common.h"
52
53 struct hf_agent {
54         char *name;     /* Bus id */
55         char *path;     /* D-Bus path */
56         guint watch;    /* Disconnect watch */
57 };
58
59 struct connect_cb {
60         unsigned int id;
61         gateway_stream_cb_t cb;
62         void *cb_data;
63 };
64
65 struct gateway {
66         gateway_state_t state;
67         GIOChannel *rfcomm;
68         GIOChannel *sco;
69         GIOChannel *incoming;
70         GSList *callbacks;
71         struct hf_agent *agent;
72         DBusMessage *msg;
73         int version;
74         gateway_lock_t lock;
75 };
76
77 struct gateway_state_callback {
78         gateway_state_cb cb;
79         void *user_data;
80         unsigned int id;
81 };
82
83 static GSList *gateway_callbacks = NULL;
84
85 int gateway_close(struct audio_device *device);
86
87 GQuark gateway_error_quark(void)
88 {
89         return g_quark_from_static_string("gateway-error-quark");
90 }
91
92 static const char *state2str(gateway_state_t state)
93 {
94         switch (state) {
95         case GATEWAY_STATE_DISCONNECTED:
96                 return "disconnected";
97         case GATEWAY_STATE_CONNECTING:
98                 return "connecting";
99         case GATEWAY_STATE_CONNECTED:
100                 return "connected";
101         case GATEWAY_STATE_PLAYING:
102                 return "playing";
103         default:
104                 return "";
105         }
106 }
107
108 static void agent_free(struct hf_agent *agent)
109 {
110         if (!agent)
111                 return;
112
113         g_free(agent->name);
114         g_free(agent->path);
115         g_free(agent);
116 }
117
118 static void change_state(struct audio_device *dev, gateway_state_t new_state)
119 {
120         struct gateway *gw = dev->gateway;
121         const char *val;
122         GSList *l;
123         gateway_state_t old_state;
124
125         if (gw->state == new_state)
126                 return;
127
128         val = state2str(new_state);
129         old_state = gw->state;
130         gw->state = new_state;
131
132         emit_property_changed(dev->conn, dev->path,
133                         AUDIO_GATEWAY_INTERFACE, "State",
134                         DBUS_TYPE_STRING, &val);
135
136         for (l = gateway_callbacks; l != NULL; l = l->next) {
137                 struct gateway_state_callback *cb = l->data;
138                 cb->cb(dev, old_state, new_state, cb->user_data);
139         }
140 }
141
142 void gateway_set_state(struct audio_device *dev, gateway_state_t new_state)
143 {
144         switch (new_state) {
145         case GATEWAY_STATE_DISCONNECTED:
146                 gateway_close(dev);
147                 break;
148         case GATEWAY_STATE_CONNECTING:
149         case GATEWAY_STATE_CONNECTED:
150         case GATEWAY_STATE_PLAYING:
151                 break;
152         }
153 }
154
155 static void agent_disconnect(struct audio_device *dev, struct hf_agent *agent)
156 {
157         DBusMessage *msg;
158
159         msg = dbus_message_new_method_call(agent->name, agent->path,
160                         "org.bluez.HandsfreeAgent", "Release");
161
162         g_dbus_send_message(dev->conn, msg);
163 }
164
165 static gboolean agent_sendfd(struct hf_agent *agent, int fd,
166                 DBusPendingCallNotifyFunction notify, void *data)
167 {
168         struct audio_device *dev = data;
169         struct gateway *gw = dev->gateway;
170         DBusMessage *msg;
171         DBusPendingCall *call;
172
173         msg = dbus_message_new_method_call(agent->name, agent->path,
174                         "org.bluez.HandsfreeAgent", "NewConnection");
175
176         dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &fd,
177                                         DBUS_TYPE_UINT16, &gw->version,
178                                         DBUS_TYPE_INVALID);
179
180         if (dbus_connection_send_with_reply(dev->conn, msg,
181                                                         &call, -1) == FALSE) {
182                 dbus_message_unref(msg);
183                 return FALSE;
184         }
185
186         dbus_pending_call_set_notify(call, notify, dev, NULL);
187         dbus_pending_call_unref(call);
188         dbus_message_unref(msg);
189
190         return TRUE;
191 }
192
193 static unsigned int connect_cb_new(struct gateway *gw,
194                                         gateway_stream_cb_t func,
195                                         void *user_data)
196 {
197         struct connect_cb *cb;
198         static unsigned int free_cb_id = 1;
199
200         if (!func)
201                 return 0;
202
203         cb = g_new(struct connect_cb, 1);
204
205         cb->cb = func;
206         cb->cb_data = user_data;
207         cb->id = free_cb_id++;
208
209         gw->callbacks = g_slist_append(gw->callbacks, cb);
210
211         return cb->id;
212 }
213
214 static void run_connect_cb(struct audio_device *dev, GError *err)
215 {
216         struct gateway *gw = dev->gateway;
217         GSList *l;
218
219         for (l = gw->callbacks; l != NULL; l = l->next) {
220                 struct connect_cb *cb = l->data;
221                 cb->cb(dev, err, cb->cb_data);
222         }
223
224         g_slist_free_full(gw->callbacks, g_free);
225         gw->callbacks = NULL;
226 }
227
228 static gboolean sco_io_cb(GIOChannel *chan, GIOCondition cond,
229                         struct audio_device *dev)
230 {
231         struct gateway *gw = dev->gateway;
232
233         if (cond & G_IO_NVAL)
234                 return FALSE;
235
236         DBG("sco connection is released");
237         g_io_channel_shutdown(gw->sco, TRUE, NULL);
238         g_io_channel_unref(gw->sco);
239         gw->sco = NULL;
240         change_state(dev, GATEWAY_STATE_CONNECTED);
241
242         return FALSE;
243 }
244
245 static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
246 {
247         struct audio_device *dev = (struct audio_device *) user_data;
248         struct gateway *gw = dev->gateway;
249
250         DBG("at the begin of sco_connect_cb() in gateway.c");
251
252         gw->sco = g_io_channel_ref(chan);
253
254         if (err) {
255                 error("sco_connect_cb(): %s", err->message);
256                 gateway_suspend_stream(dev);
257                 return;
258         }
259
260         g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
261                                 (GIOFunc) sco_io_cb, dev);
262
263         change_state(dev, GATEWAY_STATE_PLAYING);
264         run_connect_cb(dev, NULL);
265 }
266
267 static gboolean rfcomm_disconnect_cb(GIOChannel *chan, GIOCondition cond,
268                         struct audio_device *dev)
269 {
270         if (cond & G_IO_NVAL)
271                 return FALSE;
272
273         gateway_close(dev);
274
275         return FALSE;
276 }
277
278 static void newconnection_reply(DBusPendingCall *call, void *data)
279 {
280         struct audio_device *dev = data;
281         struct gateway *gw = dev->gateway;
282         DBusMessage *reply = dbus_pending_call_steal_reply(call);
283         DBusError derr;
284
285         if (!dev->gateway->rfcomm) {
286                 DBG("RFCOMM disconnected from server before agent reply");
287                 goto done;
288         }
289
290         dbus_error_init(&derr);
291         if (!dbus_set_error_from_message(&derr, reply)) {
292                 DBG("Agent reply: file descriptor passed successfully");
293                 g_io_add_watch(gw->rfcomm, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
294                                         (GIOFunc) rfcomm_disconnect_cb, dev);
295                 change_state(dev, GATEWAY_STATE_CONNECTED);
296                 goto done;
297         }
298
299         DBG("Agent reply: %s", derr.message);
300
301         dbus_error_free(&derr);
302         gateway_close(dev);
303
304 done:
305         dbus_message_unref(reply);
306 }
307
308 static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
309                                 gpointer user_data)
310 {
311         struct audio_device *dev = user_data;
312         struct gateway *gw = dev->gateway;
313         DBusMessage *reply;
314         int sk, ret;
315
316         if (err) {
317                 error("connect(): %s", err->message);
318                 goto fail;
319         }
320
321         if (!gw->agent) {
322                 error("Handsfree Agent not registered");
323                 goto fail;
324         }
325
326         sk = g_io_channel_unix_get_fd(chan);
327
328         if (gw->rfcomm == NULL)
329                 gw->rfcomm = g_io_channel_ref(chan);
330
331         ret = agent_sendfd(gw->agent, sk, newconnection_reply, dev);
332
333         if (!gw->msg)
334                 return;
335
336         if (ret)
337                 reply = dbus_message_new_method_return(gw->msg);
338         else
339                 reply = btd_error_failed(gw->msg, "Can't pass file descriptor");
340
341         g_dbus_send_message(dev->conn, reply);
342
343         return;
344
345 fail:
346         if (gw->msg) {
347                 DBusMessage *reply;
348                 reply = btd_error_failed(gw->msg, "Connect failed");
349                 g_dbus_send_message(dev->conn, reply);
350         }
351
352         gateway_close(dev);
353 }
354
355 static int get_remote_profile_version(sdp_record_t *rec)
356 {
357         uuid_t uuid;
358         sdp_list_t *profiles;
359         sdp_profile_desc_t *desc;
360         int ver = 0;
361
362         sdp_uuid16_create(&uuid, HANDSFREE_PROFILE_ID);
363
364         sdp_get_profile_descs(rec, &profiles);
365         if (profiles == NULL)
366                 goto done;
367
368         desc = profiles->data;
369
370         if (sdp_uuid16_cmp(&desc->uuid, &uuid) == 0)
371                 ver = desc->version;
372
373         sdp_list_free(profiles, free);
374
375 done:
376         return ver;
377 }
378
379 static void get_incoming_record_cb(sdp_list_t *recs, int err,
380                                         gpointer user_data)
381 {
382         struct audio_device *dev = user_data;
383         struct gateway *gw = dev->gateway;
384         GError *gerr = NULL;
385
386         if (err < 0) {
387                 error("Unable to get service record: %s (%d)", strerror(-err),
388                                         -err);
389                 goto fail;
390         }
391
392         if (!recs || !recs->data) {
393                 error("No records found");
394                 goto fail;
395         }
396
397         gw->version = get_remote_profile_version(recs->data);
398         if (gw->version == 0)
399                 goto fail;
400
401         rfcomm_connect_cb(gw->incoming, gerr, dev);
402         return;
403
404 fail:
405         gateway_close(dev);
406 }
407
408 static void unregister_incoming(gpointer user_data)
409 {
410         struct audio_device *dev = user_data;
411         struct gateway *gw = dev->gateway;
412
413         if (gw->incoming) {
414                 g_io_channel_unref(gw->incoming);
415                 gw->incoming = NULL;
416         }
417 }
418
419 static void rfcomm_incoming_cb(GIOChannel *chan, GError *err,
420                                 gpointer user_data)
421 {
422         struct audio_device *dev = user_data;
423         struct gateway *gw = dev->gateway;
424         uuid_t uuid;
425
426         gw->incoming = g_io_channel_ref(chan);
427
428         sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
429         if (bt_search_service(&dev->src, &dev->dst, &uuid,
430                                                 get_incoming_record_cb, dev,
431                                                 unregister_incoming) == 0)
432                 return;
433
434         unregister_incoming(dev);
435         gateway_close(dev);
436 }
437
438 static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
439 {
440         struct audio_device *dev = user_data;
441         struct gateway *gw = dev->gateway;
442         int ch;
443         sdp_list_t *protos, *classes;
444         uuid_t uuid;
445         GIOChannel *io;
446         GError *gerr = NULL;
447
448         if (err < 0) {
449                 error("Unable to get service record: %s (%d)", strerror(-err),
450                                         -err);
451                 goto fail;
452         }
453
454         if (!recs || !recs->data) {
455                 error("No records found");
456                 err = -EIO;
457                 goto fail;
458         }
459
460         if (sdp_get_service_classes(recs->data, &classes) < 0) {
461                 error("Unable to get service classes from record");
462                 err = -EINVAL;
463                 goto fail;
464         }
465
466         if (sdp_get_access_protos(recs->data, &protos) < 0) {
467                 error("Unable to get access protocols from record");
468                 err = -ENODATA;
469                 goto fail;
470         }
471
472         gw->version = get_remote_profile_version(recs->data);
473         if (gw->version == 0) {
474                 error("Unable to get profile version from record");
475                 err = -EINVAL;
476                 goto fail;
477         }
478
479         memcpy(&uuid, classes->data, sizeof(uuid));
480         sdp_list_free(classes, free);
481
482         if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
483                         uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
484                 sdp_list_free(protos, NULL);
485                 error("Invalid service record or not HFP");
486                 err = -EIO;
487                 goto fail;
488         }
489
490         ch = sdp_get_proto_port(protos, RFCOMM_UUID);
491         sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
492         sdp_list_free(protos, NULL);
493         if (ch <= 0) {
494                 error("Unable to extract RFCOMM channel from service record");
495                 err = -EIO;
496                 goto fail;
497         }
498
499         io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, dev, NULL, &gerr,
500                                 BT_IO_OPT_SOURCE_BDADDR, &dev->src,
501                                 BT_IO_OPT_DEST_BDADDR, &dev->dst,
502                                 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
503                                 BT_IO_OPT_CHANNEL, ch,
504                                 BT_IO_OPT_INVALID);
505         if (!io) {
506                 error("Unable to connect: %s", gerr->message);
507                 goto fail;
508         }
509
510         g_io_channel_unref(io);
511         return;
512
513 fail:
514         if (gw->msg) {
515                 DBusMessage *reply = btd_error_failed(gw->msg,
516                                         gerr ? gerr->message : strerror(-err));
517                 g_dbus_send_message(dev->conn, reply);
518         }
519
520         gateway_close(dev);
521
522         if (gerr)
523                 g_error_free(gerr);
524 }
525
526 static int get_records(struct audio_device *device)
527 {
528         uuid_t uuid;
529
530         change_state(device, GATEWAY_STATE_CONNECTING);
531         sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
532         return bt_search_service(&device->src, &device->dst, &uuid,
533                                 get_record_cb, device, NULL);
534 }
535
536 static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
537                                 void *data)
538 {
539         struct audio_device *au_dev = (struct audio_device *) data;
540         struct gateway *gw = au_dev->gateway;
541         int err;
542
543         if (!gw->agent)
544                 return btd_error_agent_not_available(msg);
545
546         err = get_records(au_dev);
547         if (err < 0)
548                 return btd_error_failed(msg, strerror(-err));
549
550         gw->msg = dbus_message_ref(msg);
551
552         return NULL;
553 }
554
555 int gateway_close(struct audio_device *device)
556 {
557         GError *gerr = NULL;
558         struct gateway *gw = device->gateway;
559         int sock;
560
561         if (gw->rfcomm) {
562                 sock = g_io_channel_unix_get_fd(gw->rfcomm);
563                 shutdown(sock, SHUT_RDWR);
564
565                 g_io_channel_shutdown(gw->rfcomm, TRUE, NULL);
566                 g_io_channel_unref(gw->rfcomm);
567                 gw->rfcomm = NULL;
568         }
569
570         if (gw->sco) {
571                 g_io_channel_shutdown(gw->sco, TRUE, NULL);
572                 g_io_channel_unref(gw->sco);
573                 gw->sco = NULL;
574         }
575
576         change_state(device, GATEWAY_STATE_DISCONNECTED);
577         g_set_error(&gerr, GATEWAY_ERROR,
578                         GATEWAY_ERROR_DISCONNECTED, "Disconnected");
579         run_connect_cb(device, gerr);
580         g_error_free(gerr);
581
582         return 0;
583 }
584
585 static DBusMessage *ag_disconnect(DBusConnection *conn, DBusMessage *msg,
586                                         void *data)
587 {
588         struct audio_device *device = data;
589         struct gateway *gw = device->gateway;
590         DBusMessage *reply = NULL;
591         char gw_addr[18];
592
593         if (!device->conn)
594                 return NULL;
595
596         if (!gw->rfcomm)
597                 return btd_error_not_connected(msg);
598
599         reply = dbus_message_new_method_return(msg);
600         if (!reply)
601                 return NULL;
602
603         gateway_close(device);
604         ba2str(&device->dst, gw_addr);
605         DBG("Disconnected from %s, %s", gw_addr, device->path);
606
607         return reply;
608 }
609
610 static void agent_exited(DBusConnection *conn, void *data)
611 {
612         struct gateway *gateway = data;
613         struct hf_agent *agent = gateway->agent;
614
615         DBG("Agent %s exited", agent->name);
616
617         agent_free(agent);
618         gateway->agent = NULL;
619 }
620
621 static DBusMessage *ag_get_properties(DBusConnection *conn, DBusMessage *msg,
622                                         void *data)
623 {
624         struct audio_device *device = data;
625         struct gateway *gw = device->gateway;
626         DBusMessage *reply;
627         DBusMessageIter iter;
628         DBusMessageIter dict;
629         const char *value;
630
631
632         reply = dbus_message_new_method_return(msg);
633         if (!reply)
634                 return NULL;
635
636         dbus_message_iter_init_append(reply, &iter);
637
638         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
639                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
640                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
641                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
642
643         value = state2str(gw->state);
644         dict_append_entry(&dict, "State",
645                         DBUS_TYPE_STRING, &value);
646
647         dbus_message_iter_close_container(&iter, &dict);
648
649         return reply;
650 }
651
652 static DBusMessage *register_agent(DBusConnection *conn,
653                                         DBusMessage *msg, void *data)
654 {
655         struct audio_device *device = data;
656         struct gateway *gw = device->gateway;
657         struct hf_agent *agent;
658         const char *path, *name;
659
660         if (gw->agent)
661                 return btd_error_already_exists(msg);
662
663         if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
664                                                 DBUS_TYPE_INVALID))
665                 return btd_error_invalid_args(msg);
666
667         name = dbus_message_get_sender(msg);
668         agent = g_new0(struct hf_agent, 1);
669
670         agent->name = g_strdup(name);
671         agent->path = g_strdup(path);
672
673         agent->watch = g_dbus_add_disconnect_watch(conn, name,
674                                                 agent_exited, gw, NULL);
675
676         gw->agent = agent;
677
678         return dbus_message_new_method_return(msg);
679 }
680
681 static DBusMessage *unregister_agent(DBusConnection *conn,
682                                 DBusMessage *msg, void *data)
683 {
684         struct audio_device *device = data;
685         struct gateway *gw = device->gateway;
686         const char *path;
687
688         if (!gw->agent)
689                 goto done;
690
691         if (strcmp(gw->agent->name, dbus_message_get_sender(msg)) != 0)
692                 return btd_error_not_authorized(msg);
693
694         if (!dbus_message_get_args(msg, NULL,
695                                 DBUS_TYPE_OBJECT_PATH, &path,
696                                 DBUS_TYPE_INVALID))
697                 return btd_error_invalid_args(msg);
698
699         if (strcmp(gw->agent->path, path) != 0)
700                 return btd_error_does_not_exist(msg);
701
702         g_dbus_remove_watch(device->conn, gw->agent->watch);
703
704         agent_free(gw->agent);
705         gw->agent = NULL;
706
707 done:
708         return dbus_message_new_method_return(msg);
709 }
710
711 static const GDBusMethodTable gateway_methods[] = {
712         { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, ag_connect) },
713         { GDBUS_ASYNC_METHOD("Disconnect", NULL, NULL, ag_disconnect) },
714         { GDBUS_METHOD("GetProperties",
715                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
716                         ag_get_properties) },
717         { GDBUS_METHOD("RegisterAgent",
718                         GDBUS_ARGS({ "agent", "o" }), NULL, register_agent) },
719         { GDBUS_METHOD("UnregisterAgent",
720                         GDBUS_ARGS({ "agent", "o" }), NULL, unregister_agent) },
721         { }
722 };
723
724 static const GDBusSignalTable gateway_signals[] = {
725         { GDBUS_SIGNAL("PropertyChanged",
726                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
727         { }
728 };
729
730 static void path_unregister(void *data)
731 {
732         struct audio_device *dev = data;
733
734         DBG("Unregistered interface %s on path %s",
735                 AUDIO_GATEWAY_INTERFACE, dev->path);
736
737         gateway_close(dev);
738
739         g_free(dev->gateway);
740         dev->gateway = NULL;
741 }
742
743 void gateway_unregister(struct audio_device *dev)
744 {
745         if (dev->gateway->agent)
746                 agent_disconnect(dev, dev->gateway->agent);
747
748         g_dbus_unregister_interface(dev->conn, dev->path,
749                                                 AUDIO_GATEWAY_INTERFACE);
750 }
751
752 struct gateway *gateway_init(struct audio_device *dev)
753 {
754         if (!g_dbus_register_interface(dev->conn, dev->path,
755                                         AUDIO_GATEWAY_INTERFACE,
756                                         gateway_methods, gateway_signals,
757                                         NULL, dev, path_unregister))
758                 return NULL;
759
760         return g_new0(struct gateway, 1);
761 }
762
763 gboolean gateway_is_connected(struct audio_device *dev)
764 {
765         struct gateway *gw = dev->gateway;
766
767         if (gw->state == GATEWAY_STATE_CONNECTED)
768                 return TRUE;
769
770         return FALSE;
771 }
772
773 gboolean gateway_is_active(struct audio_device *dev)
774 {
775         struct gateway *gw = dev->gateway;
776
777         if (gw->state != GATEWAY_STATE_DISCONNECTED)
778                 return TRUE;
779
780         return FALSE;
781 }
782
783 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
784 {
785         if (!io)
786                 return -EINVAL;
787
788         dev->gateway->rfcomm = g_io_channel_ref(io);
789
790         change_state(dev, GATEWAY_STATE_CONNECTING);
791
792         return 0;
793 }
794
795 int gateway_connect_sco(struct audio_device *dev, GIOChannel *io)
796 {
797         struct gateway *gw = dev->gateway;
798
799         if (gw->sco)
800                 return -EISCONN;
801
802         gw->sco = g_io_channel_ref(io);
803
804         g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
805                                                 (GIOFunc) sco_io_cb, dev);
806
807         change_state(dev, GATEWAY_STATE_PLAYING);
808
809         return 0;
810 }
811
812 void gateway_start_service(struct audio_device *dev)
813 {
814         struct gateway *gw = dev->gateway;
815         GError *err = NULL;
816
817         if (gw->rfcomm == NULL)
818                 return;
819
820         if (!bt_io_accept(gw->rfcomm, rfcomm_incoming_cb, dev, NULL, &err)) {
821                 error("bt_io_accept: %s", err->message);
822                 g_error_free(err);
823                 gateway_close(dev);
824         }
825 }
826
827 static gboolean request_stream_cb(gpointer data)
828 {
829         run_connect_cb(data, NULL);
830         return FALSE;
831 }
832
833 /* These are functions to be called from unix.c for audio system
834  * ifaces (alsa, gstreamer, etc.) */
835 unsigned int gateway_request_stream(struct audio_device *dev,
836                                 gateway_stream_cb_t cb, void *user_data)
837 {
838         struct gateway *gw = dev->gateway;
839         GError *err = NULL;
840         GIOChannel *io;
841
842         if (!gw->rfcomm)
843                 get_records(dev);
844         else if (!gw->sco) {
845                 io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
846                                 BT_IO_OPT_SOURCE_BDADDR, &dev->src,
847                                 BT_IO_OPT_DEST_BDADDR, &dev->dst,
848                                 BT_IO_OPT_SEC_LEVEL, BT_IO_SEC_MEDIUM,
849                                 BT_IO_OPT_INVALID);
850                 if (!io) {
851                         error("%s", err->message);
852                         g_error_free(err);
853                         return 0;
854                 }
855         } else
856                 g_idle_add(request_stream_cb, dev);
857
858         return connect_cb_new(gw, cb, user_data);
859 }
860
861 int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t cb,
862                                 void *user_data)
863 {
864         struct gateway *gw = dev->gateway;
865         unsigned int id;
866
867         id = connect_cb_new(gw, cb, user_data);
868
869         if (!gw->rfcomm)
870                 get_records(dev);
871         else if (cb)
872                 g_idle_add(request_stream_cb, dev);
873
874         return id;
875 }
876
877 gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
878 {
879         struct gateway *gw = dev->gateway;
880         GSList *l;
881         struct connect_cb *cb = NULL;
882
883         for (l = gw->callbacks; l != NULL; l = l->next) {
884                 struct connect_cb *tmp = l->data;
885
886                 if (tmp->id == id) {
887                         cb = tmp;
888                         break;
889                 }
890         }
891
892         if (!cb)
893                 return FALSE;
894
895         gw->callbacks = g_slist_remove(gw->callbacks, cb);
896         g_free(cb);
897
898         gateway_suspend_stream(dev);
899
900         return TRUE;
901 }
902
903 int gateway_get_sco_fd(struct audio_device *dev)
904 {
905         struct gateway *gw = dev->gateway;
906
907         if (!gw || !gw->sco)
908                 return -1;
909
910         return g_io_channel_unix_get_fd(gw->sco);
911 }
912
913 void gateway_suspend_stream(struct audio_device *dev)
914 {
915         GError *gerr = NULL;
916         struct gateway *gw = dev->gateway;
917
918         if (!gw || !gw->sco)
919                 return;
920
921         g_io_channel_shutdown(gw->sco, TRUE, NULL);
922         g_io_channel_unref(gw->sco);
923         gw->sco = NULL;
924         g_set_error(&gerr, GATEWAY_ERROR, GATEWAY_ERROR_SUSPENDED, "Suspended");
925         run_connect_cb(dev, gerr);
926         g_error_free(gerr);
927         change_state(dev, GATEWAY_STATE_CONNECTED);
928 }
929
930 unsigned int gateway_add_state_cb(gateway_state_cb cb, void *user_data)
931 {
932         struct gateway_state_callback *state_cb;
933         static unsigned int id = 0;
934
935         state_cb = g_new(struct gateway_state_callback, 1);
936         state_cb->cb = cb;
937         state_cb->user_data = user_data;
938         state_cb->id = ++id;
939
940         gateway_callbacks = g_slist_append(gateway_callbacks, state_cb);
941
942         return state_cb->id;
943 }
944
945 gboolean gateway_remove_state_cb(unsigned int id)
946 {
947         GSList *l;
948
949         for (l = gateway_callbacks; l != NULL; l = l->next) {
950                 struct gateway_state_callback *cb = l->data;
951                 if (cb && cb->id == id) {
952                         gateway_callbacks = g_slist_remove(gateway_callbacks,
953                                                                         cb);
954                         g_free(cb);
955                         return TRUE;
956                 }
957         }
958
959         return FALSE;
960 }
961
962 gateway_lock_t gateway_get_lock(struct audio_device *dev)
963 {
964         struct gateway *gw = dev->gateway;
965
966         return gw->lock;
967 }
968
969 gboolean gateway_lock(struct audio_device *dev, gateway_lock_t lock)
970 {
971         struct gateway *gw = dev->gateway;
972
973         if (gw->lock & lock)
974                 return FALSE;
975
976         gw->lock |= lock;
977
978         return TRUE;
979 }
980
981 gboolean gateway_unlock(struct audio_device *dev, gateway_lock_t lock)
982 {
983         struct gateway *gw = dev->gateway;
984
985         if (!(gw->lock & lock))
986                 return FALSE;
987
988         gw->lock &= ~lock;
989
990         if (gw->lock)
991                 return TRUE;
992
993         if (gw->state == GATEWAY_STATE_PLAYING)
994                 gateway_suspend_stream(dev);
995
996         return TRUE;
997 }