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 "glib-helper.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 #ifndef DBUS_TYPE_UNIX_FD
54 #define DBUS_TYPE_UNIX_FD -1
55 #endif
56
57 struct hf_agent {
58 char *name; /* Bus id */
59 char *path; /* D-Bus path */
60 guint watch; /* Disconnect watch */
61 };
62
63 struct gateway {
64 gateway_state_t state;
65 GIOChannel *rfcomm;
66 GIOChannel *sco;
67 gateway_stream_cb_t sco_start_cb;
68 void *sco_start_cb_data;
69 struct hf_agent *agent;
70 DBusMessage *msg;
71 };
72
73 int gateway_close(struct audio_device *device);
74
state2str(gateway_state_t state)75 static const char *state2str(gateway_state_t state)
76 {
77 switch (state) {
78 case GATEWAY_STATE_DISCONNECTED:
79 return "disconnected";
80 case GATEWAY_STATE_CONNECTING:
81 return "connecting";
82 case GATEWAY_STATE_CONNECTED:
83 return "connected";
84 case GATEWAY_STATE_PLAYING:
85 return "playing";
86 default:
87 return "";
88 }
89 }
90
agent_free(struct hf_agent * agent)91 static void agent_free(struct hf_agent *agent)
92 {
93 if (!agent)
94 return;
95
96 g_free(agent->name);
97 g_free(agent->path);
98 g_free(agent);
99 }
100
change_state(struct audio_device * dev,gateway_state_t new_state)101 static void change_state(struct audio_device *dev, gateway_state_t new_state)
102 {
103 struct gateway *gw = dev->gateway;
104 const char *val;
105
106 if (gw->state == new_state)
107 return;
108
109 val = state2str(new_state);
110 gw->state = new_state;
111
112 emit_property_changed(dev->conn, dev->path,
113 AUDIO_GATEWAY_INTERFACE, "State",
114 DBUS_TYPE_STRING, &val);
115 }
116
agent_disconnect(struct audio_device * dev,struct hf_agent * agent)117 static void agent_disconnect(struct audio_device *dev, struct hf_agent *agent)
118 {
119 DBusMessage *msg;
120
121 msg = dbus_message_new_method_call(agent->name, agent->path,
122 "org.bluez.HandsfreeAgent", "Release");
123
124 g_dbus_send_message(dev->conn, msg);
125 }
126
agent_sendfd(struct hf_agent * agent,int fd,DBusPendingCallNotifyFunction notify,void * data)127 static gboolean agent_sendfd(struct hf_agent *agent, int fd,
128 DBusPendingCallNotifyFunction notify, void *data)
129 {
130 struct audio_device *dev = data;
131 DBusMessage *msg;
132 DBusPendingCall *call;
133
134 msg = dbus_message_new_method_call(agent->name, agent->path,
135 "org.bluez.HandsfreeAgent", "NewConnection");
136
137 dbus_message_append_args(msg, DBUS_TYPE_UNIX_FD, &fd,
138 DBUS_TYPE_INVALID);
139
140 if (dbus_connection_send_with_reply(dev->conn, msg, &call, -1) == FALSE)
141 return FALSE;
142
143 dbus_pending_call_set_notify(call, notify, dev, NULL);
144 dbus_pending_call_unref(call);
145
146 return TRUE;
147 }
148
sco_io_cb(GIOChannel * chan,GIOCondition cond,struct audio_device * dev)149 static gboolean sco_io_cb(GIOChannel *chan, GIOCondition cond,
150 struct audio_device *dev)
151 {
152 struct gateway *gw = dev->gateway;
153
154 if (cond & G_IO_NVAL)
155 return FALSE;
156
157 if (cond & (G_IO_ERR | G_IO_HUP)) {
158 DBG("sco connection is released");
159 g_io_channel_shutdown(gw->sco, TRUE, NULL);
160 g_io_channel_unref(gw->sco);
161 gw->sco = NULL;
162 change_state(dev, GATEWAY_STATE_CONNECTED);
163 return FALSE;
164 }
165
166 return TRUE;
167 }
168
sco_connect_cb(GIOChannel * chan,GError * err,gpointer user_data)169 static void sco_connect_cb(GIOChannel *chan, GError *err, gpointer user_data)
170 {
171 struct audio_device *dev = (struct audio_device *) user_data;
172 struct gateway *gw = dev->gateway;
173
174 DBG("at the begin of sco_connect_cb() in gateway.c");
175
176 gw->sco = g_io_channel_ref(chan);
177
178 if (gw->sco_start_cb)
179 gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
180
181 if (err) {
182 error("sco_connect_cb(): %s", err->message);
183 gateway_close(dev);
184 return;
185 }
186
187 g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
188 (GIOFunc) sco_io_cb, dev);
189 }
190
newconnection_reply(DBusPendingCall * call,void * data)191 static void newconnection_reply(DBusPendingCall *call, void *data)
192 {
193 struct audio_device *dev = data;
194 DBusMessage *reply = dbus_pending_call_steal_reply(call);
195 DBusError derr;
196
197 if (!dev->gateway->rfcomm) {
198 DBG("RFCOMM disconnected from server before agent reply");
199 goto done;
200 }
201
202 dbus_error_init(&derr);
203 if (!dbus_set_error_from_message(&derr, reply)) {
204 DBG("Agent reply: file descriptor passed successfully");
205 change_state(dev, GATEWAY_STATE_CONNECTED);
206 goto done;
207 }
208
209 DBG("Agent reply: %s", derr.message);
210
211 dbus_error_free(&derr);
212 gateway_close(dev);
213
214 done:
215 dbus_message_unref(reply);
216 }
217
rfcomm_connect_cb(GIOChannel * chan,GError * err,gpointer user_data)218 static void rfcomm_connect_cb(GIOChannel *chan, GError *err,
219 gpointer user_data)
220 {
221 struct audio_device *dev = user_data;
222 struct gateway *gw = dev->gateway;
223 DBusMessage *reply;
224 int sk, ret;
225
226 if (err) {
227 error("connect(): %s", err->message);
228 if (gw->sco_start_cb)
229 gw->sco_start_cb(dev, err, gw->sco_start_cb_data);
230 goto fail;
231 }
232
233 if (!gw->agent) {
234 error("Handsfree Agent not registered");
235 goto fail;
236 }
237
238 sk = g_io_channel_unix_get_fd(chan);
239
240 gw->rfcomm = g_io_channel_ref(chan);
241
242 ret = agent_sendfd(gw->agent, sk, newconnection_reply, dev);
243
244 if (!gw->msg)
245 return;
246
247 if (ret)
248 reply = dbus_message_new_method_return(gw->msg);
249 else
250 reply = btd_error_failed(gw->msg, "Can't pass file descriptor");
251
252 g_dbus_send_message(dev->conn, reply);
253
254 return;
255
256 fail:
257 if (gw->msg) {
258 DBusMessage *reply;
259 reply = btd_error_failed(gw->msg, "Connect failed");
260 g_dbus_send_message(dev->conn, reply);
261 }
262
263 change_state(dev, GATEWAY_STATE_DISCONNECTED);
264 }
265
get_record_cb(sdp_list_t * recs,int err,gpointer user_data)266 static void get_record_cb(sdp_list_t *recs, int err, gpointer user_data)
267 {
268 struct audio_device *dev = user_data;
269 struct gateway *gw = dev->gateway;
270 int ch;
271 sdp_list_t *protos, *classes;
272 uuid_t uuid;
273 GIOChannel *io;
274 GError *gerr = NULL;
275
276 if (err < 0) {
277 error("Unable to get service record: %s (%d)", strerror(-err),
278 -err);
279 goto fail;
280 }
281
282 if (!recs || !recs->data) {
283 error("No records found");
284 err = -EIO;
285 goto fail;
286 }
287
288 if (sdp_get_service_classes(recs->data, &classes) < 0) {
289 error("Unable to get service classes from record");
290 err = -EINVAL;
291 goto fail;
292 }
293
294 if (sdp_get_access_protos(recs->data, &protos) < 0) {
295 error("Unable to get access protocols from record");
296 err = -ENODATA;
297 goto fail;
298 }
299
300 memcpy(&uuid, classes->data, sizeof(uuid));
301 sdp_list_free(classes, free);
302
303 if (!sdp_uuid128_to_uuid(&uuid) || uuid.type != SDP_UUID16 ||
304 uuid.value.uuid16 != HANDSFREE_AGW_SVCLASS_ID) {
305 sdp_list_free(protos, NULL);
306 error("Invalid service record or not HFP");
307 err = -EIO;
308 goto fail;
309 }
310
311 ch = sdp_get_proto_port(protos, RFCOMM_UUID);
312 sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free, NULL);
313 sdp_list_free(protos, NULL);
314 if (ch <= 0) {
315 error("Unable to extract RFCOMM channel from service record");
316 err = -EIO;
317 goto fail;
318 }
319
320 io = bt_io_connect(BT_IO_RFCOMM, rfcomm_connect_cb, dev, NULL, &gerr,
321 BT_IO_OPT_SOURCE_BDADDR, &dev->src,
322 BT_IO_OPT_DEST_BDADDR, &dev->dst,
323 BT_IO_OPT_CHANNEL, ch,
324 BT_IO_OPT_INVALID);
325 if (!io) {
326 error("Unable to connect: %s", gerr->message);
327 gateway_close(dev);
328 goto fail;
329 }
330
331 g_io_channel_unref(io);
332
333 change_state(dev, GATEWAY_STATE_CONNECTING);
334 return;
335
336 fail:
337 if (gw->msg) {
338 DBusMessage *reply = btd_error_failed(gw->msg,
339 gerr ? gerr->message : strerror(-err));
340 g_dbus_send_message(dev->conn, reply);
341 }
342
343 change_state(dev, GATEWAY_STATE_DISCONNECTED);
344
345 if (!gerr)
346 g_set_error(&gerr, BT_IO_ERROR, BT_IO_ERROR_FAILED,
347 "connect: %s (%d)", strerror(-err), -err);
348
349 if (gw->sco_start_cb)
350 gw->sco_start_cb(dev, gerr, gw->sco_start_cb_data);
351
352 g_error_free(gerr);
353 }
354
get_records(struct audio_device * device)355 static int get_records(struct audio_device *device)
356 {
357 uuid_t uuid;
358
359 sdp_uuid16_create(&uuid, HANDSFREE_AGW_SVCLASS_ID);
360 return bt_search_service(&device->src, &device->dst, &uuid,
361 get_record_cb, device, NULL);
362 }
363
ag_connect(DBusConnection * conn,DBusMessage * msg,void * data)364 static DBusMessage *ag_connect(DBusConnection *conn, DBusMessage *msg,
365 void *data)
366 {
367 struct audio_device *au_dev = (struct audio_device *) data;
368 struct gateway *gw = au_dev->gateway;
369 int err;
370
371 if (!gw->agent)
372 return btd_error_agent_not_available(msg);
373
374 err = get_records(au_dev);
375 if (err < 0)
376 return btd_error_failed(msg, strerror(-err));
377
378 gw->msg = dbus_message_ref(msg);
379
380 return NULL;
381 }
382
gateway_close(struct audio_device * device)383 int gateway_close(struct audio_device *device)
384 {
385 struct gateway *gw = device->gateway;
386 int sock;
387
388 if (gw->rfcomm) {
389 sock = g_io_channel_unix_get_fd(gw->rfcomm);
390 shutdown(sock, SHUT_RDWR);
391
392 g_io_channel_shutdown(gw->rfcomm, TRUE, NULL);
393 g_io_channel_unref(gw->rfcomm);
394 gw->rfcomm = NULL;
395 }
396
397 if (gw->sco) {
398 g_io_channel_shutdown(gw->sco, TRUE, NULL);
399 g_io_channel_unref(gw->sco);
400 gw->sco = NULL;
401 gw->sco_start_cb = NULL;
402 gw->sco_start_cb_data = NULL;
403 }
404
405 change_state(device, GATEWAY_STATE_DISCONNECTED);
406
407 return 0;
408 }
409
ag_disconnect(DBusConnection * conn,DBusMessage * msg,void * data)410 static DBusMessage *ag_disconnect(DBusConnection *conn, DBusMessage *msg,
411 void *data)
412 {
413 struct audio_device *device = data;
414 struct gateway *gw = device->gateway;
415 DBusMessage *reply = NULL;
416 char gw_addr[18];
417
418 if (!device->conn)
419 return NULL;
420
421 reply = dbus_message_new_method_return(msg);
422 if (!reply)
423 return NULL;
424
425 if (!gw->rfcomm)
426 return btd_error_not_connected(msg);
427
428 gateway_close(device);
429 ba2str(&device->dst, gw_addr);
430 DBG("Disconnected from %s, %s", gw_addr, device->path);
431
432 return reply;
433 }
434
agent_exited(DBusConnection * conn,void * data)435 static void agent_exited(DBusConnection *conn, void *data)
436 {
437 struct gateway *gateway = data;
438 struct hf_agent *agent = gateway->agent;
439
440 DBG("Agent %s exited", agent->name);
441
442 agent_free(agent);
443 gateway->agent = NULL;
444 }
445
ag_get_properties(DBusConnection * conn,DBusMessage * msg,void * data)446 static DBusMessage *ag_get_properties(DBusConnection *conn, DBusMessage *msg,
447 void *data)
448 {
449 struct audio_device *device = data;
450 struct gateway *gw = device->gateway;
451 DBusMessage *reply;
452 DBusMessageIter iter;
453 DBusMessageIter dict;
454 const char *value;
455
456
457 reply = dbus_message_new_method_return(msg);
458 if (!reply)
459 return NULL;
460
461 dbus_message_iter_init_append(reply, &iter);
462
463 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
464 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
465 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
466 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
467
468 value = state2str(gw->state);
469 dict_append_entry(&dict, "State",
470 DBUS_TYPE_STRING, &value);
471
472 dbus_message_iter_close_container(&iter, &dict);
473
474 return reply;
475 }
476
register_agent(DBusConnection * conn,DBusMessage * msg,void * data)477 static DBusMessage *register_agent(DBusConnection *conn,
478 DBusMessage *msg, void *data)
479 {
480 struct audio_device *device = data;
481 struct gateway *gw = device->gateway;
482 struct hf_agent *agent;
483 const char *path, *name;
484
485 if (gw->agent)
486 return btd_error_already_exists(msg);
487
488 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
489 DBUS_TYPE_INVALID))
490 return btd_error_invalid_args(msg);
491
492 name = dbus_message_get_sender(msg);
493 agent = g_new0(struct hf_agent, 1);
494
495 agent->name = g_strdup(name);
496 agent->path = g_strdup(path);
497
498 agent->watch = g_dbus_add_disconnect_watch(conn, name,
499 agent_exited, gw, NULL);
500
501 gw->agent = agent;
502
503 return dbus_message_new_method_return(msg);
504 }
505
unregister_agent(DBusConnection * conn,DBusMessage * msg,void * data)506 static DBusMessage *unregister_agent(DBusConnection *conn,
507 DBusMessage *msg, void *data)
508 {
509 struct audio_device *device = data;
510 struct gateway *gw = device->gateway;
511 const char *path;
512
513 if (!gw->agent)
514 goto done;
515
516 if (strcmp(gw->agent->name, dbus_message_get_sender(msg)) != 0)
517 return btd_error_not_authorized(msg);
518
519 if (!dbus_message_get_args(msg, NULL,
520 DBUS_TYPE_OBJECT_PATH, &path,
521 DBUS_TYPE_INVALID))
522 return btd_error_invalid_args(msg);
523
524 if (strcmp(gw->agent->path, path) != 0)
525 return btd_error_does_not_exist(msg);
526
527 g_dbus_remove_watch(device->conn, gw->agent->watch);
528
529 agent_free(gw->agent);
530 gw->agent = NULL;
531
532 done:
533 return dbus_message_new_method_return(msg);
534 }
535
536 static GDBusMethodTable gateway_methods[] = {
537 { "Connect", "", "", ag_connect, G_DBUS_METHOD_FLAG_ASYNC },
538 { "Disconnect", "", "", ag_disconnect, G_DBUS_METHOD_FLAG_ASYNC },
539 { "GetProperties", "", "a{sv}", ag_get_properties },
540 { "RegisterAgent", "o", "", register_agent },
541 { "UnregisterAgent", "o", "", unregister_agent },
542 { NULL, NULL, NULL, NULL }
543 };
544
545 static GDBusSignalTable gateway_signals[] = {
546 { "PropertyChanged", "sv" },
547 { NULL, NULL }
548 };
549
path_unregister(void * data)550 static void path_unregister(void *data)
551 {
552 struct audio_device *dev = data;
553
554 DBG("Unregistered interface %s on path %s",
555 AUDIO_GATEWAY_INTERFACE, dev->path);
556
557 gateway_close(dev);
558
559 g_free(dev->gateway);
560 dev->gateway = NULL;
561 }
562
gateway_unregister(struct audio_device * dev)563 void gateway_unregister(struct audio_device *dev)
564 {
565 if (dev->gateway->agent)
566 agent_disconnect(dev, dev->gateway->agent);
567
568 g_dbus_unregister_interface(dev->conn, dev->path,
569 AUDIO_GATEWAY_INTERFACE);
570 }
571
gateway_init(struct audio_device * dev)572 struct gateway *gateway_init(struct audio_device *dev)
573 {
574 if (DBUS_TYPE_UNIX_FD < 0)
575 return NULL;
576
577 if (!g_dbus_register_interface(dev->conn, dev->path,
578 AUDIO_GATEWAY_INTERFACE,
579 gateway_methods, gateway_signals,
580 NULL, dev, path_unregister))
581 return NULL;
582
583 return g_new0(struct gateway, 1);
584
585 }
586
gateway_is_connected(struct audio_device * dev)587 gboolean gateway_is_connected(struct audio_device *dev)
588 {
589 return (dev && dev->gateway &&
590 dev->gateway->state == GATEWAY_STATE_CONNECTED);
591 }
592
gateway_connect_rfcomm(struct audio_device * dev,GIOChannel * io)593 int gateway_connect_rfcomm(struct audio_device *dev, GIOChannel *io)
594 {
595 if (!io)
596 return -EINVAL;
597
598 dev->gateway->rfcomm = g_io_channel_ref(io);
599
600 return 0;
601 }
602
gateway_connect_sco(struct audio_device * dev,GIOChannel * io)603 int gateway_connect_sco(struct audio_device *dev, GIOChannel *io)
604 {
605 struct gateway *gw = dev->gateway;
606
607 if (gw->sco)
608 return -EISCONN;
609
610 gw->sco = g_io_channel_ref(io);
611
612 g_io_add_watch(gw->sco, G_IO_ERR | G_IO_HUP | G_IO_NVAL,
613 (GIOFunc) sco_io_cb, dev);
614
615 change_state(dev, GATEWAY_STATE_PLAYING);
616
617 return 0;
618 }
619
gateway_start_service(struct audio_device * dev)620 void gateway_start_service(struct audio_device *dev)
621 {
622 struct gateway *gw = dev->gateway;
623 GError *err = NULL;
624
625 if (gw->rfcomm == NULL)
626 return;
627
628 if (!bt_io_accept(gw->rfcomm, rfcomm_connect_cb, dev, NULL, &err)) {
629 error("bt_io_accept: %s", err->message);
630 g_error_free(err);
631 }
632 }
633
634 /* These are functions to be called from unix.c for audio system
635 * ifaces (alsa, gstreamer, etc.) */
gateway_request_stream(struct audio_device * dev,gateway_stream_cb_t cb,void * user_data)636 gboolean gateway_request_stream(struct audio_device *dev,
637 gateway_stream_cb_t cb, void *user_data)
638 {
639 struct gateway *gw = dev->gateway;
640 GError *err = NULL;
641 GIOChannel *io;
642
643 if (!gw->rfcomm) {
644 gw->sco_start_cb = cb;
645 gw->sco_start_cb_data = user_data;
646 get_records(dev);
647 } else if (!gw->sco) {
648 gw->sco_start_cb = cb;
649 gw->sco_start_cb_data = user_data;
650 io = bt_io_connect(BT_IO_SCO, sco_connect_cb, dev, NULL, &err,
651 BT_IO_OPT_SOURCE_BDADDR, &dev->src,
652 BT_IO_OPT_DEST_BDADDR, &dev->dst,
653 BT_IO_OPT_INVALID);
654 if (!io) {
655 error("%s", err->message);
656 g_error_free(err);
657 return FALSE;
658 }
659 } else if (cb)
660 cb(dev, err, user_data);
661
662 return TRUE;
663 }
664
gateway_config_stream(struct audio_device * dev,gateway_stream_cb_t sco_cb,void * user_data)665 int gateway_config_stream(struct audio_device *dev, gateway_stream_cb_t sco_cb,
666 void *user_data)
667 {
668 struct gateway *gw = dev->gateway;
669
670 if (!gw->rfcomm) {
671 gw->sco_start_cb = sco_cb;
672 gw->sco_start_cb_data = user_data;
673 return get_records(dev);
674 }
675
676 if (sco_cb)
677 sco_cb(dev, NULL, user_data);
678
679 return 0;
680 }
681
gateway_cancel_stream(struct audio_device * dev,unsigned int id)682 gboolean gateway_cancel_stream(struct audio_device *dev, unsigned int id)
683 {
684 gateway_close(dev);
685 return TRUE;
686 }
687
gateway_get_sco_fd(struct audio_device * dev)688 int gateway_get_sco_fd(struct audio_device *dev)
689 {
690 struct gateway *gw = dev->gateway;
691
692 if (!gw || !gw->sco)
693 return -1;
694
695 return g_io_channel_unix_get_fd(gw->sco);
696 }
697
gateway_suspend_stream(struct audio_device * dev)698 void gateway_suspend_stream(struct audio_device *dev)
699 {
700 struct gateway *gw = dev->gateway;
701
702 if (!gw || !gw->sco)
703 return;
704
705 g_io_channel_shutdown(gw->sco, TRUE, NULL);
706 g_io_channel_unref(gw->sco);
707 gw->sco = NULL;
708 gw->sco_start_cb = NULL;
709 gw->sco_start_cb_data = NULL;
710 change_state(dev, GATEWAY_STATE_CONNECTED);
711 }
712