3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2012 Intel Corporation. All rights reserved.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include <dbus/dbus.h>
36 #ifdef __TIZEN_PATCH__
37 #include <sys/types.h>
38 #include <sys/xattr.h>
39 #include <linux/xattr.h>
42 #include "lib/bluetooth.h"
44 #include "lib/sdp_lib.h"
47 #include "gdbus/gdbus.h"
49 #include "btio/btio.h"
53 #include "uuid-helper.h"
54 #include "dbus-common.h"
55 #include "sdp-client.h"
62 #define DUN_DEFAULT_CHANNEL 1
63 #define SPP_DEFAULT_CHANNEL 3
64 #define HFP_HF_DEFAULT_CHANNEL 7
65 #define OPP_DEFAULT_CHANNEL 9
66 #define FTP_DEFAULT_CHANNEL 10
67 #define BIP_DEFAULT_CHANNEL 11
68 #define HSP_AG_DEFAULT_CHANNEL 12
69 #define HFP_AG_DEFAULT_CHANNEL 13
70 #define SYNC_DEFAULT_CHANNEL 14
71 #define PBAP_DEFAULT_CHANNEL 15
72 #define MAS_DEFAULT_CHANNEL 16
73 #define MNS_DEFAULT_CHANNEL 17
75 #define BTD_PROFILE_PSM_AUTO -1
76 #define BTD_PROFILE_CHAN_AUTO -1
78 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
79 #define HID_DEVICE_INTR_PSM 17
80 #define HID_DEVICE_CTRL_PSM 19
83 #define HFP_HF_RECORD \
84 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
86 <attribute id=\"0x0001\"> \
88 <uuid value=\"0x111e\" /> \
89 <uuid value=\"0x1203\" /> \
92 <attribute id=\"0x0004\"> \
95 <uuid value=\"0x0100\" /> \
98 <uuid value=\"0x0003\" /> \
99 <uint8 value=\"0x%02x\" /> \
103 <attribute id=\"0x0005\"> \
105 <uuid value=\"0x1002\" /> \
108 <attribute id=\"0x0009\"> \
111 <uuid value=\"0x111e\" /> \
112 <uint16 value=\"0x%04x\" /> \
116 <attribute id=\"0x0100\"> \
117 <text value=\"%s\" /> \
119 <attribute id=\"0x0311\"> \
120 <uint16 value=\"0x%04x\" /> \
124 #define HFP_AG_RECORD \
125 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
127 <attribute id=\"0x0001\"> \
129 <uuid value=\"0x111f\" /> \
130 <uuid value=\"0x1203\" /> \
133 <attribute id=\"0x0004\"> \
136 <uuid value=\"0x0100\" /> \
139 <uuid value=\"0x0003\" /> \
140 <uint8 value=\"0x%02x\" /> \
144 <attribute id=\"0x0005\"> \
146 <uuid value=\"0x1002\" /> \
149 <attribute id=\"0x0009\"> \
152 <uuid value=\"0x111e\" /> \
153 <uint16 value=\"0x%04x\" /> \
157 <attribute id=\"0x0100\"> \
158 <text value=\"%s\" /> \
160 <attribute id=\"0x0311\"> \
161 <uint16 value=\"0x%04x\" /> \
163 <attribute id=\"0x0301\" > \
164 <uint8 value=\"0x01\" /> \
168 #define HSP_AG_RECORD \
169 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
171 <attribute id=\"0x0001\"> \
173 <uuid value=\"0x1112\" /> \
174 <uuid value=\"0x1203\" /> \
177 <attribute id=\"0x0004\"> \
180 <uuid value=\"0x0100\" /> \
183 <uuid value=\"0x0003\" /> \
184 <uint8 value=\"0x%02x\" /> \
188 <attribute id=\"0x0005\"> \
190 <uuid value=\"0x1002\" /> \
193 <attribute id=\"0x0009\"> \
196 <uuid value=\"0x1108\" /> \
197 <uint16 value=\"0x%04x\" /> \
201 <attribute id=\"0x0100\"> \
202 <text value=\"%s\" /> \
206 #ifdef __TIZEN_PATCH__
208 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
210 <attribute id=\"0x0001\"> \
215 <attribute id=\"0x0004\"> \
218 <uuid value=\"0x0100\" /> \
221 <uuid value=\"0x0003\" /> \
222 <uint8 value=\"0x%02x\" /> \
226 <attribute id=\"0x0005\"> \
228 <uuid value=\"0x1002\" /> \
232 <attribute id=\"0x0009\"> \
235 <uuid value=\"0x1101\" /> \
236 <uint16 value=\"0x%04x\" /> \
240 <attribute id=\"0x0100\"> \
241 <text value=\"%s\" /> \
246 "<attribute id=\"0x0006\"> \
248 <uint16 value=\"0x%04x\" /> \
249 <uint16 value=\"0x%04x\" /> \
250 <uint16 value=\"0x%04x\" /> \
255 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
257 <attribute id=\"0x0001\"> \
259 <uuid value=\"0x1101\" /> \
263 <attribute id=\"0x0004\"> \
266 <uuid value=\"0x0100\" /> \
269 <uuid value=\"0x0003\" /> \
270 <uint8 value=\"0x%02x\" /> \
274 <attribute id=\"0x0005\"> \
276 <uuid value=\"0x1002\" /> \
279 <attribute id=\"0x0009\"> \
282 <uuid value=\"0x1101\" /> \
283 <uint16 value=\"0x%04x\" /> \
287 <attribute id=\"0x0100\"> \
288 <text value=\"%s\" /> \
294 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
296 <attribute id=\"0x0001\"> \
298 <uuid value=\"0x1103\" /> \
299 <uuid value=\"0x1201\" /> \
302 <attribute id=\"0x0004\"> \
305 <uuid value=\"0x0100\" /> \
308 <uuid value=\"0x0003\" /> \
309 <uint8 value=\"0x%02x\" /> \
313 <attribute id=\"0x0005\"> \
315 <uuid value=\"0x1002\" /> \
318 <attribute id=\"0x0009\"> \
321 <uuid value=\"0x1103\" /> \
322 <uint16 value=\"0x%04x\" /> \
326 <attribute id=\"0x0100\"> \
327 <text value=\"%s\" /> \
331 #ifdef __TIZEN_PATCH__
333 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
335 <attribute id=\"0x0001\"> \
337 <uuid value=\"0x1105\" /> \
340 <attribute id=\"0x0004\"> \
343 <uuid value=\"0x0100\" /> \
346 <uuid value=\"0x0003\" /> \
347 <uint8 value=\"0x%02x\" /> \
350 <uuid value=\"0x0008\"/> \
354 <attribute id=\"0x0005\"> \
356 <uuid value=\"0x1002\" /> \
359 <attribute id=\"0x0009\"> \
362 <uuid value=\"0x1105\" /> \
363 <uint16 value=\"0x%04x\" /> \
367 <attribute id=\"0x0303\"> \
369 <uint8 value=\"0x01\"/> \
370 <uint8 value=\"0x02\"/> \
371 <uint8 value=\"0x03\"/> \
372 <uint8 value=\"0x04\"/> \
373 <uint8 value=\"0x05\"/> \
374 <uint8 value=\"0x06\"/> \
375 <uint8 value=\"0xff\"/> \
378 <attribute id=\"0x0100\"> \
379 <text value=\"%s\" /> \
384 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
386 <attribute id=\"0x0001\"> \
388 <uuid value=\"0x1105\" /> \
391 <attribute id=\"0x0004\"> \
394 <uuid value=\"0x0100\" /> \
397 <uuid value=\"0x0003\" /> \
398 <uint8 value=\"0x%02x\" /> \
401 <uuid value=\"0x0008\"/> \
405 <attribute id=\"0x0005\"> \
407 <uuid value=\"0x1002\" /> \
410 <attribute id=\"0x0009\"> \
413 <uuid value=\"0x1105\" /> \
414 <uint16 value=\"0x%04x\" /> \
418 <attribute id=\"0x0303\"> \
420 <uint8 value=\"0x01\"/> \
421 <uint8 value=\"0x02\"/> \
422 <uint8 value=\"0x03\"/> \
423 <uint8 value=\"0x04\"/> \
424 <uint8 value=\"0x05\"/> \
425 <uint8 value=\"0x06\"/> \
426 <uint8 value=\"0xff\"/> \
429 <attribute id=\"0x0200\"> \
430 <uint16 value=\"%u\" name=\"psm\"/> \
432 <attribute id=\"0x0100\"> \
433 <text value=\"%s\" /> \
439 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
441 <attribute id=\"0x0001\"> \
443 <uuid value=\"0x1106\" /> \
446 <attribute id=\"0x0004\"> \
449 <uuid value=\"0x0100\" /> \
452 <uuid value=\"0x0003\" /> \
453 <uint8 value=\"0x%02x\" /> \
456 <uuid value=\"0x0008\"/> \
460 <attribute id=\"0x0005\"> \
462 <uuid value=\"0x1002\" /> \
465 <attribute id=\"0x0009\"> \
468 <uuid value=\"0x1106\" /> \
469 <uint16 value=\"0x%04x\" /> \
473 <attribute id=\"0x0200\"> \
474 <uint16 value=\"%u\" name=\"psm\"/> \
476 <attribute id=\"0x0100\"> \
477 <text value=\"%s\" /> \
482 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
484 <attribute id=\"0x0001\"> \
486 <uuid value=\"0x112e\" /> \
489 <attribute id=\"0x0005\"> \
491 <uuid value=\"0x1002\" /> \
494 <attribute id=\"0x0009\"> \
497 <uuid value=\"0x1130\" /> \
498 <uint16 value=\"0x%04x\" /> \
502 <attribute id=\"0x0100\"> \
503 <text value=\"%s\" /> \
507 #ifdef PBAP_SIM_ENABLE
508 #define PBAP_ACCESS "0x03" /* Phone and SIM access support*/
510 #define PBAP_ACCESS "0x01" /* Phone access support only*/
514 #ifdef __TIZEN_PATCH__
516 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
518 <attribute id=\"0x0001\"> \
520 <uuid value=\"0x112f\" /> \
523 <attribute id=\"0x0004\"> \
526 <uuid value=\"0x0100\" /> \
529 <uuid value=\"0x0003\" /> \
530 <uint8 value=\"0x%02x\" /> \
533 <uuid value=\"0x0008\"/> \
537 <attribute id=\"0x0005\"> \
539 <uuid value=\"0x1002\" /> \
542 <attribute id=\"0x0009\"> \
545 <uuid value=\"0x1130\" /> \
546 <uint16 value=\"0x%04x\" /> \
550 <attribute id=\"0x0100\"> \
551 <text value=\"%s\" /> \
553 <attribute id=\"0x0314\"> \
554 <uint8 value=\""PBAP_ACCESS"\"/> \
556 <attribute id=\"0x0200\"> \
557 <uint16 value=\"%u\" name=\"psm\"/> \
562 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
564 <attribute id=\"0x0001\"> \
566 <uuid value=\"0x112f\" /> \
569 <attribute id=\"0x0004\"> \
572 <uuid value=\"0x0100\" /> \
575 <uuid value=\"0x0003\" /> \
576 <uint8 value=\"0x%02x\" /> \
579 <uuid value=\"0x0008\"/> \
583 <attribute id=\"0x0005\"> \
585 <uuid value=\"0x1002\" /> \
588 <attribute id=\"0x0009\"> \
591 <uuid value=\"0x1130\" /> \
592 <uint16 value=\"0x%04x\" /> \
596 <attribute id=\"0x0100\"> \
597 <text value=\"%s\" /> \
599 <attribute id=\"0x0314\"> \
600 <uint8 value=\"0x01\"/> \
602 <attribute id=\"0x0317\"> \
603 <uint32 value=\"0x00000003\"/> \
605 <attribute id=\"0x0200\"> \
606 <uint16 value=\"%u\" name=\"psm\"/> \
612 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
614 <attribute id=\"0x0001\"> \
616 <uuid value=\"0x1132\"/> \
619 <attribute id=\"0x0004\"> \
622 <uuid value=\"0x0100\"/> \
625 <uuid value=\"0x0003\"/> \
626 <uint8 value=\"0x%02x\"/> \
629 <uuid value=\"0x0008\"/> \
633 <attribute id=\"0x0005\"> \
635 <uuid value=\"0x1002\" /> \
638 <attribute id=\"0x0009\"> \
641 <uuid value=\"0x1134\"/> \
642 <uint16 value=\"0x%04x\" /> \
646 <attribute id=\"0x0100\"> \
647 <text value=\"%s\"/> \
649 <attribute id=\"0x0315\"> \
650 <uint8 value=\"0x00\"/> \
652 <attribute id=\"0x0316\"> \
653 <uint8 value=\"0x0F\"/> \
655 <attribute id=\"0x0317\"> \
656 <uint32 value=\"0x0000007f\"/> \
658 <attribute id=\"0x0200\"> \
659 <uint16 value=\"%u\" name=\"psm\"/> \
664 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
666 <attribute id=\"0x0001\"> \
668 <uuid value=\"0x1133\"/> \
671 <attribute id=\"0x0004\"> \
674 <uuid value=\"0x0100\"/> \
677 <uuid value=\"0x0003\"/> \
678 <uint8 value=\"0x%02x\"/> \
681 <uuid value=\"0x0008\"/> \
685 <attribute id=\"0x0005\"> \
687 <uuid value=\"0x1002\" /> \
690 <attribute id=\"0x0009\"> \
693 <uuid value=\"0x1134\"/> \
694 <uint16 value=\"0x%04x\"/> \
698 <attribute id=\"0x0100\"> \
699 <text value=\"%s\"/> \
701 <attribute id=\"0x0317\"> \
702 <uint32 value=\"0x0000007f\"/> \
704 <attribute id=\"0x0200\"> \
705 <uint16 value=\"%u\" name=\"psm\"/> \
709 #define SYNC_RECORD \
710 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
712 <attribute id=\"0x0001\"> \
714 <uuid value=\"0x1104\"/> \
717 <attribute id=\"0x0004\"> \
720 <uuid value=\"0x0100\"/> \
723 <uuid value=\"0x0003\"/> \
724 <uint8 value=\"0x%02x\"/> \
727 <uuid value=\"0x0008\"/> \
731 <attribute id=\"0x0005\"> \
733 <uuid value=\"0x1002\" /> \
736 <attribute id=\"0x0009\"> \
739 <uuid value=\"0x1104\"/> \
740 <uint16 value=\"0x%04x\" /> \
744 <attribute id=\"0x0100\"> \
745 <text value=\"%s\"/> \
747 <attribute id=\"0x0301\"> \
749 <uint8 value=\"0x01\"/> \
754 #define GENERIC_RECORD \
755 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
757 <attribute id=\"0x0001\"> \
759 <uuid value=\"%s\" /> \
762 <attribute id=\"0x0004\"> \
765 <uuid value=\"0x0100\" /> \
771 <attribute id=\"0x0005\"> \
773 <uuid value=\"0x1002\" /> \
777 <attribute id=\"0x0100\"> \
778 <text value=\"%s\" /> \
782 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
783 #define HID_DEVICE_RECORD \
784 "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
786 <attribute id=\"0x0001\"> \
788 <uuid value=\"0x1124\" /> \
791 <attribute id=\"0x0004\"> \
794 <uuid value=\"0x0100\" /> \
795 <uint16 value=\"0x0011\" /> \
798 <uuid value=\"0x0011\" /> \
802 <attribute id=\"0x0005\"> \
804 <uuid value=\"0x1002\" /> \
807 <attribute id=\"0x0006\"> \
809 <uint16 value=\"0x656e\" /> \
810 <uint16 value=\"0x006a\" /> \
811 <uint16 value=\"0x0100\" /> \
814 <attribute id=\"0x0009\"> \
817 <uuid value=\"0x0011\" /> \
818 <uint16 value=\"0x0100\" /> \
822 <attribute id=\"0x000d\"> \
826 <uuid value=\"0x0100\" /> \
827 <uint16 value=\"0x0013\" /> \
830 <uuid value=\"0x0011\" /> \
835 <attribute id=\"0x0100\"> \
836 <text value=\"Bluez Mouse\" /> \
838 <attribute id=\"0x0101\"> \
839 <text value=\"Mouse\" /> \
841 <attribute id=\"0x0200\"> \
842 <uint16 value=\"0x0100\" /> \
844 <attribute id=\"0x0201\"> \
845 <uint16 value=\"0x0111\" /> \
847 <attribute id=\"0x0202\"> \
848 <uint8 value=\"0x40\" /> \
850 <attribute id=\"0x0203\"> \
851 <uint8 value=\"0x00\" /> \
853 <attribute id=\"0x0204\"> \
854 <boolean value=\"true\" /> \
856 <attribute id=\"0x0205\"> \
857 <boolean value=\"true\" /> \
859 <attribute id=\"0x0206\"> \
862 <uint8 value=\"0x22\" /> \
863 <text encoding=\"hex\" value=\"05010902a10185010901a1000509190129031500250175019503810275059501810105010930093109381581257f750895028106c0c005010906a1018502a100050719e029e71500250175019508810295087508150025650507190029658100c0c0\" /> \
867 <attribute id=\"0x0207\"> \
870 <uint16 value=\"0x0409\" /> \
871 <uint16 value=\"0x0100\" /> \
875 <attribute id=\"0x020b\"> \
876 <uint16 value=\"0x0100\" /> \
878 <attribute id=\"0x020e\"> \
879 <boolean value=\"true\" /> \
888 struct btd_profile p;
898 char *(*get_record)(struct ext_profile *ext, struct ext_io *l2cap,
899 struct ext_io *rfcomm);
906 BtIOSecLevel sec_level;
926 #ifdef __TIZEN_PATCH__
930 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
936 struct ext_profile *ext;
940 struct btd_adapter *adapter;
941 struct btd_device *device;
942 struct btd_service *service;
954 DBusPendingCall *pending;
958 struct btd_adapter *adapter;
962 struct btd_profile_custom_property {
966 btd_profile_prop_exists exists;
967 btd_profile_prop_get get;
971 static GSList *custom_props = NULL;
973 static GSList *profiles = NULL;
974 static GSList *ext_profiles = NULL;
976 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
977 static int connect_io(struct ext_io *conn, const bdaddr_t *src,
978 const bdaddr_t *dst);
981 void btd_profile_foreach(void (*func)(struct btd_profile *p, void *data),
986 for (l = profiles; l != NULL; l = next) {
987 struct btd_profile *profile = l->data;
989 next = g_slist_next(l);
994 for (l = ext_profiles; l != NULL; l = next) {
995 struct ext_profile *profile = l->data;
997 next = g_slist_next(l);
999 func(&profile->p, data);
1003 int btd_profile_register(struct btd_profile *profile)
1005 profiles = g_slist_append(profiles, profile);
1009 void btd_profile_unregister(struct btd_profile *profile)
1011 profiles = g_slist_remove(profiles, profile);
1014 static struct ext_profile *find_ext_profile(const char *owner,
1019 for (l = ext_profiles; l != NULL; l = g_slist_next(l)) {
1020 struct ext_profile *ext = l->data;
1022 if (g_strcmp0(ext->owner, owner))
1025 if (!g_strcmp0(ext->path, path))
1032 static void ext_io_destroy(gpointer p)
1034 struct ext_io *ext_io = p;
1036 if (ext_io->io_id > 0)
1037 g_source_remove(ext_io->io_id);
1040 g_io_channel_shutdown(ext_io->io, FALSE, NULL);
1041 g_io_channel_unref(ext_io->io);
1044 if (ext_io->auth_id != 0)
1045 btd_cancel_authorization(ext_io->auth_id);
1047 if (ext_io->pending) {
1048 dbus_pending_call_cancel(ext_io->pending);
1049 dbus_pending_call_unref(ext_io->pending);
1052 if (ext_io->resolving)
1053 bt_cancel_discovery(btd_adapter_get_address(ext_io->adapter),
1054 device_get_address(ext_io->device));
1056 if (ext_io->adapter)
1057 btd_adapter_unref(ext_io->adapter);
1060 btd_device_unref(ext_io->device);
1062 if (ext_io->service)
1063 btd_service_unref(ext_io->service);
1068 static gboolean ext_io_disconnected(GIOChannel *io, GIOCondition cond,
1071 struct ext_io *conn = user_data;
1072 struct ext_profile *ext = conn->ext;
1073 GError *gerr = NULL;
1076 if (cond & G_IO_NVAL)
1079 bt_io_get(io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
1081 error("Unable to get io data for %s: %s",
1082 ext->name, gerr->message);
1087 DBG("%s disconnected from %s", ext->name, addr);
1089 if (conn->service) {
1090 if (btd_service_get_state(conn->service) ==
1091 BTD_SERVICE_STATE_CONNECTING)
1092 btd_service_connecting_complete(conn->service, -EIO);
1094 btd_service_disconnecting_complete(conn->service, 0);
1097 ext->conns = g_slist_remove(ext->conns, conn);
1098 ext_io_destroy(conn);
1102 static void new_conn_reply(DBusPendingCall *call, void *user_data)
1104 struct ext_io *conn = user_data;
1105 struct ext_profile *ext = conn->ext;
1106 DBusMessage *reply = dbus_pending_call_steal_reply(call);
1109 dbus_error_init(&err);
1110 dbus_set_error_from_message(&err, reply);
1112 dbus_message_unref(reply);
1114 dbus_pending_call_unref(conn->pending);
1115 conn->pending = NULL;
1117 if (!dbus_error_is_set(&err)) {
1119 btd_service_connecting_complete(conn->service, 0);
1121 conn->connected = true;
1125 error("%s replied with an error: %s, %s", ext->name,
1126 err.name, err.message);
1129 btd_service_connecting_complete(conn->service, -ECONNREFUSED);
1131 dbus_error_free(&err);
1133 ext->conns = g_slist_remove(ext->conns, conn);
1134 ext_io_destroy(conn);
1137 static void disconn_reply(DBusPendingCall *call, void *user_data)
1139 struct ext_io *conn = user_data;
1140 struct ext_profile *ext = conn->ext;
1141 DBusMessage *reply = dbus_pending_call_steal_reply(call);
1144 dbus_error_init(&err);
1145 dbus_set_error_from_message(&err, reply);
1147 dbus_message_unref(reply);
1149 dbus_pending_call_unref(conn->pending);
1150 conn->pending = NULL;
1152 if (!dbus_error_is_set(&err)) {
1154 btd_service_disconnecting_complete(conn->service, 0);
1159 error("%s replied with an error: %s, %s", ext->name,
1160 err.name, err.message);
1163 btd_service_disconnecting_complete(conn->service,
1166 dbus_error_free(&err);
1169 ext->conns = g_slist_remove(ext->conns, conn);
1170 ext_io_destroy(conn);
1173 struct prop_append_data {
1174 DBusMessageIter *dict;
1178 static void append_prop(gpointer a, gpointer b)
1180 struct btd_profile_custom_property *p = a;
1181 struct prop_append_data *data = b;
1182 DBusMessageIter entry, value, *dict = data->dict;
1183 struct btd_device *dev = data->io->device;
1184 struct ext_profile *ext = data->io->ext;
1185 const char *uuid = ext->service ? ext->service : ext->uuid;
1187 if (strcasecmp(p->uuid, uuid) != 0)
1190 if (p->exists && !p->exists(p->uuid, dev, p->user_data))
1193 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, NULL,
1195 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &p->name);
1196 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, p->type,
1199 p->get(p->uuid, dev, &value, p->user_data);
1201 dbus_message_iter_close_container(&entry, &value);
1202 dbus_message_iter_close_container(dict, &entry);
1205 static uint16_t get_supported_features(const sdp_record_t *rec)
1209 data = sdp_data_get(rec, SDP_ATTR_SUPPORTED_FEATURES);
1210 if (!data || data->dtd != SDP_UINT16)
1213 return data->val.uint16;
1216 static uint16_t get_profile_version(const sdp_record_t *rec)
1221 if (sdp_get_profile_descs(rec, &descs) < 0)
1224 if (descs && descs->data) {
1225 sdp_profile_desc_t *desc = descs->data;
1226 version = desc->version;
1231 sdp_list_free(descs, free);
1236 static bool send_new_connection(struct ext_profile *ext, struct ext_io *conn)
1239 DBusMessageIter iter, dict;
1240 struct prop_append_data data = { &dict, conn };
1241 const char *remote_uuid = ext->remote_uuid;
1242 const sdp_record_t *rec;
1246 msg = dbus_message_new_method_call(ext->owner, ext->path,
1247 "org.bluez.Profile1",
1250 error("Unable to create NewConnection call for %s", ext->name);
1255 rec = btd_device_get_record(conn->device, remote_uuid);
1257 conn->features = get_supported_features(rec);
1258 conn->version = get_profile_version(rec);
1262 dbus_message_iter_init_append(msg, &iter);
1264 path = device_get_path(conn->device);
1265 dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path);
1267 fd = g_io_channel_unix_get_fd(conn->io);
1269 #ifdef __TIZEN_PATCH__
1271 DBG("Set smack label!");
1274 ret = fsetxattr(fd, XATTR_NAME_SMACKIPIN, "System", sizeof("System"), 0);
1276 DBG("Set attr error: %d", ret);
1279 ret = fsetxattr(fd, XATTR_NAME_SMACKIPOUT, "System", sizeof("System"), 0);
1281 DBG("Set attr error: %d", ret);
1286 dbus_message_iter_append_basic(&iter, DBUS_TYPE_UNIX_FD, &fd);
1288 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict);
1291 dict_append_entry(&dict, "Version", DBUS_TYPE_UINT16,
1295 dict_append_entry(&dict, "Features", DBUS_TYPE_UINT16,
1298 g_slist_foreach(custom_props, append_prop, &data);
1300 dbus_message_iter_close_container(&iter, &dict);
1302 if (!g_dbus_send_message_with_reply(btd_get_dbus_connection(),
1303 msg, &conn->pending, -1)) {
1304 error("%s: sending NewConnection failed", ext->name);
1305 dbus_message_unref(msg);
1309 dbus_message_unref(msg);
1311 dbus_pending_call_set_notify(conn->pending, new_conn_reply, conn, NULL);
1316 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1317 static int check_connection_psm(gconstpointer a, gconstpointer b)
1319 const struct ext_io *conn = a;
1321 DBG("conn->psm %d, psm %d", conn->psm, *psm);
1322 return (conn->psm == *psm ? 0 : -1);
1326 static void ext_connect(GIOChannel *io, GError *err, gpointer user_data)
1328 struct ext_io *conn = user_data;
1329 struct ext_profile *ext = conn->ext;
1330 GError *io_err = NULL;
1333 if (!bt_io_get(io, &io_err,
1334 BT_IO_OPT_DEST, addr,
1335 BT_IO_OPT_INVALID)) {
1336 error("Unable to get connect data for %s: %s", ext->name,
1339 g_error_free(io_err);
1348 error("%s failed to connect to %s: %s", ext->name, addr,
1353 DBG("%s connected to %s", ext->name, addr);
1355 if (conn->io_id == 0) {
1356 GIOCondition cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1357 conn->io_id = g_io_add_watch(io, cond, ext_io_disconnected,
1361 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1362 if (g_strcmp0(ext->uuid, HID_UUID) == 0 && ext->local_connect == TRUE) {
1364 int psm = HID_DEVICE_CTRL_PSM;
1365 ext->local_connect = FALSE;
1366 l = g_slist_find_custom(ext->conns, &psm, check_connection_psm);
1368 struct ext_io *conn1 = g_new0(struct ext_io, 1);
1370 ext->remote_psm = psm;
1372 conn1->psm = ext->remote_psm;
1373 conn1->chan = ext->remote_chan;
1374 error = connect_io(conn1, btd_adapter_get_address(conn->adapter),
1375 device_get_address(conn->device));
1376 DBG("error from connect_io %d", error);
1377 conn1->adapter = btd_adapter_ref(conn->adapter);
1378 conn1->device = btd_device_ref(conn->device);
1379 conn1->service = btd_service_ref(conn->service);
1380 ext->conns = g_slist_append(ext->conns, conn1);
1382 DBG("Connection Already there");
1387 if (conn->service && service_accept(conn->service) == 0) {
1388 if (send_new_connection(ext, conn))
1394 btd_service_connecting_complete(conn->service,
1395 err ? -err->code : -EIO);
1398 g_error_free(io_err);
1400 ext->conns = g_slist_remove(ext->conns, conn);
1401 ext_io_destroy(conn);
1404 static void ext_auth(DBusError *err, void *user_data)
1406 struct ext_io *conn = user_data;
1407 struct ext_profile *ext = conn->ext;
1408 GError *gerr = NULL;
1413 bt_io_get(conn->io, &gerr, BT_IO_OPT_DEST, addr, BT_IO_OPT_INVALID);
1415 error("Unable to get connect data for %s: %s",
1416 ext->name, gerr->message);
1421 if (err && dbus_error_is_set(err)) {
1422 error("%s rejected %s: %s", ext->name, addr, err->message);
1426 if (!bt_io_accept(conn->io, ext_connect, conn, NULL, &gerr)) {
1427 error("bt_io_accept: %s", gerr->message);
1432 DBG("%s authorized to connect to %s", addr, ext->name);
1437 ext->conns = g_slist_remove(ext->conns, conn);
1438 ext_io_destroy(conn);
1441 static struct ext_io *create_conn(struct ext_io *server, GIOChannel *io,
1442 bdaddr_t *src, bdaddr_t *dst)
1444 struct btd_device *device;
1445 struct btd_service *service;
1446 struct ext_io *conn;
1450 device = btd_adapter_find_device(server->adapter, dst, BDADDR_BREDR);
1451 if (device == NULL) {
1453 error("%s device %s not found", server->ext->name, addr);
1457 /* Do not add UUID if client role is not enabled */
1458 if (!server->ext->enable_client) {
1463 btd_device_add_uuid(device, server->ext->remote_uuid);
1464 service = btd_device_get_service(device, server->ext->remote_uuid);
1465 if (service == NULL) {
1467 error("%s service not found for device %s", server->ext->name,
1473 conn = g_new0(struct ext_io, 1);
1474 conn->io = g_io_channel_ref(io);
1475 conn->proto = server->proto;
1476 conn->ext = server->ext;
1477 conn->adapter = btd_adapter_ref(server->adapter);
1478 conn->device = btd_device_ref(device);
1481 conn->service = btd_service_ref(service);
1483 cond = G_IO_HUP | G_IO_ERR | G_IO_NVAL;
1484 conn->io_id = g_io_add_watch(io, cond, ext_io_disconnected, conn);
1489 static void ext_confirm(GIOChannel *io, gpointer user_data)
1491 struct ext_io *server = user_data;
1492 struct ext_profile *ext = server->ext;
1493 const char *uuid = ext->service ? ext->service : ext->uuid;
1494 struct ext_io *conn;
1495 GError *gerr = NULL;
1499 bt_io_get(io, &gerr,
1500 BT_IO_OPT_SOURCE_BDADDR, &src,
1501 BT_IO_OPT_DEST_BDADDR, &dst,
1502 BT_IO_OPT_DEST, addr,
1505 error("%s failed to get connect data: %s", ext->name,
1511 DBG("incoming connect from %s", addr);
1513 conn = create_conn(server, io, &src, &dst);
1517 conn->auth_id = btd_request_authorization(&src, &dst, uuid, ext_auth,
1519 if (conn->auth_id == 0) {
1520 error("%s authorization failure", ext->name);
1521 ext_io_destroy(conn);
1525 ext->conns = g_slist_append(ext->conns, conn);
1527 DBG("%s authorizing connection from %s", ext->name, addr);
1530 static void ext_direct_connect(GIOChannel *io, GError *err, gpointer user_data)
1532 struct ext_io *server = user_data;
1533 struct ext_profile *ext = server->ext;
1534 GError *gerr = NULL;
1535 struct ext_io *conn;
1538 bt_io_get(io, &gerr,
1539 BT_IO_OPT_SOURCE_BDADDR, &src,
1540 BT_IO_OPT_DEST_BDADDR, &dst,
1543 error("%s failed to get connect data: %s", ext->name,
1549 conn = create_conn(server, io, &src, &dst);
1553 ext->conns = g_slist_append(ext->conns, conn);
1555 ext_connect(io, err, conn);
1558 static uint32_t ext_register_record(struct ext_profile *ext,
1559 struct ext_io *l2cap,
1560 struct ext_io *rfcomm,
1561 struct btd_adapter *a)
1564 char *dyn_record = NULL;
1565 const char *record = ext->record;
1567 if (!record && ext->get_record) {
1568 dyn_record = ext->get_record(ext, l2cap, rfcomm);
1569 record = dyn_record;
1575 rec = sdp_xml_parse_record(record, strlen(record));
1580 error("Unable to parse record for %s", ext->name);
1584 if (adapter_service_add(a, rec) < 0) {
1585 error("Failed to register service record");
1586 sdp_record_free(rec);
1593 static uint32_t ext_start_servers(struct ext_profile *ext,
1594 struct btd_adapter *adapter)
1596 struct ext_io *l2cap = NULL;
1597 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1598 struct ext_io *l2cap1 = NULL;
1600 struct ext_io *rfcomm = NULL;
1601 BtIOConfirm confirm;
1602 BtIOConnect connect;
1605 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1609 if (ext->authorize) {
1610 confirm = ext_confirm;
1614 connect = ext_direct_connect;
1617 if (ext->local_psm) {
1620 if (ext->local_psm > 0)
1621 psm = ext->local_psm;
1625 l2cap = g_new0(struct ext_io, 1);
1628 io = bt_io_listen(connect, confirm, l2cap, NULL, &err,
1629 BT_IO_OPT_SOURCE_BDADDR,
1630 btd_adapter_get_address(adapter),
1631 BT_IO_OPT_MODE, ext->mode,
1633 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1636 error("L2CAP server failed for %s: %s",
1637 ext->name, err->message);
1640 g_clear_error(&err);
1644 bt_io_get(io, NULL, BT_IO_OPT_PSM, &psm,
1647 l2cap->proto = BTPROTO_L2CAP;
1649 l2cap->adapter = btd_adapter_ref(adapter);
1650 ext->servers = g_slist_append(ext->servers, l2cap);
1651 DBG("%s listening on PSM %u", ext->name, psm);
1653 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
1654 if (g_strcmp0(ext->uuid , HID_UUID) == 0) {
1655 psm = HID_DEVICE_CTRL_PSM;
1656 l2cap1 = g_new0(struct ext_io, 1);
1658 io1 = bt_io_listen(connect, confirm, l2cap, NULL, &err,
1659 BT_IO_OPT_SOURCE_BDADDR,
1660 btd_adapter_get_address(adapter),
1661 BT_IO_OPT_MODE, ext->mode,
1663 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1666 l2cap1->proto = BTPROTO_L2CAP;
1668 l2cap1->adapter = btd_adapter_ref(adapter);
1669 ext->servers = g_slist_append(ext->servers, l2cap1);
1670 DBG("%s listening on PSM %u", ext->name, psm);
1675 if (ext->local_chan) {
1678 if (ext->local_chan > 0)
1679 chan = ext->local_chan;
1683 rfcomm = g_new0(struct ext_io, 1);
1686 io = bt_io_listen(connect, confirm, rfcomm, NULL, &err,
1687 BT_IO_OPT_SOURCE_BDADDR,
1688 btd_adapter_get_address(adapter),
1689 BT_IO_OPT_CHANNEL, chan,
1690 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1693 error("RFCOMM server failed for %s: %s",
1694 ext->name, err->message);
1696 g_clear_error(&err);
1700 bt_io_get(io, NULL, BT_IO_OPT_CHANNEL, &chan,
1703 rfcomm->proto = BTPROTO_RFCOMM;
1704 rfcomm->chan = chan;
1705 rfcomm->adapter = btd_adapter_ref(adapter);
1706 ext->servers = g_slist_append(ext->servers, rfcomm);
1707 DBG("%s listening on chan %u", ext->name, chan);
1711 return ext_register_record(ext, l2cap, rfcomm, adapter);
1715 ext->servers = g_slist_remove(ext->servers, l2cap);
1716 ext_io_destroy(l2cap);
1722 static struct ext_profile *find_ext(struct btd_profile *p)
1726 l = g_slist_find(ext_profiles, p);
1733 #ifdef __TIZEN_PATCH__
1734 gboolean ext_profile_is_registered_as_client_role(struct btd_profile *p)
1736 struct ext_profile *ext = find_ext(p);
1737 if (ext && ext->role) {
1738 if(strcasecmp(ext->role, "client") == 0) {
1748 static int ext_adapter_probe(struct btd_profile *p,
1749 struct btd_adapter *adapter)
1751 struct ext_profile *ext;
1752 struct ext_record *rec;
1759 DBG("\"%s\" probed", ext->name);
1761 handle = ext_start_servers(ext, adapter);
1765 rec = g_new0(struct ext_record, 1);
1766 rec->adapter = btd_adapter_ref(adapter);
1767 rec->handle = handle;
1769 ext->records = g_slist_append(ext->records, rec);
1774 static void ext_remove_records(struct ext_profile *ext,
1775 struct btd_adapter *adapter)
1779 for (l = ext->records; l != NULL; l = next) {
1780 struct ext_record *r = l->data;
1782 next = g_slist_next(l);
1784 if (adapter && r->adapter != adapter)
1787 ext->records = g_slist_remove(ext->records, r);
1789 adapter_service_remove(adapter, r->handle);
1790 btd_adapter_unref(r->adapter);
1795 static void ext_adapter_remove(struct btd_profile *p,
1796 struct btd_adapter *adapter)
1798 struct ext_profile *ext;
1805 DBG("\"%s\" removed", ext->name);
1807 ext_remove_records(ext, adapter);
1809 for (l = ext->servers; l != NULL; l = next) {
1810 struct ext_io *server = l->data;
1812 next = g_slist_next(l);
1814 if (server->adapter != adapter)
1817 ext->servers = g_slist_remove(ext->servers, server);
1818 ext_io_destroy(server);
1822 static int ext_device_probe(struct btd_service *service)
1824 struct btd_profile *p = btd_service_get_profile(service);
1825 struct ext_profile *ext;
1831 DBG("%s probed with UUID %s", ext->name, p->remote_uuid);
1836 static struct ext_io *find_connection(struct ext_profile *ext,
1837 struct btd_device *dev)
1841 for (l = ext->conns; l != NULL; l = g_slist_next(l)) {
1842 struct ext_io *conn = l->data;
1844 if (conn->device == dev)
1851 static void ext_device_remove(struct btd_service *service)
1853 struct btd_profile *p = btd_service_get_profile(service);
1854 struct btd_device *dev = btd_service_get_device(service);
1855 struct ext_profile *ext;
1856 struct ext_io *conn;
1862 DBG("%s", ext->name);
1864 conn = find_connection(ext, dev);
1866 ext->conns = g_slist_remove(ext->conns, conn);
1867 ext_io_destroy(conn);
1871 static int connect_io(struct ext_io *conn, const bdaddr_t *src,
1872 const bdaddr_t *dst)
1874 struct ext_profile *ext = conn->ext;
1875 GError *gerr = NULL;
1879 conn->proto = BTPROTO_L2CAP;
1880 io = bt_io_connect(ext_connect, conn, NULL, &gerr,
1881 BT_IO_OPT_SOURCE_BDADDR, src,
1882 BT_IO_OPT_DEST_BDADDR, dst,
1883 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1884 BT_IO_OPT_PSM, conn->psm,
1887 conn->proto = BTPROTO_RFCOMM;
1888 io = bt_io_connect(ext_connect, conn, NULL, &gerr,
1889 BT_IO_OPT_SOURCE_BDADDR, src,
1890 BT_IO_OPT_DEST_BDADDR, dst,
1891 BT_IO_OPT_SEC_LEVEL, ext->sec_level,
1892 BT_IO_OPT_CHANNEL, conn->chan,
1897 error("Unable to connect %s: %s", ext->name, gerr->message);
1907 static uint16_t get_goep_l2cap_psm(sdp_record_t *rec)
1911 data = sdp_data_get(rec, SDP_ATTR_GOEP_L2CAP_PSM);
1915 if (data->dtd != SDP_UINT16)
1918 /* PSM must be odd and lsb of upper byte must be 0 */
1919 if ((data->val.uint16 & 0x0101) != 0x0001)
1922 return data->val.uint16;
1925 static void record_cb(sdp_list_t *recs, int err, gpointer user_data)
1927 struct ext_io *conn = user_data;
1928 struct ext_profile *ext = conn->ext;
1931 conn->resolving = false;
1934 error("Unable to get %s SDP record: %s", ext->name,
1939 if (!recs || !recs->data) {
1940 error("No SDP records found for %s", ext->name);
1945 for (r = recs; r != NULL; r = r->next) {
1946 sdp_record_t *rec = r->data;
1949 #ifdef __TIZEN_PATCH__
1951 sdp_list_t *svcclass = NULL;
1953 if (sdp_get_service_classes(rec, &svcclass) < 0)
1956 /* Check for empty service classes list */
1957 if (svcclass == NULL) {
1958 DBG("Skipping record with no service classes");
1962 /* Extract the first element and skip the remainning */
1963 profile_uuid = bt_uuid2string(svcclass->data);
1964 if (!profile_uuid) {
1965 sdp_list_free(svcclass, free);
1969 sdp_list_free(svcclass, free);
1971 DBG("profile uuid %s port uuid %s", profile_uuid, ext->remote_uuid);
1973 if (g_ascii_strncasecmp(profile_uuid, ext->remote_uuid,
1974 strlen(profile_uuid)) != 0) {
1982 if (sdp_get_access_protos(rec, &protos) < 0) {
1983 error("Unable to get proto list from %s record",
1989 port = sdp_get_proto_port(protos, L2CAP_UUID);
1993 port = sdp_get_proto_port(protos, RFCOMM_UUID);
1997 if (conn->psm == 0 && sdp_get_proto_desc(protos, OBEX_UUID))
1998 conn->psm = get_goep_l2cap_psm(rec);
2000 conn->features = get_supported_features(rec);
2001 conn->version = get_profile_version(rec);
2003 sdp_list_foreach(protos, (sdp_list_func_t) sdp_list_free,
2005 sdp_list_free(protos, NULL);
2007 if (conn->chan || conn->psm)
2011 if (!conn->chan && !conn->psm) {
2012 error("Failed to find L2CAP PSM or RFCOMM channel for %s",
2018 err = connect_io(conn, btd_adapter_get_address(conn->adapter),
2019 device_get_address(conn->device));
2021 error("Connecting %s failed: %s", ext->name, strerror(-err));
2029 btd_service_connecting_complete(conn->service, err);
2031 ext->conns = g_slist_remove(ext->conns, conn);
2032 ext_io_destroy(conn);
2035 static int resolve_service(struct ext_io *conn, const bdaddr_t *src,
2036 const bdaddr_t *dst)
2038 struct ext_profile *ext = conn->ext;
2042 bt_string2uuid(&uuid, ext->remote_uuid);
2043 sdp_uuid128_to_uuid(&uuid);
2045 err = bt_search_service(src, dst, &uuid, record_cb, conn, NULL, 0);
2047 conn->resolving = true;
2052 static int ext_connect_dev(struct btd_service *service)
2054 struct btd_device *dev = btd_service_get_device(service);
2055 struct btd_profile *profile = btd_service_get_profile(service);
2056 struct btd_adapter *adapter;
2057 struct ext_io *conn;
2058 struct ext_profile *ext;
2061 ext = find_ext(profile);
2065 conn = find_connection(ext, dev);
2069 adapter = device_get_adapter(dev);
2071 conn = g_new0(struct ext_io, 1);
2073 #ifndef TIZEN_BT_HID_DEVICE_ENABLE
2074 if (ext->remote_psm || ext->remote_chan) {
2075 conn->psm = ext->remote_psm;
2076 conn->chan = ext->remote_chan;
2077 err = connect_io(conn, btd_adapter_get_address(adapter),
2078 device_get_address(dev));
2080 err = resolve_service(conn, btd_adapter_get_address(adapter),
2081 device_get_address(dev));
2087 if (g_strcmp0(ext->uuid, HID_UUID) == 0) {
2088 ext->local_connect = TRUE;
2089 ext->remote_psm = HID_DEVICE_INTR_PSM;
2090 conn->psm = ext->remote_psm;
2091 conn->chan = ext->remote_chan;
2092 err = connect_io(conn, btd_adapter_get_address(adapter),
2093 device_get_address(dev));
2095 if (ext->remote_psm || ext->remote_chan) {
2096 conn->psm = ext->remote_psm;
2097 conn->chan = ext->remote_chan;
2098 err = connect_io(conn, btd_adapter_get_address(adapter),
2099 device_get_address(dev));
2101 err = resolve_service(conn, btd_adapter_get_address(adapter),
2102 device_get_address(dev));
2108 conn->adapter = btd_adapter_ref(adapter);
2109 conn->device = btd_device_ref(dev);
2110 conn->service = btd_service_ref(service);
2112 ext->conns = g_slist_append(ext->conns, conn);
2121 static int send_disconn_req(struct ext_profile *ext, struct ext_io *conn)
2126 msg = dbus_message_new_method_call(ext->owner, ext->path,
2127 "org.bluez.Profile1",
2128 "RequestDisconnection");
2130 error("Unable to create RequestDisconnection call for %s",
2135 path = device_get_path(conn->device);
2136 dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &path,
2139 if (!g_dbus_send_message_with_reply(btd_get_dbus_connection(),
2140 msg, &conn->pending, -1)) {
2141 error("%s: sending RequestDisconnection failed", ext->name);
2142 dbus_message_unref(msg);
2146 dbus_message_unref(msg);
2148 dbus_pending_call_set_notify(conn->pending, disconn_reply, conn, NULL);
2153 static int ext_disconnect_dev(struct btd_service *service)
2155 struct btd_device *dev = btd_service_get_device(service);
2156 struct btd_profile *profile = btd_service_get_profile(service);
2157 struct ext_profile *ext;
2158 struct ext_io *conn;
2161 ext = find_ext(profile);
2165 #ifndef TIZEN_BT_HID_DEVICE_ENABLE
2166 conn = find_connection(ext, dev);
2167 if (!conn || !conn->connected)
2173 err = send_disconn_req(ext, conn);
2177 if (g_strcmp0(ext->uuid, HID_UUID) != 0) {
2178 conn = find_connection(ext, dev);
2179 if (!conn || !conn->connected)
2185 err = send_disconn_req(ext, conn);
2190 /* As HID will be using two psm we need to send disconnect
2191 * request for both the psms */
2192 for (l = ext->conns; l != NULL; l = g_slist_next(l)) {
2193 struct ext_io *conn1 = l->data;
2194 if (conn1->device == dev) {
2195 err = send_disconn_req(ext, conn1);
2203 static char *get_hfp_hf_record(struct ext_profile *ext, struct ext_io *l2cap,
2204 struct ext_io *rfcomm)
2206 return g_strdup_printf(HFP_HF_RECORD, rfcomm->chan, ext->version,
2207 ext->name, ext->features);
2210 static char *get_hfp_ag_record(struct ext_profile *ext, struct ext_io *l2cap,
2211 struct ext_io *rfcomm)
2213 return g_strdup_printf(HFP_AG_RECORD, rfcomm->chan, ext->version,
2214 ext->name, ext->features);
2217 static char *get_hsp_ag_record(struct ext_profile *ext, struct ext_io *l2cap,
2218 struct ext_io *rfcomm)
2220 return g_strdup_printf(HSP_AG_RECORD, rfcomm->chan, ext->version,
2224 static char *get_spp_record(struct ext_profile *ext, struct ext_io *l2cap,
2225 struct ext_io *rfcomm)
2228 #ifdef __TIZEN_PATCH__
2230 uint16_t code_ISO639 = (0x65 << 8) | 0x6e;
2231 uint16_t encoding = 106;
2232 uint16_t base_offset = SDP_PRIMARY_LANG_BASE;
2236 svc = g_strdup_printf("<uuid value=\"%s\" />", ext->service);
2240 #ifdef __TIZEN_PATCH__
2241 lan_seq = g_strdup_printf(LANG_SEQ, code_ISO639, encoding,
2243 rec = g_strdup_printf(SPP_RECORD, svc, rfcomm->chan, lan_seq, ext->version,
2247 rec = g_strdup_printf(SPP_RECORD, svc, rfcomm->chan, ext->version,
2254 static char *get_dun_record(struct ext_profile *ext, struct ext_io *l2cap,
2255 struct ext_io *rfcomm)
2257 return g_strdup_printf(DUN_RECORD, rfcomm->chan, ext->version,
2261 static char *get_pce_record(struct ext_profile *ext, struct ext_io *l2cap,
2262 struct ext_io *rfcomm)
2264 return g_strdup_printf(PCE_RECORD, ext->version, ext->name);
2267 static char *get_pse_record(struct ext_profile *ext, struct ext_io *l2cap,
2268 struct ext_io *rfcomm)
2276 chan = rfcomm->chan;
2278 return g_strdup_printf(PSE_RECORD, chan, ext->version, ext->name, psm);
2281 static char *get_mas_record(struct ext_profile *ext, struct ext_io *l2cap,
2282 struct ext_io *rfcomm)
2290 chan = rfcomm->chan;
2292 return g_strdup_printf(MAS_RECORD, chan, ext->version, ext->name, psm);
2295 static char *get_mns_record(struct ext_profile *ext, struct ext_io *l2cap,
2296 struct ext_io *rfcomm)
2304 chan = rfcomm->chan;
2306 return g_strdup_printf(MNS_RECORD, chan, ext->version, ext->name, psm);
2309 static char *get_sync_record(struct ext_profile *ext, struct ext_io *l2cap,
2310 struct ext_io *rfcomm)
2312 return g_strdup_printf(SYNC_RECORD, rfcomm->chan, ext->version,
2316 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
2317 static char *get_hid_device_record(struct ext_profile *ext, struct ext_io *l2cap,
2318 struct ext_io *rfcomm)
2320 return g_strdup(HID_DEVICE_RECORD);
2324 static char *get_opp_record(struct ext_profile *ext, struct ext_io *l2cap,
2325 struct ext_io *rfcomm)
2327 #ifndef __TIZEN_PATCH__
2332 #ifndef __TIZEN_PATCH__
2337 chan = rfcomm->chan;
2339 #ifdef __TIZEN_PATCH__
2340 return g_strdup_printf(OPP_RECORD, chan, ext->version, ext->name);
2342 return g_strdup_printf(OPP_RECORD, chan, ext->version, psm, ext->name);
2346 static char *get_ftp_record(struct ext_profile *ext, struct ext_io *l2cap,
2347 struct ext_io *rfcomm)
2355 chan = rfcomm->chan;
2357 return g_strdup_printf(FTP_RECORD, chan, ext->version, psm, ext->name);
2360 #define RFCOMM_SEQ "<sequence> \
2361 <uuid value=\"0x0003\" /> \
2362 <uint8 value=\"0x%02x\" /> \
2365 #define VERSION_ATTR \
2366 "<attribute id=\"0x0009\"> \
2369 <uuid value=\"%s\" /> \
2370 <uint16 value=\"0x%04x\" /> \
2375 static char *get_generic_record(struct ext_profile *ext, struct ext_io *l2cap,
2376 struct ext_io *rfcomm)
2378 char uuid_str[MAX_LEN_UUID_STR], svc_str[MAX_LEN_UUID_STR], psm[30];
2379 char *rf_seq, *ver_attr, *rec;
2382 bt_string2uuid(&uuid, ext->uuid);
2383 sdp_uuid2strn(&uuid, uuid_str, sizeof(uuid_str));
2386 bt_string2uuid(&uuid, ext->service);
2387 sdp_uuid2strn(&uuid, svc_str, sizeof(svc_str));
2389 strncpy(svc_str, uuid_str, sizeof(svc_str));
2393 snprintf(psm, sizeof(psm), "<uint16 value=\"0x%04x\" />",
2399 rf_seq = g_strdup_printf(RFCOMM_SEQ, rfcomm->chan);
2401 rf_seq = g_strdup("");
2404 ver_attr = g_strdup_printf(VERSION_ATTR, uuid_str,
2407 ver_attr = g_strdup("");
2409 rec = g_strdup_printf(GENERIC_RECORD, svc_str, psm, rf_seq, ver_attr,
2418 static struct default_settings {
2422 const char *remote_uuid;
2426 BtIOSecLevel sec_level;
2429 char * (*get_record)(struct ext_profile *ext,
2430 struct ext_io *l2cap,
2431 struct ext_io *rfcomm);
2437 .name = "Serial Port",
2438 .channel = SPP_DEFAULT_CHANNEL,
2440 .get_record = get_spp_record,
2443 .uuid = DUN_GW_UUID,
2444 .name = "Dial-Up Networking",
2445 .channel = DUN_DEFAULT_CHANNEL,
2447 .get_record = get_dun_record,
2450 .uuid = HFP_HS_UUID,
2451 .name = "Hands-Free unit",
2452 .priority = BTD_PROFILE_PRIORITY_HIGH,
2453 .remote_uuid = HFP_AG_UUID,
2454 .channel = HFP_HF_DEFAULT_CHANNEL,
2456 .auto_connect = true,
2457 .get_record = get_hfp_hf_record,
2460 .uuid = HFP_AG_UUID,
2461 .name = "Hands-Free Voice gateway",
2462 .priority = BTD_PROFILE_PRIORITY_HIGH,
2463 .remote_uuid = HFP_HS_UUID,
2464 .channel = HFP_AG_DEFAULT_CHANNEL,
2466 .auto_connect = true,
2467 .get_record = get_hfp_ag_record,
2470 .uuid = HSP_AG_UUID,
2471 .name = "Headset Voice gateway",
2472 .priority = BTD_PROFILE_PRIORITY_HIGH,
2473 .remote_uuid = HSP_HS_UUID,
2474 .channel = HSP_AG_DEFAULT_CHANNEL,
2476 .auto_connect = true,
2477 .get_record = get_hsp_ag_record,
2480 .uuid = OBEX_OPP_UUID,
2481 .name = "Object Push",
2482 .channel = OPP_DEFAULT_CHANNEL,
2483 .psm = BTD_PROFILE_PSM_AUTO,
2484 .mode = BT_IO_MODE_ERTM,
2485 .sec_level = BT_IO_SEC_LOW,
2486 #ifdef __TIZEN_PATCH__
2491 .get_record = get_opp_record,
2492 #ifdef __TIZEN_PATCH__
2498 .uuid = OBEX_FTP_UUID,
2499 .name = "File Transfer",
2500 .channel = FTP_DEFAULT_CHANNEL,
2501 .psm = BTD_PROFILE_PSM_AUTO,
2502 .mode = BT_IO_MODE_ERTM,
2504 .get_record = get_ftp_record,
2507 .uuid = OBEX_SYNC_UUID,
2508 .name = "Synchronization",
2509 .channel = SYNC_DEFAULT_CHANNEL,
2511 .get_record = get_sync_record,
2514 .uuid = OBEX_PSE_UUID,
2515 .name = "Phone Book Access",
2516 .channel = PBAP_DEFAULT_CHANNEL,
2517 .psm = BTD_PROFILE_PSM_AUTO,
2518 .mode = BT_IO_MODE_ERTM,
2520 .get_record = get_pse_record,
2523 .uuid = OBEX_PCE_UUID,
2524 .name = "Phone Book Access Client",
2525 .remote_uuid = OBEX_PSE_UUID,
2527 .get_record = get_pce_record,
2530 .uuid = OBEX_MAS_UUID,
2531 .name = "Message Access",
2532 .channel = MAS_DEFAULT_CHANNEL,
2533 .psm = BTD_PROFILE_PSM_AUTO,
2534 .mode = BT_IO_MODE_ERTM,
2536 .get_record = get_mas_record,
2539 .uuid = OBEX_MNS_UUID,
2540 .name = "Message Notification",
2541 .channel = MNS_DEFAULT_CHANNEL,
2542 .psm = BTD_PROFILE_PSM_AUTO,
2543 .mode = BT_IO_MODE_ERTM,
2545 .get_record = get_mns_record,
2547 #ifdef TIZEN_BT_HID_DEVICE_ENABLE
2550 .name = "HID Device",
2551 .psm = HID_DEVICE_INTR_PSM,
2553 .get_record = get_hid_device_record,
2561 static void ext_set_defaults(struct ext_profile *ext)
2565 ext->mode = BT_IO_MODE_BASIC;
2566 ext->sec_level = BT_IO_SEC_MEDIUM;
2567 ext->authorize = true;
2568 ext->enable_client = true;
2569 ext->enable_server = true;
2570 ext->remote_uuid = NULL;
2572 for (i = 0; i < G_N_ELEMENTS(defaults); i++) {
2573 struct default_settings *settings = &defaults[i];
2574 const char *remote_uuid;
2576 if (strcasecmp(ext->uuid, settings->uuid) != 0)
2579 if (settings->remote_uuid)
2580 remote_uuid = settings->remote_uuid;
2582 remote_uuid = ext->uuid;
2584 ext->remote_uuid = g_strdup(remote_uuid);
2586 if (settings->channel)
2587 ext->local_chan = settings->channel;
2590 ext->local_psm = settings->psm;
2592 if (settings->sec_level)
2593 ext->sec_level = settings->sec_level;
2596 ext->mode = settings->mode;
2598 ext->authorize = settings->authorize;
2600 if (settings->auto_connect)
2601 ext->p.auto_connect = true;
2603 if (settings->priority)
2604 ext->p.priority = settings->priority;
2606 if (settings->get_record)
2607 ext->get_record = settings->get_record;
2609 if (settings->version)
2610 ext->version = settings->version;
2612 if (settings->features)
2613 ext->features = settings->features;
2616 ext->name = g_strdup(settings->name);
2620 static int parse_ext_opt(struct ext_profile *ext, const char *key,
2621 DBusMessageIter *value)
2623 int type = dbus_message_iter_get_arg_type(value);
2628 if (strcasecmp(key, "Name") == 0) {
2629 if (type != DBUS_TYPE_STRING)
2631 dbus_message_iter_get_basic(value, &str);
2633 ext->name = g_strdup(str);
2634 } else if (strcasecmp(key, "AutoConnect") == 0) {
2635 if (type != DBUS_TYPE_BOOLEAN)
2637 dbus_message_iter_get_basic(value, &b);
2638 ext->p.auto_connect = b;
2639 } else if (strcasecmp(key, "PSM") == 0) {
2640 if (type != DBUS_TYPE_UINT16)
2642 dbus_message_iter_get_basic(value, &u16);
2643 ext->local_psm = u16 ? u16 : BTD_PROFILE_PSM_AUTO;
2644 } else if (strcasecmp(key, "Channel") == 0) {
2645 if (type != DBUS_TYPE_UINT16)
2648 dbus_message_iter_get_basic(value, &u16);
2651 ext->local_chan = u16 ? u16 : BTD_PROFILE_CHAN_AUTO;
2652 } else if (strcasecmp(key, "RequireAuthentication") == 0) {
2653 if (type != DBUS_TYPE_BOOLEAN)
2656 dbus_message_iter_get_basic(value, &b);
2657 #ifndef __TIZEN_PATCH__
2659 ext->sec_level = BT_IO_SEC_MEDIUM;
2661 ext->sec_level = BT_IO_SEC_LOW;
2663 #ifdef TIZEN_BT_IO_CAPA_NO_INPUT_OUTPUT
2665 * NoInputOut device should have another authentication method.
2666 * So turn off force authentication setting for that device.
2669 ext->sec_level = BT_IO_SEC_MEDIUM;
2671 ext->sec_level = BT_IO_SEC_LOW;
2673 if (!strcasecmp(ext->uuid, WEARABLE_OLD_SAP_UUID) ||
2674 !strcasecmp(ext->uuid, WEARABLE_NEW_SAP_UUID)) {
2675 DBG("Set SAP UUID's sec_level to HIGH");
2676 ext->sec_level = BT_IO_SEC_HIGH;
2678 ext->sec_level = BT_IO_SEC_MEDIUM;
2680 ext->sec_level = BT_IO_SEC_LOW;
2683 } else if (strcasecmp(key, "RequireAuthorization") == 0) {
2684 if (type != DBUS_TYPE_BOOLEAN)
2686 dbus_message_iter_get_basic(value, &b);
2688 } else if (strcasecmp(key, "Role") == 0) {
2689 if (type != DBUS_TYPE_STRING)
2691 dbus_message_iter_get_basic(value, &str);
2693 ext->role = g_strdup(str);
2695 if (g_str_equal(ext->role, "client")) {
2696 ext->enable_server = false;
2697 ext->enable_client = true;
2698 } else if (g_str_equal(ext->role, "server")) {
2699 ext->enable_server = true;
2700 ext->enable_client = false;
2702 } else if (strcasecmp(key, "ServiceRecord") == 0) {
2703 if (type != DBUS_TYPE_STRING)
2705 dbus_message_iter_get_basic(value, &str);
2706 g_free(ext->record);
2707 ext->record = g_strdup(str);
2708 ext->enable_server = true;
2709 } else if (strcasecmp(key, "Version") == 0) {
2712 if (type != DBUS_TYPE_UINT16)
2715 dbus_message_iter_get_basic(value, &ver);
2717 } else if (strcasecmp(key, "Features") == 0) {
2720 if (type != DBUS_TYPE_UINT16)
2723 dbus_message_iter_get_basic(value, &feat);
2724 ext->features = feat;
2725 } else if (strcasecmp(key, "Service") == 0) {
2726 if (type != DBUS_TYPE_STRING)
2728 dbus_message_iter_get_basic(value, &str);
2730 ext->service = bt_name2string(str);
2736 static void set_service(struct ext_profile *ext)
2738 if (strcasecmp(ext->uuid, HSP_HS_UUID) == 0) {
2739 ext->service = strdup(ext->uuid);
2740 } else if (strcasecmp(ext->uuid, HSP_AG_UUID) == 0) {
2741 ext->service = ext->uuid;
2742 ext->uuid = strdup(HSP_HS_UUID);
2743 } else if (strcasecmp(ext->uuid, HFP_HS_UUID) == 0) {
2744 ext->service = strdup(ext->uuid);
2745 } else if (strcasecmp(ext->uuid, HFP_AG_UUID) == 0) {
2746 ext->service = ext->uuid;
2747 ext->uuid = strdup(HFP_HS_UUID);
2748 } else if (strcasecmp(ext->uuid, OBEX_SYNC_UUID) == 0 ||
2749 strcasecmp(ext->uuid, OBEX_OPP_UUID) == 0 ||
2750 strcasecmp(ext->uuid, OBEX_FTP_UUID) == 0) {
2751 ext->service = strdup(ext->uuid);
2752 } else if (strcasecmp(ext->uuid, OBEX_PSE_UUID) == 0 ||
2753 strcasecmp(ext->uuid, OBEX_PCE_UUID) == 0) {
2754 ext->service = ext->uuid;
2755 ext->uuid = strdup(OBEX_PBAP_UUID);
2756 } else if (strcasecmp(ext->uuid, OBEX_MAS_UUID) == 0 ||
2757 strcasecmp(ext->uuid, OBEX_MNS_UUID) == 0) {
2758 ext->service = ext->uuid;
2759 ext->uuid = strdup(OBEX_MAP_UUID);
2763 #ifdef __TIZEN_PATCH__
2764 static struct ext_profile *create_ext2(const char *owner, const char *path,
2765 const char *uuid, const char *destination, const char *app_path,
2766 DBusMessageIter *opts)
2768 struct btd_profile *p;
2769 struct ext_profile *ext;
2771 ext = g_new0(struct ext_profile, 1);
2773 ext->uuid = bt_name2string(uuid);
2774 if (ext->uuid == NULL) {
2779 ext->owner = g_strdup(destination);
2780 ext->path = g_strdup(app_path);
2781 ext->destination = g_strdup(destination);
2782 ext->app_path = g_strdup(app_path);
2783 DBG("VALUES Dest %s, path2 %s", destination, app_path);
2784 ext_set_defaults(ext);
2786 while (dbus_message_iter_get_arg_type(opts) == DBUS_TYPE_DICT_ENTRY) {
2787 DBusMessageIter value, entry;
2790 dbus_message_iter_recurse(opts, &entry);
2791 dbus_message_iter_get_basic(&entry, &key);
2793 dbus_message_iter_next(&entry);
2794 dbus_message_iter_recurse(&entry, &value);
2796 if (parse_ext_opt(ext, key, &value) < 0)
2797 error("Invalid value for profile option %s", key);
2799 dbus_message_iter_next(opts);
2805 if (ext->enable_server && !(ext->record || ext->get_record))
2806 ext->get_record = get_generic_record;
2809 ext->name = g_strdup_printf("%s%s/%s", owner, path, uuid);
2811 if (!ext->remote_uuid) {
2813 ext->remote_uuid = g_strdup(ext->service);
2815 ext->remote_uuid = g_strdup(ext->uuid);
2820 p->name = ext->name;
2821 p->local_uuid = ext->service ? ext->service : ext->uuid;
2822 p->remote_uuid = ext->remote_uuid;
2824 if (ext->enable_server) {
2825 p->adapter_probe = ext_adapter_probe;
2826 p->adapter_remove = ext_adapter_remove;
2829 if (ext->enable_client) {
2830 p->device_probe = ext_device_probe;
2831 p->device_remove = ext_device_remove;
2832 p->connect = ext_connect_dev;
2833 p->disconnect = ext_disconnect_dev;
2836 DBG("Created \"%s\"", ext->name);
2838 ext_profiles = g_slist_append(ext_profiles, ext);
2840 adapter_foreach(adapter_add_profile, &ext->p);
2846 static struct ext_profile *create_ext(const char *owner, const char *path,
2848 DBusMessageIter *opts)
2850 struct btd_profile *p;
2851 struct ext_profile *ext;
2853 ext = g_new0(struct ext_profile, 1);
2855 ext->uuid = bt_name2string(uuid);
2856 if (ext->uuid == NULL) {
2861 ext->owner = g_strdup(owner);
2862 ext->path = g_strdup(path);
2864 ext_set_defaults(ext);
2866 while (dbus_message_iter_get_arg_type(opts) == DBUS_TYPE_DICT_ENTRY) {
2867 DBusMessageIter value, entry;
2870 dbus_message_iter_recurse(opts, &entry);
2871 dbus_message_iter_get_basic(&entry, &key);
2873 dbus_message_iter_next(&entry);
2874 dbus_message_iter_recurse(&entry, &value);
2876 if (parse_ext_opt(ext, key, &value) < 0)
2877 error("Invalid value for profile option %s", key);
2879 dbus_message_iter_next(opts);
2885 if (ext->enable_server && !(ext->record || ext->get_record))
2886 ext->get_record = get_generic_record;
2889 ext->name = g_strdup_printf("%s%s/%s", owner, path, uuid);
2891 if (!ext->remote_uuid) {
2893 ext->remote_uuid = g_strdup(ext->service);
2895 ext->remote_uuid = g_strdup(ext->uuid);
2900 p->name = ext->name;
2901 p->local_uuid = ext->service ? ext->service : ext->uuid;
2902 p->remote_uuid = ext->remote_uuid;
2905 if (ext->enable_server) {
2906 p->adapter_probe = ext_adapter_probe;
2907 p->adapter_remove = ext_adapter_remove;
2910 if (ext->enable_client) {
2911 p->device_probe = ext_device_probe;
2912 p->device_remove = ext_device_remove;
2913 p->connect = ext_connect_dev;
2914 p->disconnect = ext_disconnect_dev;
2917 DBG("Created \"%s\"", ext->name);
2919 ext_profiles = g_slist_append(ext_profiles, ext);
2921 adapter_foreach(adapter_add_profile, &ext->p);
2926 static void remove_ext(struct ext_profile *ext)
2928 adapter_foreach(adapter_remove_profile, &ext->p);
2930 ext_profiles = g_slist_remove(ext_profiles, ext);
2932 DBG("Removed \"%s\"", ext->name);
2934 ext_remove_records(ext, NULL);
2936 g_slist_free_full(ext->servers, ext_io_destroy);
2937 g_slist_free_full(ext->conns, ext_io_destroy);
2939 g_free(ext->remote_uuid);
2946 g_free(ext->record);
2951 static void ext_exited(DBusConnection *conn, void *user_data)
2953 struct ext_profile *ext = user_data;
2955 DBG("\"%s\" exited", ext->name);
2960 static DBusMessage *register_profile(DBusConnection *conn,
2961 DBusMessage *msg, void *user_data)
2963 const char *path, *sender, *uuid;
2964 DBusMessageIter args, opts;
2965 struct ext_profile *ext;
2967 sender = dbus_message_get_sender(msg);
2969 DBG("sender %s", sender);
2971 dbus_message_iter_init(msg, &args);
2973 dbus_message_iter_get_basic(&args, &path);
2974 dbus_message_iter_next(&args);
2976 ext = find_ext_profile(sender, path);
2978 return btd_error_already_exists(msg);
2980 dbus_message_iter_get_basic(&args, &uuid);
2981 dbus_message_iter_next(&args);
2983 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
2984 return btd_error_invalid_args(msg);
2986 dbus_message_iter_recurse(&args, &opts);
2988 ext = create_ext(sender, path, uuid, &opts);
2990 return btd_error_invalid_args(msg);
2992 ext->id = g_dbus_add_disconnect_watch(conn, sender, ext_exited, ext,
2995 return dbus_message_new_method_return(msg);
2998 static DBusMessage *unregister_profile(DBusConnection *conn,
2999 DBusMessage *msg, void *user_data)
3001 const char *path, *sender;
3002 struct ext_profile *ext;
3004 sender = dbus_message_get_sender(msg);
3006 DBG("sender %s", sender);
3008 if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
3010 return btd_error_invalid_args(msg);
3012 ext = find_ext_profile(sender, path);
3014 return btd_error_does_not_exist(msg);
3016 g_dbus_remove_watch(conn, ext->id);
3019 return dbus_message_new_method_return(msg);
3022 #ifdef __TIZEN_PATCH__
3023 static DBusMessage *register_profile2(DBusConnection *conn,
3024 DBusMessage *msg, void *user_data)
3026 const char *path, *sender, *uuid;
3027 DBusMessageIter args, opts;
3028 struct ext_profile *ext;
3029 const char *destination, *app_path;
3030 sender = dbus_message_get_sender(msg);
3032 DBG("sender %s", sender);
3034 dbus_message_iter_init(msg, &args);
3036 dbus_message_iter_get_basic(&args, &path);
3037 dbus_message_iter_next(&args);
3038 DBG("path %s", path);
3040 DBG("path %s", path);
3041 dbus_message_iter_get_basic(&args, &uuid);
3042 dbus_message_iter_next(&args);
3043 DBG("uuid %s", uuid);
3044 dbus_message_iter_get_basic(&args, &destination);
3045 dbus_message_iter_next(&args);
3046 DBG("destination %s", destination);
3047 dbus_message_iter_get_basic(&args, &app_path);
3048 dbus_message_iter_next(&args);
3049 DBG("path2 %s", app_path);
3050 ext = find_ext_profile(destination, path);
3052 return btd_error_already_exists(msg);
3053 if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY)
3054 return btd_error_invalid_args(msg);
3056 dbus_message_iter_recurse(&args, &opts);
3058 ext = create_ext2(sender, path, uuid, destination, app_path, &opts);
3060 return btd_error_invalid_args(msg);
3062 ext->id = g_dbus_add_disconnect_watch(conn, sender, ext_exited, ext,
3066 return dbus_message_new_method_return(msg);
3070 static const GDBusMethodTable methods[] = {
3071 { GDBUS_METHOD("RegisterProfile",
3072 GDBUS_ARGS({ "profile", "o"}, { "UUID", "s" },
3073 { "options", "a{sv}" }),
3074 NULL, register_profile) },
3075 #ifdef __TIZEN_PATCH__
3076 /* For Dbus Smack devides dbus API, the functionality is same */
3077 { GDBUS_METHOD("RegisterProfile1",
3078 GDBUS_ARGS({ "profile", "o"}, { "UUID", "s" },
3079 { "options", "a{sv}" }),
3080 NULL, register_profile) },
3081 { GDBUS_METHOD("RegisterProfile2",
3082 GDBUS_ARGS({"profile", "o"}, { "UUID", "s" },
3083 {"destination", "s"}, {"path", "s"},
3084 { "options", "a{sv}"}),
3085 NULL, register_profile2) },
3088 { GDBUS_METHOD("UnregisterProfile", GDBUS_ARGS({ "profile", "o" }),
3089 NULL, unregister_profile) },
3093 static struct btd_profile_custom_property *find_custom_prop(const char *uuid,
3098 for (l = custom_props; l; l = l->next) {
3099 struct btd_profile_custom_property *prop = l->data;
3101 if (strcasecmp(prop->uuid, uuid) != 0)
3104 if (g_strcmp0(prop->name, name) == 0)
3111 bool btd_profile_add_custom_prop(const char *uuid, const char *type,
3113 btd_profile_prop_exists exists,
3114 btd_profile_prop_get get,
3117 struct btd_profile_custom_property *prop;
3119 prop = find_custom_prop(uuid, name);
3123 prop = g_new0(struct btd_profile_custom_property, 1);
3125 prop->uuid = strdup(uuid);
3126 prop->type = g_strdup(type);
3127 prop->name = g_strdup(name);
3128 prop->exists = exists;
3130 prop->user_data = user_data;
3132 custom_props = g_slist_append(custom_props, prop);
3137 static void free_property(gpointer data)
3139 struct btd_profile_custom_property *p = data;
3148 bool btd_profile_remove_custom_prop(const char *uuid, const char *name)
3150 struct btd_profile_custom_property *prop;
3152 prop = find_custom_prop(uuid, name);
3156 custom_props = g_slist_remove(custom_props, prop);
3157 free_property(prop);
3162 void btd_profile_init(void)
3164 g_dbus_register_interface(btd_get_dbus_connection(),
3165 "/org/bluez", "org.bluez.ProfileManager1",
3166 methods, NULL, NULL, NULL, NULL);
3169 void btd_profile_cleanup(void)
3171 while (ext_profiles) {
3172 struct ext_profile *ext = ext_profiles->data;
3173 DBusConnection *conn = btd_get_dbus_connection();
3176 DBG("Releasing \"%s\"", ext->name);
3178 g_slist_free_full(ext->conns, ext_io_destroy);
3181 #ifdef __TIZEN_PATCH__
3182 if (ext->destination == NULL) {
3183 msg = dbus_message_new_method_call(ext->owner,
3185 "org.bluez.Profile1",
3188 g_dbus_send_message(conn, msg);
3191 msg = dbus_message_new_method_call(ext->owner, ext->path,
3192 "org.bluez.Profile1",
3195 g_dbus_send_message(conn, msg);
3198 g_dbus_remove_watch(conn, ext->id);
3203 g_slist_free_full(custom_props, free_property);
3204 custom_props = NULL;
3206 g_dbus_unregister_interface(btd_get_dbus_connection(),
3207 "/org/bluez", "org.bluez.ProfileManager1");