3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2006-2007 Nokia Corporation
6 * Copyright (C) 2004-2009 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
33 #ifdef __TIZEN_PATCH__
34 #include <sys/types.h>
35 #include <sys/xattr.h>
36 #include <linux/xattr.h>
39 #include "lib/bluetooth.h"
43 #include "gdbus/gdbus.h"
45 #include "src/adapter.h"
46 #include "src/device.h"
47 #include "src/dbus-common.h"
50 #include "src/error.h"
51 #include "src/shared/queue.h"
55 #include "transport.h"
61 #define MEDIA_TRANSPORT_INTERFACE "org.bluez.MediaTransport1"
64 TRANSPORT_STATE_IDLE, /* Not acquired and suspended */
65 TRANSPORT_STATE_PENDING, /* Playing but not acquired */
66 TRANSPORT_STATE_REQUESTING, /* Acquire in progress */
67 TRANSPORT_STATE_ACTIVE, /* Acquired and playing */
68 TRANSPORT_STATE_SUSPENDING, /* Release in progress */
71 static char *str_state[] = {
72 "TRANSPORT_STATE_IDLE",
73 "TRANSPORT_STATE_PENDING",
74 "TRANSPORT_STATE_REQUESTING",
75 "TRANSPORT_STATE_ACTIVE",
76 "TRANSPORT_STATE_SUSPENDING",
79 struct media_request {
85 struct media_transport *transport;
86 struct media_request *pending;
91 struct a2dp_transport {
92 struct avdtp *session;
97 struct media_transport {
98 char *path; /* Transport object path */
99 struct btd_device *device; /* Transport device */
100 struct media_endpoint *endpoint; /* Transport endpoint */
101 struct media_owner *owner; /* Transport owner */
102 uint8_t *configuration; /* Transport configuration */
103 int size; /* Transport configuration size */
104 int fd; /* Transport file descriptor */
105 uint16_t imtu; /* Transport input mtu */
106 uint16_t omtu; /* Transport output mtu */
107 transport_state_t state;
111 guint (*resume) (struct media_transport *transport,
112 struct media_owner *owner);
113 guint (*suspend) (struct media_transport *transport,
114 struct media_owner *owner);
115 void (*cancel) (struct media_transport *transport,
117 GDestroyNotify destroy;
121 static GSList *transports = NULL;
123 static const char *state2str(transport_state_t state)
126 case TRANSPORT_STATE_IDLE:
127 case TRANSPORT_STATE_REQUESTING:
129 case TRANSPORT_STATE_PENDING:
131 case TRANSPORT_STATE_ACTIVE:
132 case TRANSPORT_STATE_SUSPENDING:
139 static gboolean state_in_use(transport_state_t state)
142 case TRANSPORT_STATE_IDLE:
143 case TRANSPORT_STATE_PENDING:
145 case TRANSPORT_STATE_REQUESTING:
146 case TRANSPORT_STATE_ACTIVE:
147 case TRANSPORT_STATE_SUSPENDING:
154 static void transport_set_state(struct media_transport *transport,
155 transport_state_t state)
157 transport_state_t old_state = transport->state;
160 if (old_state == state)
163 transport->state = state;
165 DBG("State changed %s: %s -> %s", transport->path, str_state[old_state],
168 str = state2str(state);
170 if (g_strcmp0(str, state2str(old_state)) != 0)
171 g_dbus_emit_property_changed(btd_get_dbus_connection(),
173 MEDIA_TRANSPORT_INTERFACE,
177 void media_transport_destroy(struct media_transport *transport)
181 if (transport->sink_watch)
182 sink_remove_state_cb(transport->sink_watch);
184 if (transport->source_watch)
185 source_remove_state_cb(transport->source_watch);
187 path = g_strdup(transport->path);
188 g_dbus_unregister_interface(btd_get_dbus_connection(), path,
189 MEDIA_TRANSPORT_INTERFACE);
194 static struct media_request *media_request_create(DBusMessage *msg, guint id)
196 struct media_request *req;
198 req = g_new0(struct media_request, 1);
199 req->msg = dbus_message_ref(msg);
202 DBG("Request created: method=%s id=%u", dbus_message_get_member(msg),
208 static void media_request_reply(struct media_request *req, int err)
212 DBG("Request %s Reply %s", dbus_message_get_member(req->msg),
216 reply = g_dbus_create_reply(req->msg, DBUS_TYPE_INVALID);
218 reply = g_dbus_create_error(req->msg,
219 ERROR_INTERFACE ".Failed",
220 "%s", strerror(err));
222 g_dbus_send_message(btd_get_dbus_connection(), reply);
225 static void media_owner_remove(struct media_owner *owner)
227 struct media_transport *transport = owner->transport;
228 struct media_request *req = owner->pending;
233 DBG("Owner %s Request %s", owner->name,
234 dbus_message_get_member(req->msg));
237 transport->cancel(transport, req->id);
239 owner->pending = NULL;
241 dbus_message_unref(req->msg);
246 static void media_owner_free(struct media_owner *owner)
248 DBG("Owner %s", owner->name);
250 media_owner_remove(owner);
256 static void media_transport_remove_owner(struct media_transport *transport)
258 struct media_owner *owner = transport->owner;
260 DBG("Transport %s Owner %s", transport->path, owner->name);
262 /* Reply if owner has a pending request */
264 media_request_reply(owner->pending, EIO);
266 transport->owner = NULL;
269 g_dbus_remove_watch(btd_get_dbus_connection(), owner->watch);
271 media_owner_free(owner);
273 if (state_in_use(transport->state))
274 transport->suspend(transport, NULL);
277 static gboolean media_transport_set_fd(struct media_transport *transport,
278 int fd, uint16_t imtu, uint16_t omtu)
280 if (transport->fd == fd)
284 transport->imtu = imtu;
285 transport->omtu = omtu;
287 info("%s: fd(%d) ready", transport->path, fd);
292 static void a2dp_resume_complete(struct avdtp *session,
293 struct avdtp_error *err, void *user_data)
295 struct media_owner *owner = user_data;
296 struct media_request *req = owner->pending;
297 struct media_transport *transport = owner->transport;
298 struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
299 struct avdtp_stream *stream;
309 stream = a2dp_sep_get_stream(sep);
313 ret = avdtp_stream_get_transport(stream, &fd, &imtu, &omtu, NULL);
317 media_transport_set_fd(transport, fd, imtu, omtu);
319 #ifdef __TIZEN_PATCH__
321 DBG("Set smack label!");
324 ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, "System", sizeof("System"), 0);
326 DBG("Set attr error: %d", ret);
329 ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, "System", sizeof("System"), 0);
331 DBG("Set attr error: %d", ret);
336 ret = g_dbus_send_reply(btd_get_dbus_connection(), req->msg,
337 DBUS_TYPE_UNIX_FD, &fd,
338 DBUS_TYPE_UINT16, &imtu,
339 DBUS_TYPE_UINT16, &omtu,
344 media_owner_remove(owner);
346 transport_set_state(transport, TRANSPORT_STATE_ACTIVE);
351 media_transport_remove_owner(transport);
354 static guint resume_a2dp(struct media_transport *transport,
355 struct media_owner *owner)
357 struct a2dp_transport *a2dp = transport->data;
358 struct media_endpoint *endpoint = transport->endpoint;
359 struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
362 if (a2dp->session == NULL) {
363 a2dp->session = a2dp_avdtp_get(transport->device);
364 if (a2dp->session == NULL)
368 if (state_in_use(transport->state))
369 return a2dp_resume(a2dp->session, sep, a2dp_resume_complete,
372 if (a2dp_sep_lock(sep, a2dp->session) == FALSE)
375 id = a2dp_resume(a2dp->session, sep, a2dp_resume_complete, owner);
378 a2dp_sep_unlock(sep, a2dp->session);
382 if (transport->state == TRANSPORT_STATE_IDLE)
383 transport_set_state(transport, TRANSPORT_STATE_REQUESTING);
388 static void a2dp_suspend_complete(struct avdtp *session,
389 struct avdtp_error *err, void *user_data)
391 struct media_owner *owner = user_data;
392 struct media_transport *transport = owner->transport;
393 struct a2dp_transport *a2dp = transport->data;
394 struct a2dp_sep *sep = media_endpoint_get_sep(transport->endpoint);
396 /* Release always succeeds */
397 if (owner->pending) {
398 owner->pending->id = 0;
399 media_request_reply(owner->pending, 0);
400 media_owner_remove(owner);
403 a2dp_sep_unlock(sep, a2dp->session);
404 transport_set_state(transport, TRANSPORT_STATE_IDLE);
405 media_transport_remove_owner(transport);
408 static guint suspend_a2dp(struct media_transport *transport,
409 struct media_owner *owner)
411 struct a2dp_transport *a2dp = transport->data;
412 struct media_endpoint *endpoint = transport->endpoint;
413 struct a2dp_sep *sep = media_endpoint_get_sep(endpoint);
416 return a2dp_suspend(a2dp->session, sep, a2dp_suspend_complete,
419 transport_set_state(transport, TRANSPORT_STATE_IDLE);
420 a2dp_sep_unlock(sep, a2dp->session);
425 static void cancel_a2dp(struct media_transport *transport, guint id)
430 static void media_owner_exit(DBusConnection *connection, void *user_data)
432 struct media_owner *owner = user_data;
436 media_owner_remove(owner);
438 media_transport_remove_owner(owner->transport);
441 static void media_transport_set_owner(struct media_transport *transport,
442 struct media_owner *owner)
444 DBG("Transport %s Owner %s", transport->path, owner->name);
445 transport->owner = owner;
446 owner->transport = transport;
447 owner->watch = g_dbus_add_disconnect_watch(btd_get_dbus_connection(),
453 static struct media_owner *media_owner_create(DBusMessage *msg)
455 struct media_owner *owner;
457 owner = g_new0(struct media_owner, 1);
458 owner->name = g_strdup(dbus_message_get_sender(msg));
460 DBG("Owner created: sender=%s", owner->name);
465 static void media_owner_add(struct media_owner *owner,
466 struct media_request *req)
468 DBG("Owner %s Request %s", owner->name,
469 dbus_message_get_member(req->msg));
471 owner->pending = req;
474 static DBusMessage *acquire(DBusConnection *conn, DBusMessage *msg,
477 struct media_transport *transport = data;
478 struct media_owner *owner;
479 struct media_request *req;
482 if (transport->owner != NULL)
483 return btd_error_not_authorized(msg);
485 if (transport->state >= TRANSPORT_STATE_REQUESTING)
486 return btd_error_not_authorized(msg);
488 owner = media_owner_create(msg);
489 id = transport->resume(transport, owner);
491 media_owner_free(owner);
492 return btd_error_not_authorized(msg);
495 req = media_request_create(msg, id);
496 media_owner_add(owner, req);
497 media_transport_set_owner(transport, owner);
502 static DBusMessage *try_acquire(DBusConnection *conn, DBusMessage *msg,
505 struct media_transport *transport = data;
506 struct media_owner *owner;
507 struct media_request *req;
510 if (transport->owner != NULL)
511 return btd_error_not_authorized(msg);
513 if (transport->state >= TRANSPORT_STATE_REQUESTING)
514 return btd_error_not_authorized(msg);
516 if (transport->state != TRANSPORT_STATE_PENDING)
517 return btd_error_not_available(msg);
519 owner = media_owner_create(msg);
520 id = transport->resume(transport, owner);
522 media_owner_free(owner);
523 return btd_error_not_authorized(msg);
526 req = media_request_create(msg, id);
527 media_owner_add(owner, req);
528 media_transport_set_owner(transport, owner);
533 static DBusMessage *release(DBusConnection *conn, DBusMessage *msg,
536 struct media_transport *transport = data;
537 struct media_owner *owner = transport->owner;
539 struct media_request *req;
542 sender = dbus_message_get_sender(msg);
544 if (owner == NULL || g_strcmp0(owner->name, sender) != 0)
545 return btd_error_not_authorized(msg);
547 if (owner->pending) {
550 member = dbus_message_get_member(owner->pending->msg);
551 /* Cancel Acquire request if that exist */
552 if (g_str_equal(member, "Acquire"))
553 media_owner_remove(owner);
555 return btd_error_in_progress(msg);
558 transport_set_state(transport, TRANSPORT_STATE_SUSPENDING);
560 id = transport->suspend(transport, owner);
562 media_transport_remove_owner(transport);
563 return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
566 req = media_request_create(msg, id);
567 media_owner_add(owner, req);
572 static gboolean get_device(const GDBusPropertyTable *property,
573 DBusMessageIter *iter, void *data)
575 struct media_transport *transport = data;
576 const char *path = device_get_path(transport->device);
578 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
583 static gboolean get_uuid(const GDBusPropertyTable *property,
584 DBusMessageIter *iter, void *data)
586 struct media_transport *transport = data;
587 const char *uuid = media_endpoint_get_uuid(transport->endpoint);
589 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &uuid);
594 static gboolean get_codec(const GDBusPropertyTable *property,
595 DBusMessageIter *iter, void *data)
597 struct media_transport *transport = data;
598 uint8_t codec = media_endpoint_get_codec(transport->endpoint);
600 dbus_message_iter_append_basic(iter, DBUS_TYPE_BYTE, &codec);
605 static gboolean get_configuration(const GDBusPropertyTable *property,
606 DBusMessageIter *iter, void *data)
608 struct media_transport *transport = data;
609 DBusMessageIter array;
611 dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
612 DBUS_TYPE_BYTE_AS_STRING, &array);
614 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
615 &transport->configuration,
618 dbus_message_iter_close_container(iter, &array);
623 static gboolean get_state(const GDBusPropertyTable *property,
624 DBusMessageIter *iter, void *data)
626 struct media_transport *transport = data;
627 const char *state = state2str(transport->state);
629 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &state);
634 static gboolean delay_exists(const GDBusPropertyTable *property, void *data)
636 struct media_transport *transport = data;
637 struct a2dp_transport *a2dp = transport->data;
639 return a2dp->delay != 0;
642 static gboolean get_delay(const GDBusPropertyTable *property,
643 DBusMessageIter *iter, void *data)
645 struct media_transport *transport = data;
646 struct a2dp_transport *a2dp = transport->data;
648 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &a2dp->delay);
653 static gboolean volume_exists(const GDBusPropertyTable *property, void *data)
655 struct media_transport *transport = data;
656 struct a2dp_transport *a2dp = transport->data;
658 return a2dp->volume <= 127;
661 static gboolean get_volume(const GDBusPropertyTable *property,
662 DBusMessageIter *iter, void *data)
664 struct media_transport *transport = data;
665 struct a2dp_transport *a2dp = transport->data;
667 dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT16, &a2dp->volume);
672 static void set_volume(const GDBusPropertyTable *property,
673 DBusMessageIter *iter, GDBusPendingPropertySet id,
676 struct media_transport *transport = data;
677 struct a2dp_transport *a2dp = transport->data;
681 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_UINT16) {
682 g_dbus_pending_property_error(id,
683 ERROR_INTERFACE ".InvalidArguments",
684 "Invalid arguments in method call");
688 dbus_message_iter_get_basic(iter, &volume);
691 g_dbus_pending_property_error(id,
692 ERROR_INTERFACE ".InvalidArguments",
693 "Invalid arguments in method call");
697 g_dbus_pending_property_success(id);
699 if (a2dp->volume == volume)
702 a2dp->volume = volume;
704 notify = transport->source_watch ? true : false;
706 g_dbus_emit_property_changed(btd_get_dbus_connection(),
708 MEDIA_TRANSPORT_INTERFACE,
711 avrcp_set_volume(transport->device, volume, notify);
714 static const GDBusMethodTable transport_methods[] = {
715 { GDBUS_ASYNC_METHOD("Acquire",
717 GDBUS_ARGS({ "fd", "h" }, { "mtu_r", "q" },
720 { GDBUS_ASYNC_METHOD("TryAcquire",
722 GDBUS_ARGS({ "fd", "h" }, { "mtu_r", "q" },
725 { GDBUS_ASYNC_METHOD("Release", NULL, NULL, release) },
729 static const GDBusPropertyTable transport_properties[] = {
730 { "Device", "o", get_device },
731 { "UUID", "s", get_uuid },
732 { "Codec", "y", get_codec },
733 { "Configuration", "ay", get_configuration },
734 { "State", "s", get_state },
735 { "Delay", "q", get_delay, NULL, delay_exists },
736 { "Volume", "q", get_volume, set_volume, volume_exists },
740 static void destroy_a2dp(void *data)
742 struct a2dp_transport *a2dp = data;
745 avdtp_unref(a2dp->session);
750 static void media_transport_free(void *data)
752 struct media_transport *transport = data;
754 transports = g_slist_remove(transports, transport);
756 if (transport->owner)
757 media_transport_remove_owner(transport);
759 if (transport->destroy != NULL)
760 transport->destroy(transport->data);
762 g_free(transport->configuration);
763 g_free(transport->path);
767 static void transport_update_playing(struct media_transport *transport,
770 DBG("%s State=%s Playing=%d", transport->path,
771 str_state[transport->state], playing);
773 if (playing == FALSE) {
774 if (transport->state == TRANSPORT_STATE_PENDING)
775 transport_set_state(transport, TRANSPORT_STATE_IDLE);
776 else if (transport->state == TRANSPORT_STATE_ACTIVE) {
778 if (transport->owner != NULL)
779 media_transport_remove_owner(transport);
781 } else if (transport->state == TRANSPORT_STATE_IDLE)
782 transport_set_state(transport, TRANSPORT_STATE_PENDING);
785 static void sink_state_changed(struct btd_service *service,
786 sink_state_t old_state,
787 sink_state_t new_state,
790 struct media_transport *transport = user_data;
792 if (new_state == SINK_STATE_PLAYING)
793 transport_update_playing(transport, TRUE);
795 transport_update_playing(transport, FALSE);
798 static void source_state_changed(struct btd_service *service,
799 source_state_t old_state,
800 source_state_t new_state,
803 struct media_transport *transport = user_data;
805 if (new_state == SOURCE_STATE_PLAYING)
806 transport_update_playing(transport, TRUE);
808 transport_update_playing(transport, FALSE);
811 static int media_transport_init_source(struct media_transport *transport)
813 struct btd_service *service;
814 struct a2dp_transport *a2dp;
816 service = btd_device_get_service(transport->device, A2DP_SINK_UUID);
820 a2dp = g_new0(struct a2dp_transport, 1);
822 transport->resume = resume_a2dp;
823 transport->suspend = suspend_a2dp;
824 transport->cancel = cancel_a2dp;
825 transport->data = a2dp;
826 transport->destroy = destroy_a2dp;
829 transport->sink_watch = sink_add_state_cb(service, sink_state_changed,
835 static int media_transport_init_sink(struct media_transport *transport)
837 struct btd_service *service;
838 struct a2dp_transport *a2dp;
840 service = btd_device_get_service(transport->device, A2DP_SOURCE_UUID);
844 a2dp = g_new0(struct a2dp_transport, 1);
846 transport->resume = resume_a2dp;
847 transport->suspend = suspend_a2dp;
848 transport->cancel = cancel_a2dp;
849 transport->data = a2dp;
850 transport->destroy = destroy_a2dp;
853 transport->source_watch = source_add_state_cb(service,
854 source_state_changed,
860 struct media_transport *media_transport_create(struct btd_device *device,
861 uint8_t *configuration,
862 size_t size, void *data)
864 struct media_endpoint *endpoint = data;
865 struct media_transport *transport;
869 transport = g_new0(struct media_transport, 1);
870 transport->device = device;
871 transport->endpoint = endpoint;
872 transport->configuration = g_new(uint8_t, size);
873 memcpy(transport->configuration, configuration, size);
874 transport->size = size;
875 transport->path = g_strdup_printf("%s/fd%d", device_get_path(device),
879 uuid = media_endpoint_get_uuid(endpoint);
880 if (strcasecmp(uuid, A2DP_SOURCE_UUID) == 0) {
881 if (media_transport_init_source(transport) < 0)
883 } else if (strcasecmp(uuid, A2DP_SINK_UUID) == 0) {
884 if (media_transport_init_sink(transport) < 0)
889 if (g_dbus_register_interface(btd_get_dbus_connection(),
890 transport->path, MEDIA_TRANSPORT_INTERFACE,
891 transport_methods, NULL, transport_properties,
892 transport, media_transport_free) == FALSE) {
893 error("Could not register transport %s", transport->path);
897 transports = g_slist_append(transports, transport);
902 media_transport_free(transport);
906 const char *media_transport_get_path(struct media_transport *transport)
908 return transport->path;
911 void media_transport_update_delay(struct media_transport *transport,
914 struct a2dp_transport *a2dp = transport->data;
916 /* Check if delay really changed */
917 if (a2dp->delay == delay)
922 g_dbus_emit_property_changed(btd_get_dbus_connection(),
924 MEDIA_TRANSPORT_INTERFACE, "Delay");
927 struct btd_device *media_transport_get_dev(struct media_transport *transport)
929 return transport->device;
932 uint16_t media_transport_get_volume(struct media_transport *transport)
934 struct a2dp_transport *a2dp = transport->data;
938 void media_transport_update_volume(struct media_transport *transport,
941 struct a2dp_transport *a2dp = transport->data;
943 /* Check if volume really changed */
944 if (a2dp->volume == volume)
947 a2dp->volume = volume;
949 g_dbus_emit_property_changed(btd_get_dbus_connection(),
951 MEDIA_TRANSPORT_INTERFACE, "Volume");
954 uint8_t media_transport_get_device_volume(struct btd_device *dev)
961 for (l = transports; l; l = l->next) {
962 struct media_transport *transport = l->data;
963 if (transport->device != dev)
966 /* Volume is A2DP only */
967 if (media_endpoint_get_sep(transport->endpoint))
968 return media_transport_get_volume(transport);
974 void media_transport_update_device_volume(struct btd_device *dev,
982 for (l = transports; l; l = l->next) {
983 struct media_transport *transport = l->data;
984 if (transport->device != dev)
987 /* Volume is A2DP only */
988 if (media_endpoint_get_sep(transport->endpoint))
989 media_transport_update_volume(transport, volume);